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 7bbdd07853b..5a23faff7d7 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 @@ -588,7 +588,10 @@ public class ScryfallImageSupportCards { add("FIN"); // Final Fantasy add("FIC"); // Final Fantasy Commander add("FCA"); // Final Fantasy: Through the Ages + add("EOE"); // Edge of Eternities + add("EOC"); // Edge of Eternities Commander add("SPE"); // Marvel's Spider-Man Eternal + add("TLA"); // Avatar: The Last Airbender // Custom sets using Scryfall images - must provide a direct link for each card in directDownloadLinks add("CALC"); // Custom Alchemized versions of existing cards 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 19aecedcf0e..49894969311 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 @@ -352,6 +352,9 @@ public class ScryfallImageSupportTokens { put("ELD/Rat", "https://api.scryfall.com/cards/teld/6/en?format=image"); put("ELD/Wolf", "https://api.scryfall.com/cards/teld/14/en?format=image"); + // UND + put("UND/Goblin", "https://api.scryfall.com/cards/tund/2?format=image"); + // THB put("THB/Elemental", "https://api.scryfall.com/cards/tthb/8/en?format=image"); put("THB/Goat", "https://api.scryfall.com/cards/tthb/1/en?format=image"); @@ -1843,6 +1846,12 @@ public class ScryfallImageSupportTokens { put("40K/Tyranid Gargoyle", "https://api.scryfall.com/cards/t40k/9/en?format=image"); put("40K/Tyranid Warrior", "https://api.scryfall.com/cards/t40k/19/en?format=image"); + // UNF + put("UNF/Clown Robot/1", "https://api.scryfall.com/cards/tunf/2?format=image"); + put("UNF/Clown Robot/2", "https://api.scryfall.com/cards/tunf/3?format=image"); + put("UNF/Storm Crow", "https://api.scryfall.com/cards/tunf/5?format=image"); + put("UNF/Squirrel", "https://api.scryfall.com/cards/tunf/8?format=image"); + // BRO put("BRO/Bear", "https://api.scryfall.com/cards/tbro/2/en?format=image"); put("BRO/Construct/1", "https://api.scryfall.com/cards/tbro/5/en?format=image"); @@ -2026,6 +2035,7 @@ public class ScryfallImageSupportTokens { // DIS put("DIS/Emblem Momir", "https://api.scryfall.com/cards/pmoa/61/en?format=image"); + put("DIS/Elemental", "https://api.scryfall.com/cards/togw/9?format=image"); // MUL put("MUL/Elemental", "https://api.scryfall.com/cards/tmul/2/en?format=image"); @@ -2182,6 +2192,7 @@ public class ScryfallImageSupportTokens { // WHO put("WHO/Alien", "https://api.scryfall.com/cards/twho/2?format=image"); + put("WHO/Alien Angel", "https://api.scryfall.com/cards/twho/11?format=image"); put("WHO/Alien Insect", "https://api.scryfall.com/cards/twho/19/en?format=image"); put("WHO/Alien Rhino", "https://api.scryfall.com/cards/twho/3/en?format=image"); put("WHO/Alien Salamander", "https://api.scryfall.com/cards/twho/16?format=image"); @@ -2536,6 +2547,7 @@ public class ScryfallImageSupportTokens { put("DSK/Everywhere", "https://api.scryfall.com/cards/tdsk/16?format=image"); put("DSK/Glimmer", "https://api.scryfall.com/cards/tdsk/4?format=image"); put("DSK/Gremlin", "https://api.scryfall.com/cards/tdsk/11?format=image"); + put("DSK/Horror", "https://api.scryfall.com/cards/tdsk/10?format=image"); put("DSK/Insect/1", "https://api.scryfall.com/cards/tdsk/13?format=image"); put("DSK/Insect/2", "https://api.scryfall.com/cards/tdsk/5?format=image"); put("DSK/Primo, the Indivisible", "https://api.scryfall.com/cards/tdsk/14?format=image"); @@ -2698,7 +2710,8 @@ public class ScryfallImageSupportTokens { put("TDC/Gold", "https://api.scryfall.com/cards/ttdc/29/en?format=image"); put("TDC/Human", "https://api.scryfall.com/cards/ttdc/5/en?format=image"); put("TDC/Inkling", "https://api.scryfall.com/cards/ttdc/28?format=image"); - put("TDC/Insect", "https://api.scryfall.com/cards/ttdc/22/en?format=image"); + put("TDC/Insect/1", "https://api.scryfall.com/cards/ttdc/22/en?format=image"); + put("TDC/Insect/2", "https://api.scryfall.com/cards/ttdc/23/en?format=image"); put("TDC/Karox Bladewing", "https://api.scryfall.com/cards/ttdc/19?format=image"); put("TDC/Myr", "https://api.scryfall.com/cards/ttdc/30/en?format=image"); put("TDC/Plant", "https://api.scryfall.com/cards/ttdc/24/en?format=image"); @@ -2710,6 +2723,7 @@ public class ScryfallImageSupportTokens { put("TDC/Spider", "https://api.scryfall.com/cards/ttdc/25?format=image"); put("TDC/Spirit", "https://api.scryfall.com/cards/ttdc/6/en?format=image"); put("TDC/Thopter", "https://api.scryfall.com/cards/ttdc/33/en?format=image"); + put("TDC/Wall", "https://api.scryfall.com/cards/ttdc/7/en?format=image"); // ACR put("ACR/Assassin", "https://api.scryfall.com/cards/tacr/4?format=image"); @@ -2723,7 +2737,51 @@ public class ScryfallImageSupportTokens { put("DD2/Elemental Shaman", "https://api.scryfall.com/cards/tdd2/1?format=image"); // FIN + put("FIN/Hero/1", "https://api.scryfall.com/cards/tfin/2/en?format=image"); + put("FIN/Hero/2", "https://api.scryfall.com/cards/tfin/3/en?format=image"); + put("FIN/Hero/3", "https://api.scryfall.com/cards/tfin/4/en?format=image"); + put("FIN/Hero/4", "https://api.scryfall.com/cards/tfin/5/en?format=image"); + put("FIN/Hero/5", "https://api.scryfall.com/cards/tfin/6/en?format=image"); + put("FIN/Hero/6", "https://api.scryfall.com/cards/tfin/7/en?format=image"); + put("FIN/Hero/7", "https://api.scryfall.com/cards/tfin/8/en?format=image"); + put("FIN/Hero/8", "https://api.scryfall.com/cards/tfin/9/en?format=image"); + put("FIN/Hero/9", "https://api.scryfall.com/cards/tfin/26/en?format=image"); + put("FIN/Hero/10", "https://api.scryfall.com/cards/tfin/27/en?format=image"); + put("FIN/Hero/11", "https://api.scryfall.com/cards/tfin/28/en?format=image"); + put("FIN/Hero/12", "https://api.scryfall.com/cards/tfin/29/en?format=image"); + put("FIN/Hero/13", "https://api.scryfall.com/cards/tfin/30/en?format=image"); + put("FIN/Hero/14", "https://api.scryfall.com/cards/tfin/31/en?format=image"); + put("FIN/Hero/15", "https://api.scryfall.com/cards/tfin/32/en?format=image"); + put("FIN/Hero/16", "https://api.scryfall.com/cards/tfin/33/en?format=image"); + put("FIN/Knight", "https://api.scryfall.com/cards/tfin/10/en?format=image"); + put("FIN/Moogle/1", "https://api.scryfall.com/cards/tfin/11/en?format=image"); + put("FIN/Moogle/2", "https://api.scryfall.com/cards/tfin/34/en?format=image"); + put("FIN/Robot", "https://api.scryfall.com/cards/tfin/12/en?format=image"); + put("FIN/Horror", "https://api.scryfall.com/cards/tfin/13/en?format=image"); + put("FIN/Wizard/1", "https://api.scryfall.com/cards/tfin/14/en?format=image"); + put("FIN/Wizard/2", "https://api.scryfall.com/cards/tfin/15/en?format=image"); + put("FIN/Wizard/3", "https://api.scryfall.com/cards/tfin/35/en?format=image"); + put("FIN/Bird/1", "https://api.scryfall.com/cards/tfin/16/en?format=image"); + put("FIN/Bird/2", "https://api.scryfall.com/cards/tfin/17/en?format=image"); + put("FIN/Frog", "https://api.scryfall.com/cards/tfin/18/en?format=image"); + put("FIN/Angelo", "https://api.scryfall.com/cards/tfin/19/en?format=image"); + put("FIN/Darkstar", "https://api.scryfall.com/cards/tfin/20/en?format=image"); + put("FIN/Elemental", "https://api.scryfall.com/cards/tfin/21/en?format=image"); put("FIN/Food", "https://api.scryfall.com/cards/tfin/22?format=image"); + put("FIN/Treasure/1", "https://api.scryfall.com/cards/tfin/23/en?format=image"); + put("FIN/Treasure/2", "https://api.scryfall.com/cards/tfin/36/en?format=image"); + put("FIN/Emblem Sephiroth", "https://api.scryfall.com/cards/tfin/24/en?format=image"); + + // FIC + put("FIC/Human Soldier", "https://api.scryfall.com/cards/tfic/1/en?format=image"); + put("FIC/Soldier", "https://api.scryfall.com/cards/tfic/2/en?format=image"); + put("FIC/Spirit", "https://api.scryfall.com/cards/tfic/3/en?format=image"); + put("FIC/Bird", "https://api.scryfall.com/cards/tfic/4/en?format=image"); + put("FIC/Squid", "https://api.scryfall.com/cards/tfic/5/en?format=image"); + put("FIC/Zombie", "https://api.scryfall.com/cards/tfic/6/en?format=image"); + put("FIC/Rebel", "https://api.scryfall.com/cards/tfic/7/en?format=image"); + put("FIC/The Blackjack", "https://api.scryfall.com/cards/tfic/8/en?format=image"); + put("FIC/Clue", "https://api.scryfall.com/cards/tfic/9/en?format=image"); // JVC put("JVC/Elemental Shaman", "https://api.scryfall.com/cards/tjvc/4?format=image"); @@ -2756,6 +2814,7 @@ public class ScryfallImageSupportTokens { // UGL put("UGL/Goblin", "https://api.scryfall.com/cards/tugl/4?format=image"); put("UGL/Pegasus", "https://api.scryfall.com/cards/tugl/1?format=image"); + put("UGL/Rabid Sheep", "https://api.scryfall.com/cards/tugl/5?format=image"); put("UGL/Soldier", "https://api.scryfall.com/cards/tugl/2?format=image"); put("UGL/Squirrel", "https://api.scryfall.com/cards/tugl/6?format=image"); put("UGL/Zombie", "https://api.scryfall.com/cards/tugl/3?format=image"); diff --git a/Mage.Common/src/main/java/mage/utils/testers/AmountTestableResult.java b/Mage.Common/src/main/java/mage/utils/testers/AmountTestableResult.java new file mode 100644 index 00000000000..96b3f1892af --- /dev/null +++ b/Mage.Common/src/main/java/mage/utils/testers/AmountTestableResult.java @@ -0,0 +1,29 @@ +package mage.utils.testers; + +import java.util.List; + +/** + * Part of testable game dialogs + * + * @author JayDi85 + */ +public class AmountTestableResult extends BaseTestableResult { + + int amount = 0; + + public void onFinish(String resDebugSource, boolean status, List info, int amount) { + this.onFinish(resDebugSource, status, info); + this.amount = amount; + } + + @Override + public String getResAssert() { + return null; // TODO: implement + } + + @Override + public void onClear() { + super.onClear(); + this.amount = 0; + } +} diff --git a/Mage.Common/src/main/java/mage/utils/testers/AnnounceXTestableDialog.java b/Mage.Common/src/main/java/mage/utils/testers/AnnounceXTestableDialog.java index bd346448472..558deedab8d 100644 --- a/Mage.Common/src/main/java/mage/utils/testers/AnnounceXTestableDialog.java +++ b/Mage.Common/src/main/java/mage/utils/testers/AnnounceXTestableDialog.java @@ -3,6 +3,7 @@ package mage.utils.testers; import mage.abilities.Ability; import mage.game.Game; import mage.players.Player; +import mage.util.DebugUtil; import java.util.ArrayList; import java.util.Arrays; @@ -25,7 +26,8 @@ class AnnounceXTestableDialog extends BaseTestableDialog { public AnnounceXTestableDialog(boolean isYou, boolean isMana, int min, int max) { super(String.format("player.announceX(%s)", isYou ? "you" : "AI"), - String.format("%s from %d to %d", isMana ? "mana" : "cost", min, max), ""); + String.format("%s from %d to %d", isMana ? "mana" : "cost", min, max), "", + new AmountTestableResult()); this.isYou = isYou; this.isMana = isMana; this.min = min; @@ -33,14 +35,15 @@ class AnnounceXTestableDialog extends BaseTestableDialog { } @Override - public List showDialog(Player player, Ability source, Game game, Player opponent) { + public void showDialog(Player player, Ability source, Game game, Player opponent) { Player choosingPlayer = this.isYou ? player : opponent; String message = "message with html"; - int chooseRes; - chooseRes = choosingPlayer.announceX(this.min, this.max, message, game, source, this.isMana); - List result = new ArrayList<>(); - result.add(getGroup() + " - " + this.getName() + " selected " + chooseRes); - return result; + String chooseDebugSource = DebugUtil.getMethodNameWithSource(0, "class"); + int chooseRes = choosingPlayer.announceX(this.min, this.max, message, game, source, this.isMana); + List res = new ArrayList<>(); + res.add(getGroup() + " - " + this.getName() + " selected " + chooseRes); + + ((AmountTestableResult) this.getResult()).onFinish(chooseDebugSource, true, res, chooseRes); } static public void register(TestableDialogsRunner runner) { diff --git a/Mage.Common/src/main/java/mage/utils/testers/BaseTestableDialog.java b/Mage.Common/src/main/java/mage/utils/testers/BaseTestableDialog.java index 0ee78b67e51..2ae8d4cae79 100644 --- a/Mage.Common/src/main/java/mage/utils/testers/BaseTestableDialog.java +++ b/Mage.Common/src/main/java/mage/utils/testers/BaseTestableDialog.java @@ -1,11 +1,12 @@ package mage.utils.testers; -import mage.constants.SubType; -import mage.filter.common.FilterCreaturePermanent; +import mage.constants.ComparisonType; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.game.Game; import mage.players.Player; import mage.target.Target; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetPermanentOrPlayer; /** @@ -15,14 +16,27 @@ import mage.target.common.TargetPermanentOrPlayer; */ abstract class BaseTestableDialog implements TestableDialog { + private Integer regNumber; // dialog number in runner (use it to find results and debugging) private final String group; private final String name; private final String description; + private final TestableResult result; - public BaseTestableDialog(String group, String name, String description) { + public BaseTestableDialog(String group, String name, String description, TestableResult result) { this.group = group; this.name = name; this.description = description; + this.result = result; + } + + @Override + public void setRegNumber(Integer regNumber) { + this.regNumber = regNumber; + } + + @Override + public Integer getRegNumber() { + return this.regNumber; } @Override @@ -41,13 +55,23 @@ abstract class BaseTestableDialog implements TestableDialog { } @Override - final public void showResult(Player player, Game game, String result) { + public void prepare() { + this.result.onClear(); + } + + @Override + final public void showResult(Player player, Game game) { // show message with result - game.informPlayer(player, result); + game.informPlayer(player, String.join("
", getResult().getResDetails())); // reset game and gui (in most use cases it must return to player's priority) game.firePriorityEvent(player.getId()); } + @Override + public TestableResult getResult() { + return this.result; + } + static Target createAnyTarget(int min, int max) { return createAnyTarget(min, max, false); } @@ -56,19 +80,18 @@ abstract class BaseTestableDialog implements TestableDialog { return new TargetPermanentOrPlayer(min, max).withNotTarget(notTarget); } - static Target createCreatureTarget(int min, int max) { - return createCreatureTarget(min, max, false); - } + private static final FilterPermanent impossibleFilter = new FilterPermanent(); - private static Target createCreatureTarget(int min, int max, boolean notTarget) { - return new TargetCreaturePermanent(min, max).withNotTarget(notTarget); + static { + impossibleFilter.add(new ManaValuePredicate(ComparisonType.OR_LESS, -1)); } static Target createImpossibleTarget(int min, int max) { - return createImpossibleTarget(min, max, false); + return new TargetPermanent(min, max, impossibleFilter); } - private static Target createImpossibleTarget(int min, int max, boolean notTarget) { - return new TargetCreaturePermanent(min, max, new FilterCreaturePermanent(SubType.TROOPER, "rare type"), notTarget); + @Override + public String toString() { + return this.getGroup() + " - " + this.getName() + " - " + this.getDescription(); } } diff --git a/Mage.Common/src/main/java/mage/utils/testers/BaseTestableResult.java b/Mage.Common/src/main/java/mage/utils/testers/BaseTestableResult.java new file mode 100644 index 00000000000..6b3856e6f95 --- /dev/null +++ b/Mage.Common/src/main/java/mage/utils/testers/BaseTestableResult.java @@ -0,0 +1,57 @@ +package mage.utils.testers; + +import java.util.ArrayList; +import java.util.List; + +/** + * Part of testable game dialogs + * + * @author JayDi85 + */ +public class BaseTestableResult implements TestableResult { + + boolean isFinished = false; + String resDebugSource = ""; // source code line to find starting place to debug + boolean resStatus = false; + List resInfo = new ArrayList<>(); + + @Override + public String getResDebugSource() { + return this.resDebugSource; + } + + @Override + public boolean getResStatus() { + return this.resStatus; + } + + @Override + public List getResDetails() { + return this.resInfo; + } + + @Override + public String getResAssert() { + return null; // TODO: implement + } + + @Override + public void onFinish(String resDebugSource, boolean resStatus, List resDetails) { + this.isFinished = true; + this.resDebugSource = resDebugSource; + this.resStatus = resStatus; + this.resInfo = resDetails; + } + + @Override + public boolean isFinished() { + return this.isFinished; + } + + @Override + public void onClear() { + this.isFinished = false; + this.resStatus = false; + this.resInfo.clear(); + } +} diff --git a/Mage.Common/src/main/java/mage/utils/testers/ChoiceTestableResult.java b/Mage.Common/src/main/java/mage/utils/testers/ChoiceTestableResult.java new file mode 100644 index 00000000000..acf520e29e2 --- /dev/null +++ b/Mage.Common/src/main/java/mage/utils/testers/ChoiceTestableResult.java @@ -0,0 +1,29 @@ +package mage.utils.testers; + +import java.util.List; + +/** + * Part of testable game dialogs + * + * @author JayDi85 + */ +public class ChoiceTestableResult extends BaseTestableResult { + + String choice = null; + + public void onFinish(String resDebugSource, boolean status, List info, String choice) { + this.onFinish(resDebugSource, status, info); + this.choice = choice; + } + + @Override + public String getResAssert() { + return null; // TODO: implement + } + + @Override + public void onClear() { + super.onClear(); + this.choice = null; + } +} diff --git a/Mage.Common/src/main/java/mage/utils/testers/ChooseAmountTestableDialog.java b/Mage.Common/src/main/java/mage/utils/testers/ChooseAmountTestableDialog.java index 6a7847ec4fc..37bb11eb381 100644 --- a/Mage.Common/src/main/java/mage/utils/testers/ChooseAmountTestableDialog.java +++ b/Mage.Common/src/main/java/mage/utils/testers/ChooseAmountTestableDialog.java @@ -7,6 +7,7 @@ import mage.players.Player; import mage.target.TargetAmount; import mage.target.Targets; import mage.target.common.TargetAnyTargetAmount; +import mage.util.DebugUtil; import java.util.ArrayList; import java.util.Arrays; @@ -32,27 +33,39 @@ class ChooseAmountTestableDialog extends BaseTestableDialog { public ChooseAmountTestableDialog(boolean isYou, String name, int distributeAmount, int targetsMin, int targetsMax) { super(String.format("player.chooseTarget(%s, amount)", isYou ? "you" : "AI"), name, - String.format("%d between %d-%d targets", distributeAmount, targetsMin, targetsMax)); + String.format("%d between %d-%d targets", distributeAmount, targetsMin, targetsMax), + new TargetTestableResult()); this.isYou = isYou; this.distributeAmount = distributeAmount; this.targetsMin = targetsMin; this.targetsMax = targetsMax; } + private ChooseAmountTestableDialog aiMustChoose(boolean resStatus, int targetsCount) { + // TODO: AI use default distribution, improve someday + TargetTestableResult res = ((TargetTestableResult) this.getResult()); + res.aiAssertEnabled = true; + res.aiAssertResStatus = resStatus; + res.aiAssertTargetsCount = targetsCount; + return this; + } + @Override - public List showDialog(Player player, Ability source, Game game, Player opponent) { + public void showDialog(Player player, Ability source, Game game, Player opponent) { TargetAmount choosingTarget = new TargetAnyTargetAmount(this.distributeAmount, this.targetsMin, this.targetsMax); Player choosingPlayer = this.isYou ? player : opponent; // TODO: add "damage" word in ability text, so chooseTargetAmount an show diff dialog (due inner logic - distribute damage or 1/1) + String chooseDebugSource = DebugUtil.getMethodNameWithSource(0, "class"); boolean chooseRes = choosingPlayer.chooseTargetAmount(Outcome.Benefit, choosingTarget, source, game); - List result = new ArrayList<>(); + List res = new ArrayList<>(); if (chooseRes) { - Targets.printDebugTargets(getGroup() + " - " + this.getName() + " - " + "TRUE", new Targets(choosingTarget), source, game, result); + Targets.printDebugTargets(getGroup() + " - " + this.getName() + " - " + "TRUE", new Targets(choosingTarget), source, game, res); } else { - Targets.printDebugTargets(getGroup() + " - " + this.getName() + " - " + "FALSE", new Targets(choosingTarget), source, game, result); + Targets.printDebugTargets(getGroup() + " - " + this.getName() + " - " + "FALSE", new Targets(choosingTarget), source, game, res); } - return result; + + ((TargetTestableResult) this.getResult()).onFinish(chooseDebugSource, chooseRes, res, choosingTarget); } static public void register(TestableDialogsRunner runner) { @@ -61,53 +74,55 @@ class ChooseAmountTestableDialog extends BaseTestableDialog { List isYous = Arrays.asList(false, true); + // current AI will choose 1 target and assign all values to it (except with outcome.Damage) + // TODO: add use cases for damage effects? for (boolean isYou : isYous) { // up to - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 0, 0, 0)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 0, 0, 1)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 0, 0, 3)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 0, 0, 5)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 0, 0, 0).aiMustChoose(false, 0)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 0, 0, 1).aiMustChoose(false, 0)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 0, 0, 3).aiMustChoose(false, 0)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 0, 0, 5).aiMustChoose(false, 0)); // - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to, invalid", 1, 0, 0)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 1, 0, 1)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 1, 0, 3)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 1, 0, 5)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to, invalid", 1, 0, 0).aiMustChoose(false, 0)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 1, 0, 1).aiMustChoose(true, 1)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 1, 0, 3).aiMustChoose(true, 1)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 1, 0, 5).aiMustChoose(true, 1)); // - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to, invalid", 2, 0, 0)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 2, 0, 1)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 2, 0, 3)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 2, 0, 5)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to, invalid", 2, 0, 0).aiMustChoose(false, 0)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 2, 0, 1).aiMustChoose(true, 1)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 2, 0, 3).aiMustChoose(true, 1)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 2, 0, 5).aiMustChoose(true, 1)); // - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to, invalid", 3, 0, 0)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 3, 0, 1)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 3, 0, 3)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 3, 0, 5)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to, invalid", 3, 0, 0).aiMustChoose(false, 0)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 3, 0, 1).aiMustChoose(true, 1)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 3, 0, 3).aiMustChoose(true, 1)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 3, 0, 5).aiMustChoose(true, 1)); // - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to, invalid", 5, 0, 0)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 5, 0, 1)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 5, 0, 3)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 5, 0, 5)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to, invalid", 5, 0, 0).aiMustChoose(false, 0)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 5, 0, 1).aiMustChoose(true, 1)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 5, 0, 3).aiMustChoose(true, 1)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "up to", 5, 0, 5).aiMustChoose(true, 1)); // need target - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 0, 1, 1)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 0, 1, 3)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 0, 1, 5)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 0, 1, 1).aiMustChoose(false, 0)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 0, 1, 3).aiMustChoose(false, 0)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 0, 1, 5).aiMustChoose(false, 0)); // - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 1, 1, 1)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 1, 1, 3)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 1, 1, 5)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 1, 1, 1).aiMustChoose(true, 1)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 1, 1, 3).aiMustChoose(true, 1)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 1, 1, 5).aiMustChoose(true, 1)); // - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 2, 1, 1)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 2, 1, 3)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 2, 1, 5)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 2, 1, 1).aiMustChoose(true, 1)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 2, 1, 3).aiMustChoose(true, 1)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 2, 1, 5).aiMustChoose(true, 1)); // - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 3, 1, 1)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 3, 1, 3)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 3, 1, 5)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 3, 1, 1).aiMustChoose(true, 1)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 3, 1, 3).aiMustChoose(true, 1)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 3, 1, 5).aiMustChoose(true, 1)); // - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 5, 1, 1)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 5, 1, 3)); - runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 5, 1, 5)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 5, 1, 1).aiMustChoose(true, 1)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 5, 1, 3).aiMustChoose(true, 1)); + runner.registerDialog(new ChooseAmountTestableDialog(isYou, "need", 5, 1, 5).aiMustChoose(true, 1)); } } } diff --git a/Mage.Common/src/main/java/mage/utils/testers/ChooseCardsTestableDialog.java b/Mage.Common/src/main/java/mage/utils/testers/ChooseCardsTestableDialog.java index 8837d9b92ce..e0dbc8e45dd 100644 --- a/Mage.Common/src/main/java/mage/utils/testers/ChooseCardsTestableDialog.java +++ b/Mage.Common/src/main/java/mage/utils/testers/ChooseCardsTestableDialog.java @@ -13,6 +13,7 @@ import mage.players.Player; import mage.target.TargetCard; import mage.target.Targets; import mage.target.common.TargetCardInHand; +import mage.util.DebugUtil; import java.util.ArrayList; import java.util.Arrays; @@ -36,16 +37,17 @@ class ChooseCardsTestableDialog extends BaseTestableDialog { public ChooseCardsTestableDialog(boolean isTargetChoice, boolean notTarget, boolean isYou, String name, TargetCard target) { super(String.format("%s(%s, %s, cards)", - isTargetChoice ? "player.chooseTarget" : "player.choose", - isYou ? "you" : "AI", - notTarget ? "not target" : "target"), name, target.toString()); + isTargetChoice ? "player.chooseTarget" : "player.choose", + isYou ? "you" : "AI", + notTarget ? "not target" : "target"), name, target.toString(), + new TargetTestableResult()); this.isTargetChoice = isTargetChoice; this.target = target.withNotTarget(notTarget); this.isYou = isYou; } @Override - public List showDialog(Player player, Ability source, Game game, Player opponent) { + public void showDialog(Player player, Ability source, Game game, Player opponent) { TargetCard choosingTarget = this.target.copy(); Player choosingPlayer = this.isYou ? player : opponent; @@ -56,19 +58,23 @@ class ChooseCardsTestableDialog extends BaseTestableDialog { Cards choosingCards = new CardsImpl(all.stream().limit(100).collect(Collectors.toList())); boolean chooseRes; + String chooseDebugSource; if (this.isTargetChoice) { + chooseDebugSource = DebugUtil.getMethodNameWithSource(0, "class"); chooseRes = choosingPlayer.chooseTarget(Outcome.Benefit, choosingCards, choosingTarget, source, game); } else { + chooseDebugSource = DebugUtil.getMethodNameWithSource(0, "class"); chooseRes = choosingPlayer.choose(Outcome.Benefit, choosingCards, choosingTarget, source, game); } - List result = new ArrayList<>(); + List res = new ArrayList<>(); if (chooseRes) { - Targets.printDebugTargets(getGroup() + " - " + this.getName() + " - " + "TRUE", new Targets(choosingTarget), source, game, result); + Targets.printDebugTargets(getGroup() + " - " + this.getName() + " - " + "TRUE", new Targets(choosingTarget), source, game, res); } else { - Targets.printDebugTargets(getGroup() + " - " + this.getName() + " - " + "FALSE", new Targets(choosingTarget), source, game, result); + Targets.printDebugTargets(getGroup() + " - " + this.getName() + " - " + "FALSE", new Targets(choosingTarget), source, game, res); } - return result; + + ((TargetTestableResult) this.getResult()).onFinish(chooseDebugSource, chooseRes, res, choosingTarget); } static public void register(TestableDialogsRunner runner) { diff --git a/Mage.Common/src/main/java/mage/utils/testers/ChooseChoiceTestableDialog.java b/Mage.Common/src/main/java/mage/utils/testers/ChooseChoiceTestableDialog.java index 7e90c6cb124..e87451a54ae 100644 --- a/Mage.Common/src/main/java/mage/utils/testers/ChooseChoiceTestableDialog.java +++ b/Mage.Common/src/main/java/mage/utils/testers/ChooseChoiceTestableDialog.java @@ -5,6 +5,7 @@ import mage.choices.*; import mage.constants.Outcome; import mage.game.Game; import mage.players.Player; +import mage.util.DebugUtil; import java.util.ArrayList; import java.util.Arrays; @@ -24,28 +25,36 @@ class ChooseChoiceTestableDialog extends BaseTestableDialog { Choice choice; public ChooseChoiceTestableDialog(boolean isYou, String name, Choice choice) { - super(String.format("player.choose(%s, choice)", isYou ? "you" : "AI"), name, choice.getClass().getSimpleName()); + super(String.format("player.choose(%s, choice)", isYou ? "you" : "AI"), + name, + choice.getClass().getSimpleName(), + new ChoiceTestableResult() + ); this.isYou = isYou; this.choice = choice; } @Override - public List showDialog(Player player, Ability source, Game game, Player opponent) { + public void showDialog(Player player, Ability source, Game game, Player opponent) { Player choosingPlayer = this.isYou ? player : opponent; Choice dialog = this.choice.copy(); + String chooseDebugSource = DebugUtil.getMethodNameWithSource(0, "class"); boolean chooseRes = choosingPlayer.choose(Outcome.Benefit, dialog, game); - List result = new ArrayList<>(); - result.add(getGroup() + " - " + this.getName() + " - " + (chooseRes ? "TRUE" : "FALSE")); - result.add(""); + List res = new ArrayList<>(); + res.add(getGroup() + " - " + this.getName() + " - " + (chooseRes ? "TRUE" : "FALSE")); + res.add(""); + String choice; if (dialog.isKeyChoice()) { String key = dialog.getChoiceKey(); - result.add(String.format("* selected key: %s (%s)", key, dialog.getKeyChoices().getOrDefault(key, null))); + choice = dialog.getKeyChoices().getOrDefault(key, null); + res.add(String.format("* selected key: %s (%s)", key, choice)); } else { - result.add(String.format("* selected value: %s", dialog.getChoice())); + choice = dialog.getChoice(); + res.add(String.format("* selected value: %s", choice)); } - return result; + ((ChoiceTestableResult) this.getResult()).onFinish(chooseDebugSource, chooseRes, res, choice); } static public void register(TestableDialogsRunner runner) { diff --git a/Mage.Common/src/main/java/mage/utils/testers/ChoosePileTestableDialog.java b/Mage.Common/src/main/java/mage/utils/testers/ChoosePileTestableDialog.java index 68bc9bbb265..f25b2fae670 100644 --- a/Mage.Common/src/main/java/mage/utils/testers/ChoosePileTestableDialog.java +++ b/Mage.Common/src/main/java/mage/utils/testers/ChoosePileTestableDialog.java @@ -6,6 +6,7 @@ import mage.constants.Outcome; import mage.game.Game; import mage.players.Player; import mage.util.CardUtil; +import mage.util.DebugUtil; import java.util.ArrayList; import java.util.Arrays; @@ -28,14 +29,18 @@ class ChoosePileTestableDialog extends BaseTestableDialog { int pileSize2; public ChoosePileTestableDialog(boolean isYou, int pileSize1, int pileSize2) { - super(String.format("player.choosePile(%s)", isYou ? "you" : "AI"), "pile sizes: " + pileSize1 + " and " + pileSize2, ""); + super(String.format("player.choosePile(%s)", isYou ? "you" : "AI"), + "pile sizes: " + pileSize1 + " and " + pileSize2, + "", + new BaseTestableResult() + ); this.isYou = isYou; this.pileSize1 = pileSize1; this.pileSize2 = pileSize2; } @Override - public List showDialog(Player player, Ability source, Game game, Player opponent) { + public void showDialog(Player player, Ability source, Game game, Player opponent) { // TODO: it's ok to show broken title - must add html support in windows's title someday String mainMessage = "main message with html" + CardUtil.getSourceLogName(game, source); @@ -47,11 +52,13 @@ class ChoosePileTestableDialog extends BaseTestableDialog { List pile2 = all.stream().limit(this.pileSize2).collect(Collectors.toList()); Player choosingPlayer = this.isYou ? player : opponent; + String chooseDebugSource = DebugUtil.getMethodNameWithSource(0, "class"); boolean chooseRes = choosingPlayer.choosePile(Outcome.Benefit, mainMessage, pile1, pile2, game); - List result = new ArrayList<>(); - result.add(getGroup() + " - " + this.getName() + " - " + (chooseRes ? "TRUE" : "FALSE")); - result.add(" * selected pile: " + (chooseRes ? "pile 1" : "pile 2")); - return result; + List res = new ArrayList<>(); + res.add(getGroup() + " - " + this.getName() + " - " + (chooseRes ? "TRUE" : "FALSE")); + res.add(" * selected pile: " + (chooseRes ? "pile 1" : "pile 2")); + + this.getResult().onFinish(chooseDebugSource, chooseRes, res); } static public void register(TestableDialogsRunner runner) { diff --git a/Mage.Common/src/main/java/mage/utils/testers/ChooseTargetTestableDialog.java b/Mage.Common/src/main/java/mage/utils/testers/ChooseTargetTestableDialog.java index 65284618774..017aa055b27 100644 --- a/Mage.Common/src/main/java/mage/utils/testers/ChooseTargetTestableDialog.java +++ b/Mage.Common/src/main/java/mage/utils/testers/ChooseTargetTestableDialog.java @@ -6,6 +6,7 @@ import mage.game.Game; import mage.players.Player; import mage.target.Target; import mage.target.Targets; +import mage.util.DebugUtil; import java.util.ArrayList; import java.util.Arrays; @@ -31,10 +32,14 @@ class ChooseTargetTestableDialog extends BaseTestableDialog { public ChooseTargetTestableDialog(boolean isPlayerChoice, boolean isTargetChoice, boolean notTarget, boolean isYou, String name, Target target) { super(String.format("%s%s(%s, %s)", - isPlayerChoice ? "player.choose" : "target.choose", - isTargetChoice ? "Target" : "", // chooseTarget or choose - isYou ? "you" : "AI", - notTarget ? "not target" : "target"), name, target.toString()); + isPlayerChoice ? "player.choose" : "target.choose", + isTargetChoice ? "Target" : "", // chooseTarget or choose + isYou ? "you" : "AI", + notTarget ? "not target" : "target"), + name, + target.toString(), + new TargetTestableResult() + ); this.isPlayerChoice = isPlayerChoice; this.isTargetChoice = isTargetChoice; this.target = target.withNotTarget(notTarget); @@ -42,34 +47,48 @@ class ChooseTargetTestableDialog extends BaseTestableDialog { } @Override - public List showDialog(Player player, Ability source, Game game, Player opponent) { + public void showDialog(Player player, Ability source, Game game, Player opponent) { Target choosingTarget = this.target.copy(); Player choosingPlayer = this.isYou ? player : opponent; boolean chooseRes; + String chooseDebugSource; if (this.isPlayerChoice) { // player.chooseXXX if (this.isTargetChoice) { + chooseDebugSource = DebugUtil.getMethodNameWithSource(0, "class"); chooseRes = choosingPlayer.chooseTarget(Outcome.Benefit, choosingTarget, source, game); } else { + chooseDebugSource = DebugUtil.getMethodNameWithSource(0, "class"); chooseRes = choosingPlayer.choose(Outcome.Benefit, choosingTarget, source, game); } } else { // target.chooseXXX if (this.isTargetChoice) { + chooseDebugSource = DebugUtil.getMethodNameWithSource(0, "class"); chooseRes = choosingTarget.chooseTarget(Outcome.Benefit, choosingPlayer.getId(), source, game); } else { + chooseDebugSource = DebugUtil.getMethodNameWithSource(0, "class"); chooseRes = choosingTarget.choose(Outcome.Benefit, choosingPlayer.getId(), source, game); } } - List result = new ArrayList<>(); + List res = new ArrayList<>(); if (chooseRes) { - Targets.printDebugTargets(getGroup() + " - " + this.getName() + " - " + "TRUE", new Targets(choosingTarget), source, game, result); + Targets.printDebugTargets(getGroup() + " - " + this.getName() + " - " + "TRUE", new Targets(choosingTarget), source, game, res); } else { - Targets.printDebugTargets(getGroup() + " - " + this.getName() + " - " + "FALSE", new Targets(choosingTarget), source, game, result); + Targets.printDebugTargets(getGroup() + " - " + this.getName() + " - " + "FALSE", new Targets(choosingTarget), source, game, res); } - return result; + + ((TargetTestableResult) this.getResult()).onFinish(chooseDebugSource, chooseRes, res, choosingTarget); + } + + private ChooseTargetTestableDialog aiMustChoose(boolean resStatus, int targetsCount) { + TargetTestableResult res = ((TargetTestableResult) this.getResult()); + res.aiAssertEnabled = true; + res.aiAssertResStatus = resStatus; + res.aiAssertTargetsCount = targetsCount; + return this; } static public void register(TestableDialogsRunner runner) { @@ -84,37 +103,29 @@ class ChooseTargetTestableDialog extends BaseTestableDialog { for (boolean isYou : isYous) { for (boolean isTargetChoice : isTargetChoices) { for (boolean isPlayerChoice : isPlayerChoices) { - runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 0 e.g. X=0", createAnyTarget(0, 0))); // simulate X=0 - runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 1", createAnyTarget(1, 1))); - runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 3", createAnyTarget(3, 3))); - runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 5", createAnyTarget(5, 5))); - runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any max", createAnyTarget(0, Integer.MAX_VALUE))); - runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 0-1", createAnyTarget(0, 1))); - runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 0-3", createAnyTarget(0, 3))); - runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 0-5", createAnyTarget(0, 5))); - runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 1-3", createAnyTarget(1, 3))); - runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 2-3", createAnyTarget(2, 3))); - runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 1-5", createAnyTarget(1, 5))); - runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 2-5", createAnyTarget(2, 5))); - runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 3-5", createAnyTarget(3, 5))); - runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 4-5", createAnyTarget(4, 5))); // impossible on 3 targets + runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 0 e.g. X=0", createAnyTarget(0, 0)).aiMustChoose(false, 0)); // simulate X=0 + runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 1", createAnyTarget(1, 1)).aiMustChoose(true, 1)); + runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 3", createAnyTarget(3, 3)).aiMustChoose(true, 3)); + runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 5", createAnyTarget(5, 5)).aiMustChoose(true, 5)); + runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any max", createAnyTarget(0, Integer.MAX_VALUE)).aiMustChoose(true, 6 + 1)); // 6 own cards + 1 own player + runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 0-1", createAnyTarget(0, 1)).aiMustChoose(true, 1)); + runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 0-3", createAnyTarget(0, 3)).aiMustChoose(true, 3)); + runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 0-5", createAnyTarget(0, 5)).aiMustChoose(true, 5)); + runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 1-3", createAnyTarget(1, 3)).aiMustChoose(true, 3)); + runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 2-3", createAnyTarget(2, 3)).aiMustChoose(true, 3)); + runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 1-5", createAnyTarget(1, 5)).aiMustChoose(true, 5)); + runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 2-5", createAnyTarget(2, 5)).aiMustChoose(true, 5)); + runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 3-5", createAnyTarget(3, 5)).aiMustChoose(true, 5)); + runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "any 4-5", createAnyTarget(4, 5)).aiMustChoose(true, 5)); // - runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "impossible 0, e.g. X=0", createImpossibleTarget(0, 0))); - runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "impossible 1", createImpossibleTarget(1, 1))); - runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "impossible 3", createImpossibleTarget(3, 3))); - runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "impossible 0-1", createImpossibleTarget(0, 1))); - runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "impossible 0-3", createImpossibleTarget(0, 3))); - runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "impossible 1-3", createImpossibleTarget(1, 3))); - runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "impossible 2-3", createImpossibleTarget(2, 3))); - runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "impossible max", createImpossibleTarget(0, Integer.MAX_VALUE))); - // - /* - runner.registerDialog(new PlayerChooseTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "creatures 0, e.g. X=0", createCreatureTarget(0, 0))); // simulate X=0 - runner.registerDialog(new PlayerChooseTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "creatures 1", createCreatureTarget(1, 1))); - runner.registerDialog(new PlayerChooseTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "creatures 3", createCreatureTarget(3, 3))); - runner.registerDialog(new PlayerChooseTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "creatures 5", createCreatureTarget(5, 5))); - runner.registerDialog(new PlayerChooseTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "creatures max", createCreatureTarget(0, Integer.MAX_VALUE))); - */ + runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "impossible 0, e.g. X=0", createImpossibleTarget(0, 0)).aiMustChoose(false, 0)); + runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "impossible 1", createImpossibleTarget(1, 1)).aiMustChoose(false, 0)); + runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "impossible 3", createImpossibleTarget(3, 3)).aiMustChoose(false, 0)); + runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "impossible 0-1", createImpossibleTarget(0, 1)).aiMustChoose(false, 0)); + runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "impossible 0-3", createImpossibleTarget(0, 3)).aiMustChoose(false, 0)); + runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "impossible 1-3", createImpossibleTarget(1, 3)).aiMustChoose(false, 0)); + runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "impossible 2-3", createImpossibleTarget(2, 3)).aiMustChoose(false, 0)); + runner.registerDialog(new ChooseTargetTestableDialog(isPlayerChoice, isTargetChoice, notTarget, isYou, "impossible max", createImpossibleTarget(0, Integer.MAX_VALUE)).aiMustChoose(false, 0)); } } } diff --git a/Mage.Common/src/main/java/mage/utils/testers/ChooseUseTestableDialog.java b/Mage.Common/src/main/java/mage/utils/testers/ChooseUseTestableDialog.java index 3e8137af32b..80a1e7a8f69 100644 --- a/Mage.Common/src/main/java/mage/utils/testers/ChooseUseTestableDialog.java +++ b/Mage.Common/src/main/java/mage/utils/testers/ChooseUseTestableDialog.java @@ -5,6 +5,7 @@ import mage.constants.Outcome; import mage.game.Game; import mage.players.Player; import mage.util.CardUtil; +import mage.util.DebugUtil; import java.util.ArrayList; import java.util.Arrays; @@ -27,7 +28,11 @@ class ChooseUseTestableDialog extends BaseTestableDialog { String messageAdditional; public ChooseUseTestableDialog(boolean isYou, String name, String trueText, String falseText, String messageMain, String messageAdditional) { - super(String.format("player.chooseUse(%s)", isYou ? "you" : "AI"), name + buildName(trueText, falseText, messageMain, messageAdditional), ""); + super(String.format("player.chooseUse(%s)", isYou ? "you" : "AI"), + name + buildName(trueText, falseText, messageMain, messageAdditional), + "", + new BaseTestableResult() + ); this.isYou = isYou; this.trueText = trueText; this.falseText = falseText; @@ -42,8 +47,9 @@ class ChooseUseTestableDialog extends BaseTestableDialog { } @Override - public List showDialog(Player player, Ability source, Game game, Player opponent) { + public void showDialog(Player player, Ability source, Game game, Player opponent) { Player choosingPlayer = this.isYou ? player : opponent; + String chooseDebugSource = DebugUtil.getMethodNameWithSource(0, "class"); boolean chooseRes = choosingPlayer.chooseUse( Outcome.Benefit, messageMain, @@ -53,9 +59,10 @@ class ChooseUseTestableDialog extends BaseTestableDialog { source, game ); - List result = new ArrayList<>(); - result.add(chooseRes ? "TRUE" : "FALSE"); - return result; + List res = new ArrayList<>(); + res.add(chooseRes ? "TRUE" : "FALSE"); + + this.getResult().onFinish(chooseDebugSource, chooseRes, res); } static public void register(TestableDialogsRunner runner) { diff --git a/Mage.Common/src/main/java/mage/utils/testers/GetAmountTestableDialog.java b/Mage.Common/src/main/java/mage/utils/testers/GetAmountTestableDialog.java index 0a66bac8f9d..569284c239d 100644 --- a/Mage.Common/src/main/java/mage/utils/testers/GetAmountTestableDialog.java +++ b/Mage.Common/src/main/java/mage/utils/testers/GetAmountTestableDialog.java @@ -3,6 +3,7 @@ package mage.utils.testers; import mage.abilities.Ability; import mage.game.Game; import mage.players.Player; +import mage.util.DebugUtil; import java.util.ArrayList; import java.util.Arrays; @@ -26,21 +27,25 @@ class GetAmountTestableDialog extends BaseTestableDialog { public GetAmountTestableDialog(boolean isYou, int min, int max) { super(String.format("player.getAmount(%s)", isYou ? "you" : "AI"), - String.format("from %d to %d", min, max), ""); + String.format("from %d to %d", min, max), + "", + new AmountTestableResult() + ); this.isYou = isYou; this.min = min; this.max = max; } @Override - public List showDialog(Player player, Ability source, Game game, Player opponent) { + public void showDialog(Player player, Ability source, Game game, Player opponent) { Player choosingPlayer = this.isYou ? player : opponent; String message = "message with html"; - int chooseRes; - chooseRes = choosingPlayer.getAmount(this.min, this.max, message, source, game); - List result = new ArrayList<>(); - result.add(getGroup() + " - " + this.getName() + " selected " + chooseRes); - return result; + String chooseDebugSource = DebugUtil.getMethodNameWithSource(0, "class"); + int chooseRes = choosingPlayer.getAmount(this.min, this.max, message, source, game); + List res = new ArrayList<>(); + res.add(getGroup() + " - " + this.getName() + " selected " + chooseRes); + + ((AmountTestableResult) this.getResult()).onFinish(chooseDebugSource, true, res, chooseRes); } static public void register(TestableDialogsRunner runner) { diff --git a/Mage.Common/src/main/java/mage/utils/testers/GetMultiAmountTestableDialog.java b/Mage.Common/src/main/java/mage/utils/testers/GetMultiAmountTestableDialog.java index 2c1f9046f3a..869791a6e8a 100644 --- a/Mage.Common/src/main/java/mage/utils/testers/GetMultiAmountTestableDialog.java +++ b/Mage.Common/src/main/java/mage/utils/testers/GetMultiAmountTestableDialog.java @@ -5,12 +5,14 @@ import mage.constants.MultiAmountType; import mage.constants.Outcome; import mage.game.Game; import mage.players.Player; +import mage.util.DebugUtil; import mage.util.MultiAmountMessage; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; +import java.util.stream.IntStream; /** * Part of testable game dialogs @@ -36,7 +38,9 @@ class GetMultiAmountTestableDialog extends BaseTestableDialog { public GetMultiAmountTestableDialog(boolean isYou, String info, int totalMin, int totalMax, List> options) { super(String.format("player.getMultiAmount(%s)", isYou ? "you" : "AI"), String.format("%s, %d options from [%d-%d]", info, options.size(), totalMin, totalMax), - ""); + "", + new MultiAmountTestableResult() + ); this.isYou = isYou; this.totalMin = totalMin; this.totalMax = totalMax; @@ -48,13 +52,33 @@ class GetMultiAmountTestableDialog extends BaseTestableDialog { } } + private GetMultiAmountTestableDialog aiMustChoose(Integer... needValues) { + // TODO: AI use default distribution (min possible values), improve someday + MultiAmountTestableResult res = ((MultiAmountTestableResult) this.getResult()); + res.aiAssertEnabled = true; + res.aiAssertValues = Arrays.stream(needValues).collect(Collectors.toList()); + return this; + } + + private GetMultiAmountTestableDialog aiMustChooseMany(Integer options, Integer perOption) { + List need = new ArrayList<>(); + IntStream.rangeClosed(1, options).forEach(x -> { + need.add(perOption); + }); + + MultiAmountTestableResult res = ((MultiAmountTestableResult) this.getResult()); + res.aiAssertEnabled = true; + res.aiAssertValues = need; + return this; + } + @Override - public List showDialog(Player player, Ability source, Game game, Player opponent) { + public void showDialog(Player player, Ability source, Game game, Player opponent) { Player choosingPlayer = this.isYou ? player : opponent; //String message = "message with html"; - List chooseRes; List options = this.amountOptions.stream().map(MultiAmountMessage::copy).collect(Collectors.toList()); - chooseRes = choosingPlayer.getMultiAmountWithIndividualConstraints( + String chooseDebugSource = DebugUtil.getMethodNameWithSource(0, "class"); + List chooseRes = choosingPlayer.getMultiAmountWithIndividualConstraints( Outcome.Benefit, options, this.totalMin, @@ -63,24 +87,24 @@ class GetMultiAmountTestableDialog extends BaseTestableDialog { game ); - List result = new ArrayList<>(); - result.add(getGroup() + " - " + this.getName()); + List res = new ArrayList<>(); + res.add(getGroup() + " - " + this.getName()); int selectedIndex = -1; int selectedTotal = 0; for (Integer selectedValue : chooseRes) { selectedIndex++; selectedTotal += selectedValue; MultiAmountMessage option = this.amountOptions.get(selectedIndex); - result.add(String.format("%d from [%d-%d, def %d]", + res.add(String.format("%d from [%d-%d, def %d]", selectedValue, option.min, option.max, option.defaultValue )); } - result.add("total selected: " + selectedTotal); + res.add("total selected: " + selectedTotal); - return result; + ((MultiAmountTestableResult) this.getResult()).onFinish(chooseDebugSource, true, res, chooseRes); } static public void register(TestableDialogsRunner runner) { @@ -88,28 +112,29 @@ class GetMultiAmountTestableDialog extends BaseTestableDialog { for (boolean isYou : isYous) { // make sure default values are valid due min/max settings + // TODO: add bad effect for AI (must test default distribution) + // single target - runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "one, 0 def", 0, 1, genSameOptions(1, 0, 1, 0))); - runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "one, 0 def", 0, 3, genSameOptions(1, 0, 3, 0))); - runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "one, 1 def", 1, 1, genSameOptions(1, 1, 1, 1))); - runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "one, 1 def", 1, 3, genSameOptions(1, 1, 3, 1))); - runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "one, 5 def", 0, 10, genSameOptions(1, 0, 10, 5))); - runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "one, 10 def", 10, 10, genSameOptions(1, 0, 10, 10))); + runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "one, 0 def", 0, 1, genSameOptions(1, 0, 1, 0)).aiMustChoose(1)); + runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "one, 0 def", 0, 3, genSameOptions(1, 0, 3, 0)).aiMustChoose(3)); + runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "one, 1 def", 1, 1, genSameOptions(1, 1, 1, 1)).aiMustChoose(1)); + runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "one, 1 def", 1, 3, genSameOptions(1, 1, 3, 1)).aiMustChoose(3)); + runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "one, 5 def", 0, 10, genSameOptions(1, 0, 10, 5)).aiMustChoose(10)); + runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "one, 10 def", 10, 10, genSameOptions(1, 0, 10, 10)).aiMustChoose(10)); // multiple targets - runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "many, 0 def", 0, 5, genSameOptions(3, 0, 3, 0))); - runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "many, 0 def", 0, 5, genSameOptions(3, 0, 3, 0))); - runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "many, 1 def", 1, 5, genSameOptions(3, 1, 3, 1))); - runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "many, 1 def", 1, 5, genSameOptions(3, 1, 3, 1))); - runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "many, 20 def", 0, 60, genSameOptions(3, 0, 60, 20))); - runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "many, 20 def", 60, 60, genSameOptions(3, 0, 60, 20))); + runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "many, 0 def", 0, 5, genSameOptions(3, 0, 3, 0)).aiMustChoose(2, 2, 1)); + runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "many, 1 def", 1, 5, genSameOptions(3, 1, 3, 1)).aiMustChoose(2, 2, 1)); + runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "many, 20 def", 0, 60, genSameOptions(3, 0, 60, 20)).aiMustChoose(20, 20, 20)); + runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "many, 20 def", 60, 60, genSameOptions(3, 0, 60, 20)).aiMustChoose(20, 20, 20)); // big lists - runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "big list", 0, 100, genSameOptions(20, 0, 100, 0))); + runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "big list", 0, 100, genSameOptions(20, 0, 100, 0)).aiMustChooseMany(20, 5)); + runner.registerDialog(new GetMultiAmountTestableDialog(isYou, "big list", 0, 100, genSameOptions(100, 0, 100, 0)).aiMustChooseMany(100, 1)); } } - private static List> genSameOptions(int amount, int min, int max, int def) { + private static List> genSameOptions(int options, int min, int max, int def) { List> res = new ArrayList<>(); - for (int i = 0; i < amount; i++) { + for (int i = 0; i < options; i++) { // min, max, default res.add(Arrays.asList(min, max, def)); } diff --git a/Mage.Common/src/main/java/mage/utils/testers/MultiAmountTestableResult.java b/Mage.Common/src/main/java/mage/utils/testers/MultiAmountTestableResult.java new file mode 100644 index 00000000000..53ae9a4f5ab --- /dev/null +++ b/Mage.Common/src/main/java/mage/utils/testers/MultiAmountTestableResult.java @@ -0,0 +1,54 @@ +package mage.utils.testers; + +import java.util.ArrayList; +import java.util.List; + +/** + * Part of testable game dialogs + * + * @author JayDi85 + */ +public class MultiAmountTestableResult extends BaseTestableResult { + + List selectedValues; + + boolean aiAssertEnabled = false; + List aiAssertValues = new ArrayList<>(); + + public void onFinish(String resDebugSource, boolean status, List info, List selectedValues) { + this.onFinish(resDebugSource, status, info); + this.selectedValues = selectedValues; + } + + @Override + public String getResAssert() { + if (!this.aiAssertEnabled) { + return null; + } + + // not finished + if (this.selectedValues == null) { + return null; + } + + // wrong selection + String selected = this.selectedValues.toString(); + String need = this.aiAssertValues.toString(); + + if (!selected.equals(need)) { + return String.format("Wrong selection: need %s, but get %s", + need, + selected + ); + } + + // all fine + return ""; + } + + @Override + public void onClear() { + super.onClear(); + this.selectedValues = null; + } +} diff --git a/Mage.Common/src/main/java/mage/utils/testers/TargetTestableResult.java b/Mage.Common/src/main/java/mage/utils/testers/TargetTestableResult.java new file mode 100644 index 00000000000..1f49cb8d831 --- /dev/null +++ b/Mage.Common/src/main/java/mage/utils/testers/TargetTestableResult.java @@ -0,0 +1,61 @@ +package mage.utils.testers; + +import mage.target.Target; + +import java.util.List; + +/** + * Part of testable game dialogs + * + * @author JayDi85 + */ +public class TargetTestableResult extends BaseTestableResult { + + Target target = null; + + boolean aiAssertEnabled = false; + boolean aiAssertResStatus = false; + int aiAssertTargetsCount = 0; + + public void onFinish(String resDebugSource, boolean status, List info, Target target) { + this.onFinish(resDebugSource, status, info); + this.target = target; + } + + @Override + public String getResAssert() { + if (!this.aiAssertEnabled) { + return null; + } + + // not finished + if (this.target == null) { + return null; + } + + // wrong choose + if (this.getResStatus() != this.aiAssertResStatus) { + return String.format("Wrong status: need %s, but get %s", + this.aiAssertResStatus, + this.getResStatus() + ); + } + + // wrong targets + if (this.target.getTargets().size() != this.aiAssertTargetsCount) { + return String.format("Wrong targets count: need %d, but get %d", + this.aiAssertTargetsCount, + this.target.getTargets().size() + ); + } + + // all fine + return ""; + } + + @Override + public void onClear() { + super.onClear(); + this.target = null; + } +} diff --git a/Mage.Common/src/main/java/mage/utils/testers/TestableDialog.java b/Mage.Common/src/main/java/mage/utils/testers/TestableDialog.java index 1479ee9f306..d5e86740ff8 100644 --- a/Mage.Common/src/main/java/mage/utils/testers/TestableDialog.java +++ b/Mage.Common/src/main/java/mage/utils/testers/TestableDialog.java @@ -4,8 +4,6 @@ import mage.abilities.Ability; import mage.game.Game; import mage.players.Player; -import java.util.List; - /** * Part of testable game dialogs *

@@ -17,7 +15,11 @@ import java.util.List; * * @author JayDi85 */ -interface TestableDialog { +public interface TestableDialog { + + void setRegNumber(Integer regNumber); + + Integer getRegNumber(); String getGroup(); @@ -25,7 +27,20 @@ interface TestableDialog { String getDescription(); - List showDialog(Player player, Ability source, Game game, Player opponent); + TestableResult getResult(); - void showResult(Player player, Game game, String result); + /** + * Prepare dialog before show, e.g. clear prev results + */ + void prepare(); + + /** + * Show game dialog to the user and save result + */ + void showDialog(Player player, Ability source, Game game, Player opponent); + + /** + * Show result dialog to the user + */ + void showResult(Player player, Game game); } diff --git a/Mage.Common/src/main/java/mage/utils/testers/TestableDialogsRunner.java b/Mage.Common/src/main/java/mage/utils/testers/TestableDialogsRunner.java index 3c2cfb3840d..0970d8ecc94 100644 --- a/Mage.Common/src/main/java/mage/utils/testers/TestableDialogsRunner.java +++ b/Mage.Common/src/main/java/mage/utils/testers/TestableDialogsRunner.java @@ -8,8 +8,10 @@ import mage.constants.Outcome; import mage.game.Game; import mage.players.Player; -import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; /** @@ -55,7 +57,7 @@ import java.util.stream.Collectors; */ public class TestableDialogsRunner { - private final List dialogs = new ArrayList<>(); + private final Map dialogs = new LinkedHashMap<>(); static final int LAST_SELECTED_GROUP_ID = 997; static final int LAST_SELECTED_DIALOG_ID = 998; @@ -79,12 +81,14 @@ public class TestableDialogsRunner { } void registerDialog(TestableDialog dialog) { - this.dialogs.add(dialog); + Integer regNumber = this.dialogs.size() + 1; + dialog.setRegNumber(regNumber); + this.dialogs.put(regNumber, dialog); } public void selectAndShowTestableDialog(Player player, Ability source, Game game, Player opponent) { // select group or fast links - List groups = this.dialogs.stream() + List groups = this.dialogs.values().stream() .map(TestableDialog::getGroup) .distinct() .sorted() @@ -129,8 +133,9 @@ public class TestableDialogsRunner { // all fine, can show it and finish lastSelectedGroup = needGroup; lastSelectedDialog = needDialog; - List resInfo = needDialog.showDialog(player, source, game, opponent); - needDialog.showResult(player, game, String.join("
", resInfo)); + needDialog.prepare(); + needDialog.showDialog(player, source, game, opponent); + needDialog.showResult(player, game); } private Choice prepareSelectGroupChoice(List groups) { @@ -199,5 +204,9 @@ public class TestableDialogsRunner { } return choice; } + + public Collection getDialogs() { + return this.dialogs.values(); + } } diff --git a/Mage.Common/src/main/java/mage/utils/testers/TestableResult.java b/Mage.Common/src/main/java/mage/utils/testers/TestableResult.java new file mode 100644 index 00000000000..7615aad678a --- /dev/null +++ b/Mage.Common/src/main/java/mage/utils/testers/TestableResult.java @@ -0,0 +1,43 @@ +package mage.utils.testers; + +import java.util.List; + +/** + * Part of testable game dialogs, must contain dialogs result + * + * @author JayDi85 + */ +public interface TestableResult { + + /** + * Get source code line with called dialog, use it as starting debug point + */ + String getResDebugSource(); + + /** + * Dialog's result + */ + boolean getResStatus(); + + /** + * Dialog's detail result + */ + List getResDetails(); + + /** + * Save new result after show dialog + */ + void onFinish(String chooseDebugSource, boolean resStatus, List resDetails); + + boolean isFinished(); + + void onClear(); + + /** + * Assert dialog result + * - null - not ready (dev must setup wanted result) + * - empty - good + * - not empty - fail (return error message) + */ + String getResAssert(); +} diff --git a/Mage.Common/src/main/java/mage/view/GameView.java b/Mage.Common/src/main/java/mage/view/GameView.java index 59d47955831..4b6d06c7c95 100644 --- a/Mage.Common/src/main/java/mage/view/GameView.java +++ b/Mage.Common/src/main/java/mage/view/GameView.java @@ -67,6 +67,7 @@ public class GameView implements Serializable { // TODO: implement and support in admin tools private int totalErrorsCount; private int totalEffectsCount; + private int gameCycle; public GameView(GameState state, Game game, UUID createdForPlayerId, UUID watcherUserId) { Player createdForPlayer = null; @@ -214,6 +215,7 @@ public class GameView implements Serializable { this.rollbackTurnsAllowed = game.getOptions().rollbackTurnsAllowed; this.totalErrorsCount = game.getTotalErrorsCount(); this.totalEffectsCount = game.getTotalEffectsCount(); + this.gameCycle = game.getState().getApplyEffectsCounter(); } private void checkPaid(UUID uuid, StackAbility stackAbility) { @@ -358,4 +360,8 @@ public class GameView implements Serializable { public int getTotalEffectsCount() { return this.totalEffectsCount; } + + public int getGameCycle() { + return this.gameCycle; + } } 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 ec41f96cae2..9f591a0db29 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 @@ -18,11 +18,6 @@ public class Standard extends Constructed { super("Constructed - Standard"); setCodes.addAll(makeLegalSets()); - - banned.add("The Meathook Massacre"); - banned.add("Fable of the Mirror-Breaker"); - banned.add("Reckoner Bankbuster"); - banned.add("Invoke Despair"); } static List makeLegalSets() { diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java index 14ba9d0ea2b..b606a20d75e 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java @@ -23,6 +23,7 @@ import mage.game.stack.StackAbility; import mage.game.stack.StackObject; import mage.player.ai.ma.optimizers.TreeOptimizer; import mage.player.ai.ma.optimizers.impl.*; +import mage.player.ai.score.GameStateEvaluator2; import mage.player.ai.util.CombatInfo; import mage.player.ai.util.CombatUtil; import mage.players.Player; @@ -399,7 +400,7 @@ public class ComputerPlayer6 extends ComputerPlayer { if (effect != null && stackObject.getControllerId().equals(playerId)) { Target target = effect.getTarget(); - if (!target.isChoiceCompleted(game)) { + if (!target.isChoiceCompleted(getId(), (StackAbility) stackObject, game)) { for (UUID targetId : target.possibleTargets(stackObject.getControllerId(), stackObject.getStackAbility(), game)) { Game sim = game.createSimulationForAI(); StackAbility newAbility = (StackAbility) stackObject.copy(); @@ -848,10 +849,12 @@ public class ComputerPlayer6 extends ComputerPlayer { if (targets.isEmpty()) { return super.chooseTarget(outcome, cards, target, source, game); } - if (!target.isChoiceCompleted(game)) { + + UUID abilityControllerId = target.getAffectedAbilityControllerId(getId()); + if (!target.isChoiceCompleted(abilityControllerId, source, game)) { for (UUID targetId : targets) { target.addTarget(targetId, source, game); - if (target.isChoiceCompleted(game)) { + if (target.isChoiceCompleted(abilityControllerId, source, game)) { targets.clear(); return true; } @@ -866,10 +869,12 @@ public class ComputerPlayer6 extends ComputerPlayer { if (targets.isEmpty()) { return super.choose(outcome, cards, target, source, game); } - if (!target.isChoiceCompleted(game)) { + + UUID abilityControllerId = target.getAffectedAbilityControllerId(getId()); + if (!target.isChoiceCompleted(abilityControllerId, source, game)) { for (UUID targetId : targets) { target.add(targetId, game); - if (target.isChoiceCompleted(game)) { + if (target.isChoiceCompleted(abilityControllerId, source, game)) { targets.clear(); return true; } diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java index f78cceee8f1..31b9bee41ec 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer7.java @@ -3,6 +3,7 @@ package mage.player.ai; import mage.abilities.Ability; import mage.constants.RangeOfInfluence; import mage.game.Game; +import mage.player.ai.score.GameStateEvaluator2; import org.apache.log4j.Logger; import java.util.Date; @@ -111,8 +112,6 @@ public class ComputerPlayer7 extends ComputerPlayer6 { protected void calculateActions(Game game) { if (!getNextAction(game)) { - //logger.info("--- calculating possible actions for " + this.getName() + " on " + game.toString()); - Date startTime = new Date(); currentScore = GameStateEvaluator2.evaluate(playerId, game).getTotalScore(); Game sim = createSimulation(game); SimulationNode2.resetCount(); @@ -145,15 +144,6 @@ public class ComputerPlayer7 extends ComputerPlayer6 { } else { logger.info('[' + game.getPlayer(playerId).getName() + "][pre] Action: skip"); } - Date endTime = new Date(); - this.setLastThinkTime((endTime.getTime() - startTime.getTime())); - - /* - logger.warn("Last think time: " + this.getLastThinkTime() - + "; actions: " + actions.size() - + "; hand: " + this.getHand().size() - + "; permanents: " + game.getBattlefield().getAllPermanents().size()); - */ } else { logger.debug("Next Action exists!"); } diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/util/CombatUtil.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/util/CombatUtil.java index 873b4c5bbcd..32bc78c75b7 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/util/CombatUtil.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/util/CombatUtil.java @@ -13,7 +13,7 @@ import mage.game.permanent.Permanent; import mage.game.turn.CombatDamageStep; import mage.game.turn.EndOfCombatStep; import mage.game.turn.Step; -import mage.player.ai.GameStateEvaluator2; +import mage.player.ai.score.GameStateEvaluator2; import mage.players.Player; import org.apache.log4j.Logger; 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 ace8620e6b2..b9c6f3ff1b8 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 @@ -1,20 +1,12 @@ package mage.player.ai; -import mage.ApprovingObject; -import mage.ConditionalMana; -import mage.MageObject; -import mage.Mana; +import mage.*; import mage.abilities.*; import mage.abilities.costs.mana.*; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.DamageTargetEffect; -import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; -import mage.abilities.keyword.*; import mage.abilities.mana.ActivatedManaAbilityImpl; import mage.abilities.mana.ManaOptions; import mage.cards.Card; import mage.cards.Cards; -import mage.cards.CardsImpl; import mage.cards.RateCard; import mage.cards.decks.Deck; import mage.cards.decks.DeckValidator; @@ -24,31 +16,20 @@ import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; import mage.choices.Choice; import mage.constants.*; -import mage.counters.CounterType; -import mage.filter.FilterCard; -import mage.filter.FilterPermanent; -import mage.filter.StaticFilters; -import mage.filter.common.*; -import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.filter.common.FilterLandCard; import mage.game.Game; -import mage.game.combat.CombatGroup; import mage.game.draft.Draft; -import mage.game.events.GameEvent; import mage.game.match.Match; import mage.game.permanent.Permanent; -import mage.game.stack.Spell; -import mage.game.stack.StackObject; import mage.game.tournament.Tournament; -import mage.player.ai.simulators.CombatGroupSimulator; -import mage.player.ai.simulators.CombatSimulator; -import mage.player.ai.simulators.CreatureSimulator; import mage.players.ManaPoolItem; import mage.players.Player; import mage.players.PlayerImpl; import mage.players.net.UserData; import mage.players.net.UserGroup; -import mage.target.*; -import mage.target.common.*; +import mage.target.Target; +import mage.target.TargetAmount; +import mage.target.TargetCard; import mage.util.*; import org.apache.log4j.Logger; @@ -57,21 +38,21 @@ import java.util.*; import java.util.Map.Entry; /** - * AI: basic server side bot with simple actions support (game, draft, construction/sideboarding) + * AI: basic server side bot with simple actions support (game, draft, construction/sideboarding). + * Full and minimum implementation of all choose dialogs to allow AI to start and finish a real game. + * Used as parent class for any AI implementations. *

- * TODO: combine choose and chooseTarget to single logic to use shared code * * @author BetaSteward_at_googlemail.com, JayDi85 */ public class ComputerPlayer extends PlayerImpl { - private static final Logger log = Logger.getLogger(ComputerPlayer.class); - private long lastThinkTime = 0; // msecs for last AI actions calc + private static final Logger logger = Logger.getLogger(ComputerPlayer.class); - protected int PASSIVITY_PENALTY = 5; // Penalty value for doing nothing if some actions are available + protected static final int PASSIVITY_PENALTY = 5; // Penalty value for doing nothing if some actions are available // debug only: set TRUE to debug simulation's code/games (on false sim thread will be stopped after few secs by timeout) - protected boolean COMPUTER_DISABLE_TIMEOUT_IN_GAME_SIMULATIONS = true; // DebugUtil.AI_ENABLE_DEBUG_MODE; + protected static final boolean COMPUTER_DISABLE_TIMEOUT_IN_GAME_SIMULATIONS = true; // DebugUtil.AI_ENABLE_DEBUG_MODE; // AI agents uses game simulation thread for all calcs and it's high CPU consumption // More AI threads - more parallel AI games can be calculate @@ -80,16 +61,13 @@ public class ComputerPlayer extends PlayerImpl { // How-to use: // * 1 for debug or stable // * 5 for good performance on average computer - // * use your's CPU cores for best performance + // * use yours CPU cores for best performance // TODO: add server config to control max AI threads (with CPU cores by default) // TODO: rework AI implementation to use multiple sims calculation instead one by one final static int COMPUTER_MAX_THREADS_FOR_SIMULATIONS = 1;//DebugUtil.AI_ENABLE_DEBUG_MODE ? 1 : 5; - private final transient Map unplayable = new TreeMap<>(); - private final transient List playableNonInstant = new ArrayList<>(); - private final transient List playableInstant = new ArrayList<>(); - private final transient List playableAbilities = new ArrayList<>(); + // remember picked cards for better draft choices private final transient List pickedCards = new ArrayList<>(); private final transient List chosenColors = new ArrayList<>(); @@ -125,7 +103,6 @@ public class ComputerPlayer extends PlayerImpl { @Override public boolean chooseMulligan(Game game) { - log.debug("chooseMulligan"); if (hand.size() < 6 || isTestsMode() // ignore mulligan in tests || game.getClass().getName().contains("Momir") // ignore mulligan in Momir games @@ -144,1524 +121,253 @@ public class ComputerPlayer extends PlayerImpl { @Override public boolean choose(Outcome outcome, Target target, Ability source, Game game, Map options) { - if (log.isDebugEnabled()) { - log.debug("choose: " + outcome.toString() + ':' + target.toString()); - } - - boolean isAddedSomething = false; // must return true on any changes in targets, so game can ask next choose dialog until finish - - // controller hints: - // - target.getTargetController(), this.getId() -- player that must makes choices (must be same with this.getId) - // - target.getAbilityController(), abilityControllerId -- affected player/controller for all actions/filters - // - affected controller can be different from target controller (another player makes choices for controller) - // sometimes a target selection can be made from a player that does not control the ability - UUID abilityControllerId = playerId; - if (target.getTargetController() != null - && target.getAbilityController() != null) { - abilityControllerId = target.getAbilityController(); - } - UUID sourceId = source != null ? source.getSourceId() : null; - - boolean required = target.isRequired(sourceId, game); - Set possibleTargets = target.possibleTargets(abilityControllerId, source, game); - if (possibleTargets.isEmpty() || target.getTargets().size() >= target.getMinNumberOfTargets()) { - required = false; - } - - UUID randomOpponentId = getRandomOpponent(game); - - if (target.getOriginalTarget() instanceof TargetPlayer) { - return selectPlayer(outcome, target, abilityControllerId, randomOpponentId, game, required); - } - - if (target.getOriginalTarget() instanceof TargetDiscard) { - findPlayables(game); - // discard not playable first - if (!unplayable.isEmpty()) { - for (int i = unplayable.size() - 1; i >= 0; i--) { - UUID targetId = unplayable.values().toArray(new Card[0])[i].getId(); - if (target.canTarget(abilityControllerId, targetId, source, game) && !target.contains(targetId)) { - target.add(targetId, game); - isAddedSomething = true; - if (target.isChosen(game)) { - return true; - } - } - } - } - if (!hand.isEmpty()) { - for (int i = 0; i < hand.size(); i++) { - UUID targetId = hand.toArray(new UUID[0])[i]; - if (target.canTarget(abilityControllerId, targetId, source, game) && !target.contains(targetId)) { - target.add(targetId, game); - isAddedSomething = true; - if (target.isChosen(game)) { - return true; - } - } - } - } - return isAddedSomething; - } - - if (target.getOriginalTarget() instanceof TargetControlledPermanent - || target.getOriginalTarget() instanceof TargetSacrifice) { - List targets; - TargetPermanent origTarget = (TargetPermanent) target.getOriginalTarget(); - targets = threats(abilityControllerId, source, origTarget.getFilter(), game, target.getTargets()); - if (!outcome.isGood()) { - Collections.reverse(targets); - } - for (Permanent permanent : targets) { - if (origTarget.canTarget(abilityControllerId, permanent.getId(), source, game, false) && !target.contains(permanent.getId())) { - target.add(permanent.getId(), game); - isAddedSomething = true; - if (target.isChosen(game)) { - return true; - } - } - } - return isAddedSomething; - } - - if (target.getOriginalTarget() instanceof TargetPermanent) { - FilterPermanent filter = null; - if (target.getOriginalTarget().getFilter() instanceof FilterPermanent) { - filter = (FilterPermanent) target.getOriginalTarget().getFilter(); - } - if (filter == null) { - throw new IllegalStateException("Unsupported permanent filter in computer's choose method: " - + target.getOriginalTarget().getClass().getCanonicalName()); - } - - List targets; - if (outcome.isCanTargetAll()) { - targets = threats(null, source, filter, game, target.getTargets()); - } else { - if (outcome.isGood()) { - targets = threats(abilityControllerId, source, filter, game, target.getTargets()); - } else { - targets = threats(randomOpponentId, source, filter, game, target.getTargets()); - } - if (targets.isEmpty() && target.isRequired()) { - if (!outcome.isGood()) { - targets = threats(abilityControllerId, source, filter, game, target.getTargets()); - } else { - targets = threats(randomOpponentId, source, filter, game, target.getTargets()); - } - } - } - - for (Permanent permanent : targets) { - if (target.canTarget(abilityControllerId, permanent.getId(), source, game) && !target.contains(permanent.getId())) { - // AI workaround to stop adding more targets in "up to" on bad outcome for itself - if (target.isChosen(game) && target.getMinNumberOfTargets() == target.getTargets().size()) { - if (outcome.isGood() && hasOpponent(permanent.getControllerId(), game)) { - return isAddedSomething; - } - if (!outcome.isGood() && !hasOpponent(permanent.getControllerId(), game)) { - return isAddedSomething; - } - } - // add the target - target.add(permanent.getId(), game); - isAddedSomething = true; - if (target.isChosen(game)) { - return true; - } - } - } - return isAddedSomething; - } - - if (target.getOriginalTarget() instanceof TargetCardInHand - || (target.getZone() == Zone.HAND && (target.getOriginalTarget() instanceof TargetCard))) { - List cards = new ArrayList<>(); - for (UUID cardId : target.possibleTargets(this.getId(), source, game)) { - Card card = game.getCard(cardId); - if (card != null) { - cards.add(card); - } - } - while ((outcome.isGood() ? target.getTargets().size() < target.getMaxNumberOfTargets() : !target.isChosen(game)) - && !cards.isEmpty()) { - Card card = selectCard(abilityControllerId, cards, outcome, target, game); - if (card != null) { - cards.remove(card); // selectCard don't remove cards (only on second+ tries) - if (!target.contains(card.getId())) { - target.add(card.getId(), game); // TODO: why it add as much as possible instead go to isChosen check like above? - isAddedSomething = true; - if (target.isChosen(game)) { - //return true; // TODO: why it add as much as possible instead go to isChosen check like above? - } - } - } else { - break; - } - } - return isAddedSomething; - } - - if (target.getOriginalTarget() instanceof TargetAnyTarget) { - List targets; - TargetAnyTarget origTarget = (TargetAnyTarget) target.getOriginalTarget(); - if (outcome.isGood()) { - targets = threats(abilityControllerId, source, ((FilterAnyTarget) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets()); - } else { - targets = threats(randomOpponentId, source, ((FilterAnyTarget) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets()); - } - for (Permanent permanent : targets) { - if (target.canTarget(abilityControllerId, permanent.getId(), source, game) && !target.contains(permanent.getId())) { - target.add(permanent.getId(), game); - isAddedSomething = true; - if (target.isChosen(game)) { - return true; - } - } - } - if (outcome.isGood()) { - if (target.canTarget(abilityControllerId, getId(), source, game) && !target.contains(getId())) { - target.add(getId(), game); - isAddedSomething = true; - if (target.isChosen(game)) { - return true; - } - } - } else if (target.canTarget(abilityControllerId, randomOpponentId, source, game) && !target.contains(randomOpponentId)) { - target.add(randomOpponentId, game); - isAddedSomething = true; - if (target.isChosen(game)) { - return true; - } - } - if (!required) { - return isAddedSomething; - } - } - - if (target.getOriginalTarget() instanceof TargetPermanentOrPlayer) { - List targets; - TargetPermanentOrPlayer origTarget = (TargetPermanentOrPlayer) target.getOriginalTarget(); - List ownedTargets = threats(abilityControllerId, source, ((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets()); - List opponentTargets = threats(randomOpponentId, source, ((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets()); - if (outcome.isGood()) { - targets = ownedTargets; - } else { - targets = opponentTargets; - } - for (Permanent permanent : targets) { - if (target.canTarget(abilityControllerId, permanent.getId(), source, game) && !target.contains(permanent.getId())) { - isAddedSomething = true; - target.add(permanent.getId(), game); - return true; - } - } - if (outcome.isGood()) { - if (target.canTarget(abilityControllerId, getId(), source, game) && !target.contains(getId())) { - target.add(getId(), game); - isAddedSomething = true; - if (target.isChosen(game)) { - return true; - } - } - } else if (target.canTarget(abilityControllerId, randomOpponentId, source, game) && !target.contains(randomOpponentId)) { - target.add(randomOpponentId, game); - isAddedSomething = true; - if (target.isChosen(game)) { - return true; - } - } - if (!target.isRequired(sourceId, game) || target.getMinNumberOfTargets() == 0) { - return isAddedSomething; // TODO: need research why it here (between diff type of targets) - } - if (target.canTarget(abilityControllerId, randomOpponentId, source, game) && !target.contains(randomOpponentId)) { - target.add(randomOpponentId, game); - isAddedSomething = true; - if (target.isChosen(game)) { - return true; - } - } - if (target.canTarget(abilityControllerId, getId(), source, game) && !target.contains(getId())) { - target.add(getId(), game); - isAddedSomething = true; - if (target.isChosen(game)) { - return true; - } - } - if (outcome.isGood()) { // no other valid targets so use a permanent - targets = opponentTargets; - } else { - targets = ownedTargets; - } - for (Permanent permanent : targets) { - if (target.canTarget(abilityControllerId, permanent.getId(), source, game) && !target.contains(permanent.getId())) { - target.add(permanent.getId(), game); - isAddedSomething = true; - if (target.isChosen(game)) { - return true; - } - } - } - return isAddedSomething; - } - - if (target.getOriginalTarget() instanceof TargetCardInASingleGraveyard) { - List cards = new ArrayList<>(); - for (Player player : game.getPlayers().values()) { - for (Card card : player.getGraveyard().getCards(game)) { - if (target.canTarget(abilityControllerId, card.getId(), source, game)) { - cards.add(card); - } - } - } - - // 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(game)) - && !cards.isEmpty()) { - Card card = selectCard(abilityControllerId, cards, outcome, target, game); - if (card != null) { - cards.remove(card); // selectCard don't remove cards (only on second+ tries) - if (!target.contains(card.getId())) { - target.add(card.getId(), game); - isAddedSomething = true; - if (target.isChosen(game)) { - //return true; // TODO: why it add as much as possible instead go to isChosen check like above? - } - } - } else { - break; - } - } - return isAddedSomething; - } - - if (target.getOriginalTarget() instanceof TargetCardInGraveyard - || (target.getZone() == Zone.GRAVEYARD && (target.getOriginalTarget() instanceof TargetCard))) { - List cards = new ArrayList<>(); - for (Player player : game.getPlayers().values()) { - for (Card card : player.getGraveyard().getCards(game)) { - if (target.canTarget(abilityControllerId, card.getId(), source, game)) { - cards.add(card); - } - } - } - - // 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(game)) - && !cards.isEmpty()) { - Card card = selectCard(abilityControllerId, cards, outcome, target, game); - if (card != null) { - cards.remove(card); // selectCard don't remove cards (only on second+ tries) - if (!target.contains(card.getId())) { - target.add(card.getId(), game); - isAddedSomething = true; - if (target.isChosen(game)) { - //return true; // TODO: why it add as much as possible instead go to isChosen check like above? - } - } - } else { - break; - } - } - - return isAddedSomething; - } - - if (target.getOriginalTarget() instanceof TargetCardInYourGraveyard - || target.getOriginalTarget() instanceof TargetCardInASingleGraveyard) { - TargetCard originalTarget = (TargetCard) target.getOriginalTarget(); - List cards = new ArrayList<>(game.getPlayer(abilityControllerId).getGraveyard().getCards(originalTarget.getFilter(), game)); - while (!cards.isEmpty()) { - Card card = selectCard(abilityControllerId, cards, outcome, target, game); - if (card != null && !target.contains(card.getId())) { - target.add(card.getId(), game); - isAddedSomething = true; - if (target.isChosen(game)) { - return true; - } - } - } - return isAddedSomething; - } - - if (target.getOriginalTarget() instanceof TargetCardInExile) { - FilterCard filter = null; - if (target.getOriginalTarget().getFilter() instanceof FilterCard) { - filter = (FilterCard) target.getOriginalTarget().getFilter(); - } - if (filter == null) { - throw new IllegalStateException("Unsupported exile target filter in computer's choose method: " - + target.getOriginalTarget().getClass().getCanonicalName()); - } - - List cards = game.getExile().getCards(filter, game); - while (!cards.isEmpty()) { - Card card = selectCard(abilityControllerId, cards, outcome, target, game); - if (card != null && !target.contains(card.getId())) { - target.add(card.getId(), game); - isAddedSomething = true; - if (target.isChosen(game)) { - return true; - } - } - } - return isAddedSomething; - } - - if (target.getOriginalTarget() instanceof TargetSource) { - Set targets; - targets = target.possibleTargets(abilityControllerId, source, game); - for (UUID targetId : targets) { - MageObject targetObject = game.getObject(targetId); - if (targetObject != null) { - if (target.canTarget(abilityControllerId, targetObject.getId(), source, game)) { - if (!target.contains(targetObject.getId())) { - target.add(targetObject.getId(), game); - isAddedSomething = true; - if (target.isChosen(game)) { - return true; - } - } - } - } - } - if (!required) { - return isAddedSomething; - } - throw new IllegalStateException("TargetSource wasn't handled in computer's choose method: " + target.getClass().getCanonicalName()); - } - - if (target.getOriginalTarget() instanceof TargetPermanentOrSuspendedCard) { - List cards = new ArrayList<>(new CardsImpl(possibleTargets).getCards(game)); - while (!cards.isEmpty()) { - Card card = selectCard(abilityControllerId, cards, outcome, target, game); - if (card != null) { - cards.remove(card); // selectCard don't remove cards (only on second+ tries) - if (!target.contains(card.getId())) { - target.add(card.getId(), game); - isAddedSomething = true; - if (target.isChosen(game)) { - //return true; // TODO: why it add as much as possible instead go to isChosen check like above? - } - } - } else { - break; - } - } - return isAddedSomething; - } - - if (target.getOriginalTarget() instanceof TargetCard - && (target.getZone() == Zone.COMMAND)) { // Hellkite Courser - List cards = new ArrayList<>(); - for (Player player : game.getPlayers().values()) { - for (Card card : game.getCommanderCardsFromCommandZone(player, CommanderCardType.COMMANDER_OR_OATHBREAKER)) { - if (target.canTarget(abilityControllerId, card.getId(), source, game)) { - cards.add(card); - } - } - } - while (!cards.isEmpty()) { - Card card = selectCard(abilityControllerId, cards, outcome, target, game); - if (card != null) { - cards.remove(card); - if (!target.contains(card.getId())) { - target.add(card.getId(), game); - isAddedSomething = true; - if (target.isChosen(game)) { - //return true; // TODO: why it add as much as possible instead go to isChosen check like above? - } - } - } else { - break; - } - } - return isAddedSomething; - } - - throw new IllegalStateException("Target wasn't handled in computer's choose method: " + target.getClass().getCanonicalName()); - } //end of choose method - - @Override - public boolean chooseTarget(Outcome outcome, Target target, Ability source, Game game) { - if (log.isDebugEnabled()) { - log.debug("chooseTarget: " + outcome.toString() + ':' + target.toString()); - } - - boolean isAddedSomething = false; // must return true on any changes in targets, so game can ask next choose dialog until finish - - // target - real target, make all changes and add targets to it - // target.getOriginalTarget() - copy spell effect replaces original target with TargetWithAdditionalFilter - // use originalTarget to get filters and target class info - // source can be null (as example: legendary rule permanent selection) - UUID sourceId = source != null ? source.getSourceId() : null; - - // sometimes a target selection can be made from a player that does not control the ability - UUID abilityControllerId = playerId; - if (target.getAbilityController() != null) { - abilityControllerId = target.getAbilityController(); - } - - boolean required = target.isRequired(sourceId, game); - Set possibleTargets = target.possibleTargets(abilityControllerId, source, game); - if (possibleTargets.isEmpty() || target.getTargets().size() >= target.getMinNumberOfTargets()) { - required = false; - } - - List goodList = new ArrayList<>(); - List badList = new ArrayList<>(); - List allList = new ArrayList<>(); - - UUID randomOpponentId = getRandomOpponent(game); - - if (target.getOriginalTarget() instanceof TargetPlayer) { - return selectPlayerTarget(outcome, target, source, abilityControllerId, randomOpponentId, game, required); - } - - // Angel of Serenity trigger - if (target.getOriginalTarget() instanceof TargetCardInGraveyardBattlefieldOrStack) { - List cards = new ArrayList<>(new CardsImpl(possibleTargets).getCards(game)); - isAddedSomething = false; - for (Card card : cards) { - // check permanents first; they have more intrinsic worth - if (card instanceof Permanent) { - Permanent p = ((Permanent) card); - if (outcome.isGood() - && p.isControlledBy(abilityControllerId)) { - if (target.canTarget(abilityControllerId, p.getId(), source, game) && !target.contains(p.getId())) { - if (target.getTargets().size() >= target.getMaxNumberOfTargets()) { - break; - } - target.addTarget(p.getId(), source, game); - isAddedSomething = true; - if (target.isChoiceCompleted(game)) { - return true; - } - } - } - if (!outcome.isGood() - && !p.isControlledBy(abilityControllerId)) { - if (target.canTarget(abilityControllerId, p.getId(), source, game) && !target.contains(p.getId())) { - if (target.getTargets().size() >= target.getMaxNumberOfTargets()) { - break; - } - target.addTarget(p.getId(), source, game); - isAddedSomething = true; - if (target.isChoiceCompleted(game)) { - return true; - } - } - } - } - // check the graveyards last - if (game.getState().getZone(card.getId()) == Zone.GRAVEYARD) { - if (outcome.isGood() - && card.isOwnedBy(abilityControllerId)) { - if (target.canTarget(abilityControllerId, card.getId(), source, game) && !target.contains(card.getId())) { - if (target.getTargets().size() >= target.getMaxNumberOfTargets()) { - break; - } - target.addTarget(card.getId(), source, game); - isAddedSomething = true; - if (target.isChoiceCompleted(game)) { - return true; - } - } - } - if (!outcome.isGood() - && !card.isOwnedBy(abilityControllerId)) { - if (target.canTarget(abilityControllerId, card.getId(), source, game) && !target.contains(card.getId())) { - if (target.getTargets().size() >= target.getMaxNumberOfTargets()) { - break; - } - target.addTarget(card.getId(), source, game); - isAddedSomething = true; - if (target.isChoiceCompleted(game)) { - return true; - } - } - } - } - } - return isAddedSomething; - } - - if (target.getOriginalTarget() instanceof TargetDiscard - || target.getOriginalTarget() instanceof TargetCardInHand) { - isAddedSomething = false; - if (outcome.isGood()) { - // good - Cards cards = new CardsImpl(possibleTargets); - List cardsInHand = new ArrayList<>(cards.getCards(game)); - while (!target.isChosen(game) - && !cardsInHand.isEmpty() - && target.getMaxNumberOfTargets() > target.getTargets().size()) { - Card card = selectBestCardTarget(cardsInHand, Collections.emptyList(), target, source, game); - if (card != null) { - if (target.canTarget(abilityControllerId, card.getId(), source, game) && !target.contains(card.getId())) { - target.addTarget(card.getId(), source, game); - isAddedSomething = true; - cardsInHand.remove(card); - if (target.isChoiceCompleted(game)) { - return true; - } - } - } - } - } else { - // bad - findPlayables(game); - for (Card card : unplayable.values()) { - if (possibleTargets.contains(card.getId()) - && target.canTarget(abilityControllerId, card.getId(), source, game) - && !target.contains(card.getId())) { - target.addTarget(card.getId(), source, game); - isAddedSomething = true; - if (target.isChoiceCompleted(game)) { - return true; - } - } - } - if (!hand.isEmpty()) { - for (Card card : hand.getCards(game)) { - if (possibleTargets.contains(card.getId()) - && target.canTarget(abilityControllerId, card.getId(), source, game) - && !target.contains(card.getId())) { - target.addTarget(card.getId(), source, game); - isAddedSomething = true; - if (target.isChoiceCompleted(game)) { - return true; - } - } - } - } - } - return isAddedSomething; - } - - if (target.getOriginalTarget() instanceof TargetControlledPermanent - || target.getOriginalTarget() instanceof TargetSacrifice) { - TargetPermanent origTarget = (TargetPermanent) target.getOriginalTarget(); - List targets; - targets = threats(abilityControllerId, source, origTarget.getFilter(), game, target.getTargets()); - if (!outcome.isGood()) { - Collections.reverse(targets); - } - isAddedSomething = false; - for (Permanent permanent : targets) { - if (target.canTarget(abilityControllerId, permanent.getId(), source, game) && !target.contains(permanent.getId())) { - target.addTarget(permanent.getId(), source, game); - isAddedSomething = true; - if (target.getMinNumberOfTargets() <= target.getTargets().size() && (!outcome.isGood() || target.getMaxNumberOfTargets() <= target.getTargets().size())) { - return true; // TODO: need research - is it good optimization for good/bad effects? - } - } - } - return isAddedSomething; - - } - - // TODO: implemented findBestPlayerTargets - // TODO: add findBest*Targets for all target types - // TODO: Much of this code needs to be re-written to move code into Target.possibleTargets - // A) Having it here makes this function ridiculously long - // B) Each time a new target type is added, people must remember to add it here - if (target.getOriginalTarget() instanceof TargetPermanent) { - FilterPermanent filter = null; - if (target.getOriginalTarget().getFilter() instanceof FilterPermanent) { - filter = (FilterPermanent) target.getOriginalTarget().getFilter(); - } - if (filter == null) { - throw new IllegalStateException("Unsupported permanent filter in computer's chooseTarget method: " - + target.getOriginalTarget().getClass().getCanonicalName()); - } - - findBestPermanentTargets(outcome, abilityControllerId, sourceId, source, filter, - game, target, goodList, badList, allList); - - // use good list all the time and add maximum targets - isAddedSomething = false; - for (Permanent permanent : goodList) { - if (target.canTarget(abilityControllerId, permanent.getId(), source, game) && !target.contains(permanent.getId())) { - if (target.getTargets().size() >= target.getMaxNumberOfTargets()) { - break; - } - target.addTarget(permanent.getId(), source, game); - isAddedSomething = true; - } - } - - // use bad list only on required target and add minimum targets - if (required) { - for (Permanent permanent : badList) { - if (target.canTarget(abilityControllerId, permanent.getId(), source, game) && !target.contains(permanent.getId())) { - if (target.getTargets().size() >= target.getMinNumberOfTargets()) { - break; - } - target.addTarget(permanent.getId(), source, game); - isAddedSomething = true; - } - } - } - return isAddedSomething; - } - - if (target.getOriginalTarget() instanceof TargetAnyTarget) { - List targets; - TargetAnyTarget origTarget = ((TargetAnyTarget) target.getOriginalTarget()); - if (outcome.isGood()) { - targets = threats(abilityControllerId, source, ((FilterAnyTarget) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets()); - } else { - targets = threats(randomOpponentId, source, ((FilterAnyTarget) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets()); - } - - if (targets.isEmpty()) { - if (outcome.isGood()) { - if (target.canTarget(abilityControllerId, getId(), source, game) && !target.contains(getId())) { - return tryAddTarget(target, getId(), source, game); - } - } else if (target.canTarget(abilityControllerId, randomOpponentId, source, game) && !target.contains(randomOpponentId)) { - return tryAddTarget(target, randomOpponentId, source, game); - } - } - - if (targets.isEmpty() && required) { - targets = game.getBattlefield().getActivePermanents(((FilterAnyTarget) origTarget.getFilter()).getPermanentFilter(), playerId, game); - } - for (Permanent permanent : targets) { - List alreadyTargeted = target.getTargets(); - if (target.canTarget(abilityControllerId, permanent.getId(), source, game) && !target.contains(permanent.getId())) { - if (alreadyTargeted != null && !alreadyTargeted.contains(permanent.getId())) { - tryAddTarget(target, permanent.getId(), source, game); - } - } - } - - if (outcome.isGood()) { - if (target.canTarget(abilityControllerId, getId(), source, game) && !target.contains(getId())) { - return tryAddTarget(target, getId(), source, game); - } - } else if (target.canTarget(abilityControllerId, randomOpponentId, source, game) && !target.contains(randomOpponentId)) { - return tryAddTarget(target, randomOpponentId, source, game); - } - - //if (!target.isRequired()) - return false; - } - - if (target.getOriginalTarget() instanceof TargetPermanentOrPlayer) { - List targets; - TargetPermanentOrPlayer origTarget = ((TargetPermanentOrPlayer) target.getOriginalTarget()); - if (outcome.isGood()) { - targets = threats(abilityControllerId, source, ((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets()); - } else { - targets = threats(randomOpponentId, source, ((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets()); - } - - if (targets.isEmpty()) { - if (outcome.isGood()) { - if (target.canTarget(abilityControllerId, getId(), source, game) && !target.contains(getId())) { - return tryAddTarget(target, getId(), source, game); - } - } else if (target.canTarget(abilityControllerId, randomOpponentId, source, game) && !target.contains(randomOpponentId)) { - return tryAddTarget(target, randomOpponentId, source, game); - } - } - - if (targets.isEmpty() && target.isRequired(source)) { - targets = game.getBattlefield().getActivePermanents(((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), playerId, game); - } - for (Permanent permanent : targets) { - List alreadyTargeted = target.getTargets(); - if (target.canTarget(abilityControllerId, permanent.getId(), source, game) && !target.contains(permanent.getId())) { - if (alreadyTargeted != null && !alreadyTargeted.contains(permanent.getId())) { - return tryAddTarget(target, permanent.getId(), source, game); - } - } - } - } - - if (target.getOriginalTarget() instanceof TargetPlayerOrPlaneswalker - || target.getOriginalTarget() instanceof TargetOpponentOrPlaneswalker) { - List targets; - TargetPermanentOrPlayer origTarget = ((TargetPermanentOrPlayer) target.getOriginalTarget()); - - // TODO: in multiplayer game there many opponents - if random opponents don't have targets then AI must use next opponent, but it skips - // (e.g. you randomOpponentId must be replaced by List randomOpponents) - // normal cycle (good for you, bad for opponents) - // possible good/bad permanents - if (outcome.isGood()) { - targets = threats(abilityControllerId, source, ((FilterPermanentOrPlayer) target.getFilter()).getPermanentFilter(), game, target.getTargets()); - } else { - targets = threats(randomOpponentId, source, ((FilterPermanentOrPlayer) target.getFilter()).getPermanentFilter(), game, target.getTargets()); - } - - // possible good/bad players - if (targets.isEmpty()) { - if (outcome.isGood()) { - if (target.canTarget(abilityControllerId, getId(), source, game) && !target.contains(getId())) { - return tryAddTarget(target, getId(), source, game); - } - } else if (target.canTarget(abilityControllerId, randomOpponentId, source, game) && !target.contains(randomOpponentId)) { - return tryAddTarget(target, randomOpponentId, source, game); - } - } - - // can't find targets (e.g. effect is bad, but you need take targets from yourself) - if (targets.isEmpty() && required) { - targets = game.getBattlefield().getActivePermanents(origTarget.getFilterPermanent(), playerId, game); - } - - // try target permanent - for (Permanent permanent : targets) { - if (target.canTarget(abilityControllerId, permanent.getId(), source, game) && !target.contains(permanent.getId())) { - return tryAddTarget(target, permanent.getId(), source, game); - } - } - - // try target player as normal - if (outcome.isGood()) { - if (target.canTarget(abilityControllerId, getId(), source, game) && !target.contains(getId())) { - return tryAddTarget(target, getId(), source, game); - } - } else if (target.canTarget(abilityControllerId, randomOpponentId, source, game) && !target.contains(randomOpponentId)) { - return tryAddTarget(target, randomOpponentId, source, game); - } - - // try target player as bad (bad on itself, good on opponent) - for (UUID opponentId : game.getOpponents(getId(), true)) { - if (target.canTarget(abilityControllerId, opponentId, source, game) && !target.contains(opponentId)) { - return tryAddTarget(target, opponentId, source, game); - } - } - if (target.canTarget(abilityControllerId, getId(), source, game) && !target.contains(getId())) { - return tryAddTarget(target, getId(), source, game); - } - - return false; - } - - if (target.getOriginalTarget() instanceof TargetCardInGraveyard) { - List cards = new ArrayList<>(); - for (Player player : game.getPlayers().values()) { - cards.addAll(player.getGraveyard().getCards(game)); - } - Card card = selectCardTarget(abilityControllerId, cards, outcome, target, source, game); - if (card != null && !target.contains(card.getId())) { - return tryAddTarget(target, card.getId(), source, game); - } - //if (!target.isRequired()) - return false; - } - - if (target.getOriginalTarget() instanceof TargetCardInLibrary) { - List cards = new ArrayList<>(game.getPlayer(abilityControllerId).getLibrary().getCards(game)); - Card card = selectCardTarget(abilityControllerId, cards, outcome, target, source, game); - if (card != null && !target.contains(card.getId())) { - return tryAddTarget(target, card.getId(), source, game); - } - return false; - } - - if (target.getOriginalTarget() instanceof TargetCardInYourGraveyard) { - List cards = new ArrayList<>(game.getPlayer(abilityControllerId).getGraveyard().getCards((FilterCard) target.getFilter(), game)); - isAddedSomething = false; - while (!target.isChosen(game) && !cards.isEmpty()) { - Card card = selectCardTarget(abilityControllerId, cards, outcome, target, source, game); - if (card != null) { - cards.remove(card); // selectCard don't remove cards (only on second+ tries) - if (!target.contains(card.getId())) { - target.addTarget(card.getId(), source, game); // TODO: why it add as much as possible instead go to isChosen check like above in choose? - isAddedSomething = true; - if (target.isChoiceCompleted(game)) { - return true; - } - } - } else { - break; - } - } - return isAddedSomething; - } - - if (target.getOriginalTarget() instanceof TargetSpell - || target.getOriginalTarget() instanceof TargetStackObject) { - if (!game.getStack().isEmpty()) { - for (StackObject o : game.getStack()) { - if (o instanceof Spell - && !source.getId().equals(o.getStackAbility().getId()) - && target.canTarget(abilityControllerId, o.getStackAbility().getId(), source, game) - && !target.contains(o.getId())) { - return tryAddTarget(target, o.getId(), source, game); - } - } - } - return false; - } - - if (target.getOriginalTarget() instanceof TargetSpellOrPermanent) { - // TODO: Also check if a spell should be selected - TargetSpellOrPermanent origTarget = (TargetSpellOrPermanent) target.getOriginalTarget(); - List targets; - boolean outcomeTargets = true; - if (outcome.isGood()) { - targets = threats(abilityControllerId, source, origTarget.getPermanentFilter(), game, target.getTargets()); - } else { - targets = threats(randomOpponentId, source, origTarget.getPermanentFilter(), game, target.getTargets()); - } - if (targets.isEmpty() && required) { - targets = threats(null, source, origTarget.getPermanentFilter(), game, target.getTargets()); - Collections.reverse(targets); - outcomeTargets = false; - } - for (Permanent permanent : targets) { - if (target.canTarget(abilityControllerId, permanent.getId(), source, game) && !target.contains(permanent.getId())) { - target.addTarget(permanent.getId(), source, game); - if (!outcomeTargets || target.getMaxNumberOfTargets() <= target.getTargets().size()) { - return true; // TODO: need logic research (e.g. select as much as possible on good outcome?) - } - } - } - if (!game.getStack().isEmpty()) { - for (StackObject stackObject : game.getStack()) { - if (stackObject instanceof Spell && source != null && !source.getId().equals(stackObject.getStackAbility().getId())) { - if (target.getFilter().match(stackObject, game) && !target.contains(stackObject.getId())) { - return tryAddTarget(target, stackObject.getId(), source, game); - } - } - } - } - return false; - } - - if (target.getOriginalTarget() instanceof TargetCardInOpponentsGraveyard) { - List cards = new ArrayList<>(); - for (UUID uuid : game.getOpponents(getId(), true)) { - Player player = game.getPlayer(uuid); - if (player != null) { - cards.addAll(player.getGraveyard().getCards(game)); - } - } - isAddedSomething = false; - while (!cards.isEmpty()) { - Card card = selectCardTarget(abilityControllerId, cards, outcome, target, source, game); - if (card != null) { - cards.remove(card); // selectCard don't remove cards (only on second+ tries) - if (!target.contains(card.getId())) { - isAddedSomething = true; - target.addTarget(card.getId(), source, game); - if (target.isChoiceCompleted(game)) { - return true; - } - } - } else { - break; - } - } - //if (!target.isRequired()) - return isAddedSomething; - } - - if (target.getOriginalTarget() instanceof TargetDefender) { - List targets = new ArrayList<>(possibleTargets); - isAddedSomething = false; - while (!targets.isEmpty()) { - UUID randomDefender = RandomUtil.randomFromCollection(possibleTargets); - if (randomDefender != null) { - targets.remove(randomDefender); - if (!target.contains(randomDefender)) { - isAddedSomething = true; - target.addTarget(randomDefender, source, game); - if (target.isChoiceCompleted(game)) { - return true; - } - } - } else { - break; - } - } - return isAddedSomething; - } - - if (target.getOriginalTarget() instanceof TargetCardInASingleGraveyard) { - List cards = new ArrayList<>(); - for (Player player : game.getPlayers().values()) { - cards.addAll(player.getGraveyard().getCards(game)); - } - isAddedSomething = false; - while (!cards.isEmpty()) { - Card card = selectCardTarget(abilityControllerId, cards, outcome, target, source, game); - if (card != null) { - cards.remove(card); // selectCard don't remove cards (only on second+ tries) - if (!target.contains(card.getId())) { - isAddedSomething = true; - target.addTarget(card.getId(), source, game); - if (target.isChoiceCompleted(game)) { - return true; - } - } - } else { - break; - } - } - return isAddedSomething; - } - - if (target.getOriginalTarget() instanceof TargetCardInExile) { - FilterCard filter = null; - if (target.getOriginalTarget().getFilter() instanceof FilterCard) { - filter = (FilterCard) target.getOriginalTarget().getFilter(); - } - if (filter == null) { - throw new IllegalStateException("Unsupported exile target filter in computer's chooseTarget method: " - + target.getOriginalTarget().getClass().getCanonicalName()); - } - - List cards = new ArrayList<>(); - for (UUID uuid : target.possibleTargets(source.getControllerId(), source, game)) { - Card card = game.getCard(uuid); - if (card != null && game.getState().getZone(card.getId()) == Zone.EXILED) { - cards.add(card); - } - } - isAddedSomething = false; - while (!cards.isEmpty()) { - Card card = selectCardTarget(abilityControllerId, cards, outcome, target, source, game); - if (card != null) { - cards.remove(card); // selectCard don't remove cards (only on second+ tries) - if (!target.contains(card.getId())) { - isAddedSomething = true; - target.addTarget(card.getId(), source, game); - if (target.isChoiceCompleted(game)) { - return true; - } - } - } else { - break; - } - } - return isAddedSomething; - } - - if (target.getOriginalTarget() instanceof TargetActivatedAbility) { - List stackObjects = new ArrayList<>(); - for (UUID uuid : target.possibleTargets(source.getControllerId(), source, game)) { - StackObject stackObject = game.getStack().getStackObject(uuid); - if (stackObject != null) { - stackObjects.add(stackObject); - } - } - while (!stackObjects.isEmpty()) { - StackObject pick = stackObjects.get(0); - if (pick != null) { - stackObjects.remove(0); - if (!target.contains(pick.getId())) { - isAddedSomething = true; - target.addTarget(pick.getId(), source, game); - if (target.isChoiceCompleted(game)) { - return true; - } - } - } else { - break; - } - } - return isAddedSomething; - } - - if (target.getOriginalTarget() instanceof TargetActivatedOrTriggeredAbility) { - List targets = new ArrayList<>(target.possibleTargets(source.getControllerId(), source, game)); - isAddedSomething = false; - while (!targets.isEmpty()) { - UUID id = targets.get(0); - if (id != null) { - targets.remove(0); - if (!target.contains(id)) { - isAddedSomething = true; - target.addTarget(id, source, game); - if (target.isChoiceCompleted(game)) { - return true; - } - } - } else { - break; - } - } - return isAddedSomething; - } - - if (target.getOriginalTarget() instanceof TargetCardInGraveyardBattlefieldOrStack) { - List cards = new ArrayList<>(); - for (Player player : game.getPlayers().values()) { - cards.addAll(player.getGraveyard().getCards(game)); - cards.addAll(game.getBattlefield().getAllActivePermanents(new FilterPermanent(), player.getId(), game)); - } - while (!cards.isEmpty()) { - Card card = selectCardTarget(abilityControllerId, cards, outcome, target, source, game); - if (card != null) { - cards.remove(card); // selectCard don't remove cards (only on second+ tries) - if (!target.contains(card.getId())) { - isAddedSomething = true; - target.addTarget(card.getId(), source, game); - if (target.isChoiceCompleted(game)) { - return true; - } - } - } else { - break; - } - } - } - - if (target.getOriginalTarget() instanceof TargetPermanentOrSuspendedCard) { - List cards = new ArrayList<>(new CardsImpl(possibleTargets).getCards(game)); - isAddedSomething = false; - while (!cards.isEmpty()) { - Card card = selectCardTarget(abilityControllerId, cards, outcome, target, source, game); - if (card != null) { - cards.remove(card); // selectCard don't remove cards (only on second+ tries) - if (!target.contains(card.getId())) { - isAddedSomething = true; - target.addTarget(card.getId(), source, game); - if (target.isChoiceCompleted(game)) { - return true; - } - } - } else { - break; - } - } - return isAddedSomething; - } - - throw new IllegalStateException("Target wasn't handled in computer's chooseTarget method: " + target.getClass().getCanonicalName()); - } //end of chooseTarget method - - protected Card selectCard(UUID abilityControllerId, List cards, Outcome outcome, Target target, Game game) { - return selectCardInner(abilityControllerId, cards, outcome, target, null, game); - } - - protected Card selectCardTarget(UUID abilityControllerId, List cards, Outcome outcome, Target target, Ability targetingSource, Game game) { - return selectCardInner(abilityControllerId, cards, outcome, target, targetingSource, game); + return makeChoice(outcome, target, source, game, null); } /** - * @param targetingSource null on non-target choice like choose and source on targeting choice like chooseTarget + * Default choice logic for any choose dialogs due effect's outcome and possible target priority */ - protected Card selectCardInner(UUID abilityControllerId, List cards, Outcome outcome, Target target, Ability targetingSource, Game game) { - Card card; - while (!cards.isEmpty()) { - if (outcome.isGood()) { - card = selectBestCardInner(cards, Collections.emptyList(), target, targetingSource, game); - } else { - card = selectWorstCardInner(cards, Collections.emptyList(), target, targetingSource, game); - } - if (!target.getTargets().contains(card.getId())) { - if (targetingSource != null) { - if (target.canTarget(abilityControllerId, card.getId(), targetingSource, game)) { - return card; - } - } else { - return card; - } - } - cards.remove(card); // TODO: research parent code - is it depends on original list? Can be bugged + private boolean makeChoice(Outcome outcome, Target target, Ability source, Game game, Cards fromCards) { + // choose itself for starting player all the time + if (target.getMessage(game).equals("Select a starting player")) { + target.add(this.getId(), game); + return true; } - return null; + + // nothing to choose + if (fromCards != null && fromCards.isEmpty()) { + return false; + } + + UUID abilityControllerId = target.getAffectedAbilityControllerId(getId()); + + // nothing to choose, e.g. X=0 + if (target.isChoiceCompleted(abilityControllerId, source, game)) { + return false; + } + + // default logic for any targets + PossibleTargetsSelector possibleTargetsSelector = new PossibleTargetsSelector(outcome, target, abilityControllerId, source, game); + possibleTargetsSelector.findNewTargets(fromCards); + // good targets -- choose as much as possible + for (MageItem item : possibleTargetsSelector.getGoodTargets()) { + target.add(item.getId(), game); + if (target.isChoiceCompleted(abilityControllerId, source, game)) { + return true; + } + } + // bad targets -- choose as low as possible + for (MageItem item : possibleTargetsSelector.getBadTargets()) { + if (target.isChosen(game)) { + break; + } + target.add(item.getId(), game); + } + + return target.isChosen(game) && !target.getTargets().isEmpty(); + } + + /** + * Default choice logic for X or amount values + */ + private int makeChoiceAmount(int min, int max, Game game, Ability source, boolean isManaPay) { + // fast calc on nothing to choose + if (min >= max) { + return min; + } + + // TODO: add good/bad effects support + // TODO: add simple game simulations like declare blocker (need to find only workable payment)? + // TODO: remove random logic or make it more stable (e.g. use same value in same game cycle) + + // protection from too big values + int realMin = min; + int realMax = max; + if (max == Integer.MAX_VALUE) { + realMax = Math.max(realMin, 10); // AI don't need huge values for X, cause can't use infinite combos + } + + int xValue; + if (isManaPay) { + // as X mana payment - due available mana + xValue = Math.max(0, getAvailableManaProducers(game).size() - source.getManaCostsToPay().getUnpaid().manaValue()); + } else { + // as X actions + xValue = RandomUtil.nextInt(realMax + 1); + } + + if (xValue > realMax) { + xValue = realMax; + } + if (xValue < realMin) { + xValue = realMin; + } + + return xValue; + } + + @Override + public boolean chooseTarget(Outcome outcome, Target target, Ability source, Game game) { + return makeChoice(outcome, target, source, game, null); } @Override public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game) { - // TODO: make same code for chooseTarget (without filter and target type dependence) - if (log.isDebugEnabled()) { - log.debug("chooseTarget: " + outcome.toString() + ':' + target.toString()); - } - UUID sourceId = source != null ? source.getSourceId() : null; - - // sometimes a target selection can be made from a player that does not control the ability - UUID abilityControllerId = playerId; - if (target.getTargetController() != null - && target.getAbilityController() != null) { - abilityControllerId = target.getAbilityController(); - } - - // process multiple opponents by random - List opponents = new ArrayList<>(game.getOpponents(getId(), true)); - Collections.shuffle(opponents); - - List targets; - - // ONE KILL PRIORITY: player -> planeswalker -> creature - if (outcome == Outcome.Damage) { - // player kill - for (UUID opponentId : opponents) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null - && target.canTarget(abilityControllerId, opponentId, source, game) - && opponent.getLife() <= target.getAmountRemaining()) { - return tryAddTarget(target, opponentId, opponent.getLife(), source, game); - } - } - - // permanents kill - for (UUID opponentId : opponents) { - targets = threats(opponentId, source, StaticFilters.FILTER_PERMANENT_CREATURE_OR_PLANESWALKER_A, game, target.getTargets()); - - // planeswalker kill - for (Permanent permanent : targets) { - if (permanent.isPlaneswalker(game) && target.canTarget(abilityControllerId, permanent.getId(), source, game)) { - int loy = permanent.getCounters(game).getCount(CounterType.LOYALTY); - if (loy <= target.getAmountRemaining()) { - return tryAddTarget(target, permanent.getId(), loy, source, game); - } - } - } - - // creature kill - for (Permanent permanent : targets) { - if (permanent.isCreature(game) && target.canTarget(abilityControllerId, permanent.getId(), source, game)) { - if (permanent.getToughness().getValue() <= target.getAmountRemaining()) { - return tryAddTarget(target, permanent.getId(), permanent.getToughness().getValue(), source, game); - } - } - } - } - } - - // NORMAL PRIORITY: planeswalker -> player -> creature - // own permanents will be checked multiple times... that's ok - for (UUID opponentId : opponents) { - if (outcome.isGood()) { - targets = threats(getId(), source, StaticFilters.FILTER_PERMANENT, game, target.getTargets()); - } else { - targets = threats(opponentId, source, StaticFilters.FILTER_PERMANENT, game, target.getTargets()); - } - - // planeswalkers - for (Permanent permanent : targets) { - if (permanent.isPlaneswalker(game) && target.canTarget(abilityControllerId, permanent.getId(), source, game)) { - return tryAddTarget(target, permanent.getId(), target.getAmountRemaining(), source, game); - } - } - - // players - if (outcome.isGood() && target.canTarget(abilityControllerId, getId(), source, game)) { - return tryAddTarget(target, getId(), target.getAmountRemaining(), source, game); - } - if (!outcome.isGood() && target.canTarget(abilityControllerId, opponentId, source, game)) { - return tryAddTarget(target, opponentId, target.getAmountRemaining(), source, game); - } - - // creature - for (Permanent permanent : targets) { - if (permanent.isCreature(game) && target.canTarget(abilityControllerId, permanent.getId(), source, game)) { - return tryAddTarget(target, permanent.getId(), target.getAmountRemaining(), source, game); - } - } - } - - // BAD PRIORITY, e.g. need bad target on yourself or good target on opponent - // priority: creature (non killable, killable) -> planeswalker -> player - if (!target.isRequired(sourceId, game)) { + // nothing to choose, e.g. X=0 + target.prepareAmount(source, game); + if (target.getAmountRemaining() <= 0) { + return false; + } + if (target.getMaxNumberOfTargets() == 0 && target.getMinNumberOfTargets() == 0) { return false; } - for (UUID opponentId : opponents) { - if (!outcome.isGood()) { - // bad on yourself, uses the weakest targets - targets = threats(getId(), source, StaticFilters.FILTER_PERMANENT, game, target.getTargets(), false); - } else { - targets = threats(opponentId, source, StaticFilters.FILTER_PERMANENT, game, target.getTargets(), false); - } - // creatures - non killable (TODO: add extra skill checks like undestructeable) - for (Permanent permanent : targets) { - if (permanent.isCreature(game) && target.canTarget(abilityControllerId, permanent.getId(), source, game)) { - int safeDamage = Math.min(permanent.getToughness().getValue() - 1, target.getAmountRemaining()); - if (safeDamage > 0) { - return tryAddTarget(target, permanent.getId(), safeDamage, source, game); + UUID abilityControllerId = target.getAffectedAbilityControllerId(getId()); + + // nothing to choose, e.g. X=0 + if (target.isChoiceCompleted(abilityControllerId, source, game)) { + return false; + } + + PossibleTargetsSelector possibleTargetsSelector = new PossibleTargetsSelector(outcome, target, abilityControllerId, source, game); + possibleTargetsSelector.findNewTargets(null); + + // nothing to choose, e.g. no valid targets + if (!possibleTargetsSelector.hasAnyTargets()) { + return false; + } + + // KILL PRIORITY + if (outcome == Outcome.Damage) { + // opponent first + for (MageItem item : possibleTargetsSelector.getGoodTargets()) { + if (target.getAmountRemaining() <= 0) { + break; + } + if (target.contains(item.getId()) || !(item instanceof Player)) { + continue; + } + int leftLife = PossibleTargetsComparator.getLifeForDamage(item, game); + if (leftLife > 0 && leftLife <= target.getAmountRemaining()) { + target.addTarget(item.getId(), leftLife, source, game); + if (target.isChoiceCompleted(abilityControllerId, source, game)) { + return true; } } } - // creatures - all - for (Permanent permanent : targets) { - if (permanent.isCreature(game) && target.canTarget(abilityControllerId, permanent.getId(), source, game)) { - return tryAddTarget(target, permanent.getId(), target.getAmountRemaining(), source, game); + // opponent's creatures second + for (MageItem item : possibleTargetsSelector.getGoodTargets()) { + if (target.getAmountRemaining() <= 0) { + break; + } + if (target.contains(item.getId()) || (item instanceof Player)) { + continue; + } + int leftLife = PossibleTargetsComparator.getLifeForDamage(item, game); + if (leftLife > 0 && leftLife <= target.getAmountRemaining()) { + target.addTarget(item.getId(), leftLife, source, game); + if (target.isChoiceCompleted(abilityControllerId, source, game)) { + return true; + } } } - // planeswalkers - for (Permanent permanent : targets) { - if (permanent.isPlaneswalker(game) && target.canTarget(abilityControllerId, permanent.getId(), source, game)) { - return tryAddTarget(target, permanent.getId(), target.getAmountRemaining(), source, game); + // opponent's any + for (MageItem item : possibleTargetsSelector.getGoodTargets()) { + if (target.getAmountRemaining() <= 0) { + break; + } + if (target.contains(item.getId())) { + continue; + } + target.addTarget(item.getId(), target.getAmountRemaining(), source, game); + if (target.isChoiceCompleted(abilityControllerId, source, game)) { + return true; } } + + // own - non-killable + for (MageItem item : possibleTargetsSelector.getBadTargets()) { + if (target.getAmountRemaining() <= 0) { + break; + } + if (target.contains(item.getId())) { + continue; + } + // stop as fast as possible on bad outcome + if (target.isChosen(game)) { + return !target.getTargets().isEmpty(); + } + int leftLife = PossibleTargetsComparator.getLifeForDamage(item, game); + if (leftLife > 1) { + target.addTarget(item.getId(), Math.min(leftLife - 1, target.getAmountRemaining()), source, game); + if (target.isChoiceCompleted(abilityControllerId, source, game)) { + return true; + } + } + } + + // own - any + for (MageItem item : possibleTargetsSelector.getBadTargets()) { + if (target.getAmountRemaining() <= 0) { + break; + } + if (target.contains(item.getId())) { + continue; + } + // stop as fast as possible on bad outcome + if (target.isChosen(game)) { + return !target.getTargets().isEmpty(); + } + target.addTarget(item.getId(), target.getAmountRemaining(), source, game); + if (target.isChoiceCompleted(abilityControllerId, source, game)) { + return true; + } + } + + return target.isChosen(game); } - // players - for (UUID opponentId : opponents) { - if (target.canTarget(abilityControllerId, getId(), source, game)) { - // on itself - return tryAddTarget(target, getId(), target.getAmountRemaining(), source, game); - } else if (target.canTarget(abilityControllerId, opponentId, source, game)) { - // on opponent - return tryAddTarget(target, opponentId, target.getAmountRemaining(), source, game); + + // non-damage effect like counters - give all to first valid item + for (MageItem item : possibleTargetsSelector.getGoodTargets()) { + if (target.getAmountRemaining() <= 0) { + break; + } + if (target.contains(item.getId())) { + continue; + } + target.addTarget(item.getId(), target.getAmountRemaining(), source, game); + if (target.isChoiceCompleted(abilityControllerId, source, game)) { + return true; + } + } + for (MageItem item : possibleTargetsSelector.getBadTargets()) { + if (target.getAmountRemaining() <= 0) { + break; + } + if (target.contains(item.getId())) { + continue; + } + // stop as fast as possible on bad outcome + if (target.isChosen(game)) { + return !target.getTargets().isEmpty(); + } + target.addTarget(item.getId(), target.getAmountRemaining(), source, game); + if (target.isChoiceCompleted(abilityControllerId, source, game)) { + return true; } } - // it's ok on no targets available - log.warn("No proper AI target handling or can't find permanents/cards to target: " + target.getClass().getName()); - return false; + return target.isChosen(game) && !target.getTargets().isEmpty(); } @Override public boolean priority(Game game) { - game.resumeTimer(getTurnControlledBy()); - boolean result = priorityPlay(game); - game.pauseTimer(getTurnControlledBy()); - return result; - } - - private boolean priorityPlay(Game game) { - UUID opponentId = getRandomOpponent(game); - if (game.isActivePlayer(playerId)) { - if (game.isMainPhase() && game.getStack().isEmpty()) { - playLand(game); - } - switch (game.getTurnStepType()) { - case UPKEEP: - // TODO: is it needs here? Need research (e.g. for better choose in upkeep triggers)? - findPlayables(game); - break; - case DRAW: - break; - case PRECOMBAT_MAIN: - findPlayables(game); - if (!playableAbilities.isEmpty()) { - for (ActivatedAbility ability : playableAbilities) { - if (ability.canActivate(playerId, game).canActivate()) { - if (ability.getEffects().hasOutcome(ability, Outcome.PutLandInPlay)) { - if (this.activateAbility(ability, game)) { - return true; - } - } - if (ability.getEffects().hasOutcome(ability, Outcome.PutCreatureInPlay)) { - if (getOpponentBlockers(opponentId, game).size() <= 1) { - if (this.activateAbility(ability, game)) { - return true; - } - } - } - } - } - } - break; - case DECLARE_BLOCKERS: - findPlayables(game); - playRemoval(game.getCombat().getBlockers(), game); - playDamage(game.getCombat().getBlockers(), game); - break; - case END_COMBAT: - findPlayables(game); - playDamage(game.getCombat().getBlockers(), game); - break; - case POSTCOMBAT_MAIN: - findPlayables(game); - if (game.getStack().isEmpty()) { - if (!playableNonInstant.isEmpty()) { - for (Card card : playableNonInstant) { - if (card.getSpellAbility().canActivate(playerId, game).canActivate()) { - if (this.activateAbility(card.getSpellAbility(), game)) { - return true; - } - } - } - } - if (!playableAbilities.isEmpty()) { - for (ActivatedAbility ability : playableAbilities) { - if (ability.canActivate(playerId, game).canActivate()) { - if (!(ability.getEffects().get(0) instanceof BecomesCreatureSourceEffect)) { - if (this.activateAbility(ability, game)) { - return true; - } - } - } - } - } - } - break; - } - } else { - //respond to opponent events - switch (game.getTurnStepType()) { - case UPKEEP: - findPlayables(game); - break; - case DECLARE_ATTACKERS: - findPlayables(game); - playRemoval(game.getCombat().getAttackers(), game); - playDamage(game.getCombat().getAttackers(), game); - break; - case END_COMBAT: - findPlayables(game); - playDamage(game.getCombat().getAttackers(), game); - break; - } - } + // minimum implementation for do nothing pass(game); - return true; - } // end priorityPlay method - - protected void playLand(Game game) { - log.debug("playLand"); - Set lands = new LinkedHashSet<>(); - for (Card landCard : hand.getCards(new FilterLandCard(), game)) { - // remove lands that can not be played - boolean canPlay = false; - for (Ability ability : landCard.getAbilities(game)) { - if (ability instanceof PlayLandAbility) { - if (!game.getContinuousEffects().preventedByRuleModification(GameEvent.getEvent(GameEvent.EventType.PLAY_LAND, landCard.getId(), ability, playerId), null, game, true)) { - canPlay = true; - } - } - } - if (canPlay) { - lands.add(landCard); - } - } - while (!lands.isEmpty() && this.canPlayLand()) { - if (lands.size() == 1) { - this.playLand(lands.iterator().next(), game, false); - } else { - playALand(lands, game); - } - } - } - - protected void playALand(Set lands, Game game) { - log.debug("playALand"); - //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(game).getActivatedManaAbilities(Zone.BATTLEFIELD)) { - for (Mana netMana : ability.getNetMana(game)) { - if (netMana.enough(mana)) { - this.playLand(card, game, false); - lands.remove(card); - return; - } - } - } - } - } - //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(game).getActivatedManaAbilities(Zone.BATTLEFIELD)) { - for (Mana netMana : ability.getNetMana(game)) { - if (mana.contains(netMana)) { - this.playLand(card, game, false); - lands.remove(card); - return; - } - } - } - } - } - //play first available land - this.playLand(lands.iterator().next(), game, false); - lands.remove(lands.iterator().next()); - } - - protected void findPlayables(Game game) { - playableInstant.clear(); - playableNonInstant.clear(); - unplayable.clear(); - playableAbilities.clear(); - Set nonLands = hand.getCards(new FilterNonlandCard(), game); - ManaOptions available = getManaAvailable(game); -// available.addMana(manaPool.getMana()); - - for (Card card : nonLands) { - ManaOptions options = card.getManaCost().getOptions(); - if (!card.getManaCost().getVariableCosts().isEmpty()) { - //don't use variable mana costs unless there is at least 3 extra mana for X - for (Mana option : options) { - option.add(Mana.GenericMana(3)); - } - } - for (Mana mana : options) { - for (Mana avail : available) { - if (mana.enough(avail)) { - SpellAbility ability = card.getSpellAbility(); - GameEvent castEvent = GameEvent.getEvent(GameEvent.EventType.CAST_SPELL, ability.getId(), ability, playerId); - castEvent.setZone(game.getState().getZone(card.getMainCard().getId())); - if (ability != null && ability.canActivate(playerId, game).canActivate() - && !game.getContinuousEffects().preventedByRuleModification(castEvent, ability, game, true)) { - if (card.isInstant(game) - || card.hasAbility(FlashAbility.getInstance(), game)) { - playableInstant.add(card); - } else { - playableNonInstant.add(card); - } - } - } else if (!playableInstant.contains(card) && !playableNonInstant.contains(card)) { - unplayable.put(mana.needed(avail), card); - } - } - } - } - // TODO: wtf?! change to player.getPlayable - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(playerId)) { - for (ActivatedAbility ability : permanent.getAbilities().getActivatedAbilities(Zone.BATTLEFIELD)) { - if (!ability.isManaActivatedAbility() && ability.canActivate(playerId, game).canActivate()) { - if (ability instanceof EquipAbility && permanent.getAttachedTo() != null) { - continue; - } - ManaOptions abilityOptions = ability.getManaCosts().getOptions(); - if (!ability.getManaCosts().getVariableCosts().isEmpty()) { - //don't use variable mana costs unless there is at least 3 extra mana for X - for (Mana option : abilityOptions) { - option.add(Mana.GenericMana(3)); - } - } - if (abilityOptions.isEmpty()) { - playableAbilities.add(ability); - } else { - for (Mana mana : abilityOptions) { - for (Mana avail : available) { - if (mana.enough(avail)) { - playableAbilities.add(ability); - } - } - } - } - } - } - } - for (Card card : graveyard.getCards(game)) { - for (ActivatedAbility ability : card.getAbilities(game).getActivatedAbilities(Zone.GRAVEYARD)) { - if (ability.canActivate(playerId, game).canActivate()) { - ManaOptions abilityOptions = ability.getManaCosts().getOptions(); - if (abilityOptions.isEmpty()) { - playableAbilities.add(ability); - } else { - for (Mana mana : abilityOptions) { - for (Mana avail : available) { - if (mana.enough(avail)) { - playableAbilities.add(ability); - } - } - } - } - } - } - } - if (log.isDebugEnabled()) { - log.debug("findPlayables: " + playableInstant.toString() + "---" + playableNonInstant.toString() + "---" + playableAbilities.toString()); - } + return false; } @Override @@ -1702,7 +408,7 @@ public class ComputerPlayer extends PlayerImpl { for (Mana mana : manaAbility.getNetMana(game)) { // if mana ability can produce non-useful mana then ignore whole ability here (example: {R} or {G}) // (AI can't choose a good mana option, so make sure any selection option will be compatible with cost) - // AI support {Any} choice by lastUnpaidMana, so it can safly used in includesMana + // AI support {Any} choice by lastUnpaidMana, so it can safety used in includesMana if (!unpaid.getMana().includesMana(mana)) { continue ManaAbility; } else if (mana.getAny() > 0) { @@ -1807,7 +513,7 @@ public class ComputerPlayer extends PlayerImpl { } } } - // then pay colorless hybrid - more restrictive than mono hybrid + // then pay colorless hybrid - more restrictive than monohybrid for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) { if (cost instanceof ColorlessHybridManaCost) { for (Mana netMana : manaAbility.getNetMana(game)) { @@ -1825,7 +531,7 @@ public class ComputerPlayer extends PlayerImpl { } } } - // then pay mono hybrid + // then pay monohybrid for (ActivatedManaAbilityImpl manaAbility : getManaAbilitiesSortedByManaCount(mageObject, game)) { if (cost instanceof MonoHybridManaCost) { for (Mana netMana : manaAbility.getNetMana(game)) { @@ -1929,7 +635,7 @@ public class ComputerPlayer extends PlayerImpl { ); } - // cost can contains multiple mana types, must check each type (is it possible to pay a cost) + // cost can contain multiple mana types, must check each type (is it possible to pay a cost) for (ManaType checkType : ManaUtil.getManaTypesInCost(checkCost)) { // affected asThoughMana effect must fit a checkType with pool mana ManaType possibleAsThoughPoolManaType = game.getContinuousEffects().asThoughMana(checkType, possiblePoolItem, abilityToPay.getSourceId(), abilityToPay, abilityToPay.getControllerId(), game); @@ -1938,10 +644,10 @@ public class ComputerPlayer extends PlayerImpl { } boolean canPay; if (possibleAsThoughPoolManaType == ManaType.COLORLESS) { - // colorless can be payed by any color from the pool + // colorless can be paid by any color from the pool canPay = possiblePoolItem.count() > 0; } else { - // colored must be payed by specific color from the pool (AsThough already changed it to fit with mana pool) + // colored must be paid by specific color from the pool (AsThough already changed it to fit with mana pool) canPay = possiblePoolItem.get(possibleAsThoughPoolManaType) > 0; } if (canPay) { @@ -1956,23 +662,20 @@ public class ComputerPlayer extends PlayerImpl { Abilities manaAbilities = mageObject.getAbilities().getAvailableActivatedManaAbilities(Zone.BATTLEFIELD, playerId, game); if (manaAbilities.size() > 1) { // Sort mana abilities by number of produced manas, to use ability first that produces most mana (maybe also conditional if possible) - Collections.sort(manaAbilities, new Comparator() { - @Override - public int compare(ActivatedManaAbilityImpl a1, ActivatedManaAbilityImpl a2) { - int a1Max = 0; - for (Mana netMana : a1.getNetMana(game)) { - if (netMana.count() > a1Max) { - a1Max = netMana.count(); - } + Collections.sort(manaAbilities, (a1, a2) -> { + int a1Max = 0; + for (Mana netMana : a1.getNetMana(game)) { + if (netMana.count() > a1Max) { + a1Max = netMana.count(); } - int a2Max = 0; - for (Mana netMana : a2.getNetMana(game)) { - if (netMana.count() > a2Max) { - a2Max = netMana.count(); - } - } - return CardUtil.overflowDec(a2Max, a1Max); } + int a2Max = 0; + for (Mana netMana : a2.getNetMana(game)) { + if (netMana.count() > a2Max) { + a2Max = netMana.count(); + } + } + return CardUtil.overflowDec(a2Max, a1Max); }); } return manaAbilities; @@ -1988,7 +691,6 @@ public class ComputerPlayer extends PlayerImpl { * costs that can't be paid by any other producers * * @param unpaid - the amount of unpaid mana costs - * @param game * @return List */ private List getSortedProducers(ManaCosts unpaid, Game game) { @@ -2024,12 +726,7 @@ public class ComputerPlayer extends PlayerImpl { private List sortByValue(Map map) { List> list = new LinkedList<>(map.entrySet()); - Collections.sort(list, new Comparator>() { - @Override - public int compare(Entry o1, Entry o2) { - return (o1.getValue().compareTo(o2.getValue())); - } - }); + Collections.sort(list, Comparator.comparing(Entry::getValue)); List result = new ArrayList<>(); for (Entry entry : list) { result.add(entry.getKey()); @@ -2039,39 +736,7 @@ public class ComputerPlayer extends PlayerImpl { @Override public int announceX(int min, int max, String message, Game game, Ability source, boolean isManaPay) { - // fast calc on nothing to choose - if (min >= max) { - return min; - } - - // TODO: add good/bad effects support - // TODO: add simple game simulations like declare blocker (need to find only workable payment)? - // TODO: remove random logic or make it more stable (e.g. use same value in same game cycle) - - // protection from too big values - int realMin = min; - int realMax = max; - if (max == Integer.MAX_VALUE) { - realMax = Math.max(realMin, 10); // AI don't need huge values for X, cause can't use infinite combos - } - - int xValue; - if (isManaPay) { - // as X mana payment - due available mana - xValue = Math.max(0, getAvailableManaProducers(game).size() - source.getManaCostsToPay().getUnpaid().manaValue()); - } else { - // as X actions - xValue = RandomUtil.nextInt(realMax + 1); - } - - if (xValue > realMax) { - xValue = realMax; - } - if (xValue < realMin) { - xValue = realMin; - } - - return xValue; + return makeChoiceAmount(min, max, game, source, isManaPay); } @Override @@ -2085,12 +750,11 @@ public class ComputerPlayer extends PlayerImpl { @Override public boolean chooseUse(Outcome outcome, String message, Ability source, Game game) { - return this.chooseUse(outcome, message, null, null, null, source, game); + return chooseUse(outcome, message, null, null, null, source, game); } @Override public boolean chooseUse(Outcome outcome, String message, String secondMessage, String trueText, String falseText, Ability source, Game game) { - log.debug("chooseUse: " + outcome.isGood()); // Be proactive! Always use abilities, the evaluation function will decide if it's good or not // Otherwise some abilities won't be used by AI like LoseTargetEffect that has "bad" outcome // but still is good when targets opponent @@ -2099,13 +763,14 @@ public class ComputerPlayer extends PlayerImpl { @Override public boolean choose(Outcome outcome, Choice choice, Game game) { - log.debug("choose 3"); //TODO: improve this // choose creature type // TODO: WTF?! Creature types dialog text can changes, need to replace that code if (choice.getMessage() != null && (choice.getMessage().equals("Choose creature type") || choice.getMessage().equals("Choose a creature type"))) { - chooseCreatureType(outcome, choice, game); + if (chooseCreatureType(outcome, choice, game)) { + return true; + } } // choose the correct color to pay a spell (use last unpaid ability for color hint) @@ -2206,133 +871,38 @@ public class ComputerPlayer extends PlayerImpl { @Override public boolean chooseTarget(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game) { - if (cards == null || cards.isEmpty()) { - return false; - } - - boolean isAddedSomething = false; // must return true on any changes in targets, so game can ask next choose dialog until finish - - // sometimes a target selection can be made from a player that does not control the ability - UUID abilityControllerId = playerId; - if (target.getTargetController() != null - && target.getAbilityController() != null) { - abilityControllerId = target.getAbilityController(); - } - - // we still use playerId when getting cards even if they don't control the search - List cardChoices = new ArrayList<>(cards.getCards(target.getFilter(), playerId, source, game)); - isAddedSomething = false; - while (!cardChoices.isEmpty()) { - Card card = selectCardTarget(abilityControllerId, cardChoices, outcome, target, source, game); - if (card != null) { - cardChoices.remove(card); // selectCard don't remove cards (only on second+ tries) - if (!target.contains(card.getId())) { - target.addTarget(card.getId(), source, game); - isAddedSomething = true; - if (target.isChoiceCompleted(game)) { - return true; - } - } - } else { - break; - } - - // try to fill as much as possible for good effect (see while end) or half for bad (see if) - if (target.isChosen(game) && !outcome.isGood() && target.getTargets().size() > target.getMinNumberOfTargets() + (target.getMaxNumberOfTargets() - target.getMinNumberOfTargets()) / 2) { - return true; - } - } - return isAddedSomething; + return makeChoice(outcome, target, source, game, cards); } @Override public boolean choose(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game) { - log.debug("choose 2"); - if (cards == null || cards.isEmpty()) { - return true; - } - - // sometimes a target selection can be made from a player that does not control the ability - UUID abilityControllerId = playerId; - if (target.getTargetController() != null - && target.getAbilityController() != null) { - abilityControllerId = target.getAbilityController(); - } - - List cardChoices = new ArrayList<>(cards.getCards(target.getFilter(), abilityControllerId, source, game)); - do { - Card card = selectCard(abilityControllerId, cardChoices, outcome, target, game); - if (card != null) { - target.add(card.getId(), game); - cardChoices.remove(card); // selectCard don't remove cards (only on second+ tries) - } else { - // We don't have any valid target to choose so stop choosing - return target.isChosen(game); - } - // try to fill as much as possible for good effect (see while end) or half for bad (see if) - if (outcome == Outcome.Neutral && target.getTargets().size() > target.getMinNumberOfTargets() + (target.getMaxNumberOfTargets() - target.getMinNumberOfTargets()) / 2) { - return target.isChosen(game); - } - } while (target.getTargets().size() < target.getMaxNumberOfTargets()); - return true; + return makeChoice(outcome, target, source, game, cards); } @Override public boolean choosePile(Outcome outcome, String message, List pile1, List pile2, Game game) { //TODO: improve this - return true; + return true; // select left pile all the time } @Override public void selectAttackers(Game game, UUID attackingPlayerId) { - log.debug("selectAttackers"); - UUID opponentId = game.getCombat().getDefenders().iterator().next(); - Attackers attackers = getPotentialAttackers(game); - List blockers = getOpponentBlockers(opponentId, game); - List actualAttackers = new ArrayList<>(); - if (blockers.isEmpty()) { - actualAttackers = attackers.getAttackers(); - } else if (attackers.size() - blockers.size() >= game.getPlayer(opponentId).getLife()) { - actualAttackers = attackers.getAttackers(); - } else { - CombatSimulator combat = simulateAttack(attackers, blockers, opponentId, game); - if (combat.rating > 2) { - for (CombatGroupSimulator group : combat.groups) { - this.declareAttacker(group.attackers.get(0).id, group.defenderId, game, false); - } - } - } - for (Permanent attacker : actualAttackers) { - this.declareAttacker(attacker.getId(), opponentId, game, false); - } + // do nothing, parent class must implement it } @Override public void selectBlockers(Ability source, Game game, UUID defendingPlayerId) { - log.debug("selectBlockers"); - - List blockers = getAvailableBlockers(game); - - CombatSimulator sim = simulateBlock(CombatSimulator.load(game), blockers, game); - - List groups = game.getCombat().getGroups(); - for (int i = 0; i < groups.size(); i++) { - for (CreatureSimulator creature : sim.groups.get(i).blockers) { - groups.get(i).addBlocker(creature.id, playerId, game); - } - } + // do nothing, parent class must implement it } @Override public int chooseReplacementEffect(Map effectsMap, Map objectsMap, Game game) { - log.debug("chooseReplacementEffect"); //TODO: implement this - return 0; + return 0; // select first effect all the time } @Override public Mode chooseMode(Modes modes, Ability source, Game game) { - log.debug("chooseMode"); if (modes.getMode() != null && modes.getMaxModes(game, source) == modes.getSelectedModes().size()) { // mode was already set by the AI return modes.getMode(); @@ -2341,52 +911,30 @@ public class ComputerPlayer extends PlayerImpl { // spell modes simulated by AI, see addModeOptions // trigger modes chooses here // TODO: add AI support to select best modes, current code uses first valid mode - AvailableMode: - for (Mode mode : modes.getAvailableModes(source, game)) { - for (UUID selectedModeId : modes.getSelectedModes()) { - Mode selectedMode = modes.get(selectedModeId); - if (selectedMode.getId().equals(mode.getId())) { - continue AvailableMode; - } - } - if (mode.getTargets().canChoose(source.getControllerId(), source, game)) { // and where targets are available - return mode; - } - } - return null; + return modes.getAvailableModes(source, game).stream() + .filter(mode -> !modes.getSelectedModes().contains(mode.getId())) + .filter(mode -> mode.getTargets().canChoose(source.getControllerId(), source, game)) + .findFirst() + .orElse(null); } @Override public TriggeredAbility chooseTriggeredAbility(List abilities, Game game) { - log.debug("chooseTriggeredAbility: " + abilities.toString()); //TODO: improve this if (!abilities.isEmpty()) { - return abilities.get(0); + return abilities.get(0); // select first trigger all the time } return null; } @Override - // TODO: add AI support with outcome and replace random with min/max public int getAmount(int min, int max, String message, Ability source, Game game) { - log.debug("getAmount"); - - // fast calc on nothing to choose - if (min >= max) { - return min; - } - - if (min == 0) { - return RandomUtil.nextInt(CardUtil.overflowInc(max, 1)); - } - return min; + return makeChoiceAmount(min, max, game, source, false); } @Override public List getMultiAmountWithIndividualConstraints(Outcome outcome, List messages, int totalMin, int totalMax, MultiAmountType type, Game game) { - log.debug("getMultiAmount"); - int needCount = messages.size(); List defaultList = MultiAmountType.prepareDefaultValues(messages, totalMin, totalMax); if (needCount == 0) { @@ -2401,7 +949,7 @@ public class ComputerPlayer extends PlayerImpl { } // GOOD effect - // values must be stable, so AI must able to simulate it and choose correct actions + // values must be stable, so AI must be able to simulate it and choose correct actions // fill max values as much as possible return MultiAmountType.prepareMaxValues(messages, totalMin, totalMax); } @@ -2413,8 +961,8 @@ public class ComputerPlayer extends PlayerImpl { @Override public void sideboard(Match match, Deck deck) { - //TODO: improve this - match.submitDeck(playerId, deck); + // TODO: improve this + match.submitDeck(playerId, deck); // do not change a deck } private static void addBasicLands(Deck deck, String landName, int number) { @@ -2422,7 +970,7 @@ public class ComputerPlayer extends PlayerImpl { CardCriteria criteria = new CardCriteria(); if (!landSets.isEmpty()) { - criteria.setCodes(landSets.toArray(new String[landSets.size()])); + criteria.setCodes(landSets.toArray(new String[0])); } criteria.rarities(Rarity.LAND).name(landName); List cards = CardRepository.instance.findCards(criteria); @@ -2478,13 +1026,10 @@ public class ComputerPlayer extends PlayerImpl { // sort card pool by top score List sortedCards = new ArrayList<>(cardPool); - Collections.sort(sortedCards, new Comparator() { - @Override - public int compare(Card o1, Card o2) { - Integer score1 = RateCard.rateCard(o1, colors); - Integer score2 = RateCard.rateCard(o2, colors); - return score2.compareTo(score1); - } + Collections.sort(sortedCards, (o1, o2) -> { + Integer score1 = RateCard.rateCard(o1, colors); + Integer score2 = RateCard.rateCard(o2, colors); + return score2.compareTo(score1); }); // get top cards @@ -2576,28 +1121,11 @@ public class ComputerPlayer extends PlayerImpl { tournament.submitDeck(playerId, deck); } - public Card selectBestCard(List cards, List chosenColors) { - return selectBestCardInner(cards, chosenColors, null, null, null); - } - - public Card selectBestCardTarget(List cards, List chosenColors, Target target, Ability targetingSource, Game game) { - return selectBestCardInner(cards, chosenColors, target, targetingSource, game); - } - - /** - * @param targetingSource null on non-target choice like choose and source on targeting choice like chooseTarget - */ - public Card selectBestCardInner(List cards, List chosenColors, Target target, Ability targetingSource, Game game) { + public Card makePickCard(List cards, List chosenColors) { if (cards.isEmpty()) { return null; } - // sometimes a target selection can be made from a player that does not control the ability - UUID abilityControllerId = playerId; - if (target != null && target.getAbilityController() != null) { - abilityControllerId = target.getAbilityController(); - } - Card bestCard = null; int maxScore = 0; for (Card card : cards) { @@ -2606,13 +1134,7 @@ public class ComputerPlayer extends PlayerImpl { if (bestCard == null) { // we need any card to prevent NPE in callers betterCard = true; } else if (score > maxScore) { // we need better card - if (target != null && targetingSource != null && game != null) { - // but also check it can be targeted - betterCard = target.canTarget(abilityControllerId, card.getId(), targetingSource, game); - } else { - // target object wasn't provided, so accepting it anyway - betterCard = true; - } + betterCard = true; } // is it better than previous one? if (betterCard) { @@ -2623,69 +1145,23 @@ public class ComputerPlayer extends PlayerImpl { return bestCard; } - public Card selectWorstCard(List cards, List chosenColors) { - return selectWorstCardInner(cards, chosenColors, null, null, null); - } - - public Card selectWorstCardTarget(List cards, List chosenColors, Target target, Ability targetingSource, Game game) { - return selectWorstCardInner(cards, chosenColors, target, targetingSource, game); - } - - /** - * @param targetingSource null on non-target choice like choose and source on targeting choice like chooseTarget - */ - public Card selectWorstCardInner(List cards, List chosenColors, Target target, Ability targetingSource, Game game) { - if (cards.isEmpty()) { - return null; - } - - // sometimes a target selection can be made from a player that does not control the ability - UUID abilityControllerId = playerId; - if (target != null && target.getAbilityController() != null) { - abilityControllerId = target.getAbilityController(); - } - - Card worstCard = null; - int minScore = Integer.MAX_VALUE; - for (Card card : cards) { - int score = RateCard.rateCard(card, chosenColors); - boolean worseCard = false; - if (worstCard == null) { // we need any card to prevent NPE in callers - worseCard = true; - } else if (score < minScore) { // we need worse card - if (target != null && targetingSource != null && game != null) { - // but also check it can be targeted - worseCard = target.canTarget(abilityControllerId, card.getId(), targetingSource, game); - } else { - // target object wasn't provided, so accepting it anyway - worseCard = true; - } - } - // is it worse than previous one? - if (worseCard) { - minScore = score; - worstCard = card; - } - } - return worstCard; - } - @Override public void pickCard(List cards, Deck deck, Draft draft) { + // method used by DRAFT bot too if (cards.isEmpty()) { throw new IllegalArgumentException("No cards to pick from."); } try { - Card bestCard = selectBestCard(cards, chosenColors); + Card bestCard = makePickCard(cards, chosenColors); int maxScore = RateCard.rateCard(bestCard, chosenColors); int pickedCardRate = RateCard.getBaseCardScore(bestCard); if (pickedCardRate <= 30) { // if card is bad // try to counter pick without any color restriction - Card counterPick = selectBestCard(cards, Collections.emptyList()); + Card counterPick = makePickCard(cards, Collections.emptyList()); int counterPickScore = RateCard.getBaseCardScore(counterPick); - // card is really good + // card is perfect // take it! if (counterPickScore >= 80) { bestCard = counterPick; @@ -2708,19 +1184,15 @@ public class ComputerPlayer extends PlayerImpl { colors += symbol.toString(); } } - log.debug("[DEBUG] AI picked: " + bestCard.getName() + ", score=" + maxScore + ", deck colors=" + colors); draft.addPick(playerId, bestCard.getId(), null); } catch (Exception e) { - log.debug("Exception during AI pick card for draft playerId= " + getId()); + logger.error("Error during AI pick card for draft playerId = " + getId(), e); draft.addPick(playerId, cards.get(0).getId(), null); } } /** * Remember picked card with its score. - * - * @param card - * @param score */ protected void rememberPick(Card card, int score) { pickedCards.add(new PickedCard(card, score)); @@ -2730,22 +1202,17 @@ public class ComputerPlayer extends PlayerImpl { * Choose 2 deck colors for draft: 1. there should be at least 3 cards in * card pool 2. at least 2 cards should have different colors 3. get card * colors as chosen starting from most rated card - * - * @return */ protected List chooseDeckColorsIfPossible() { if (pickedCards.size() > 2) { // sort by score and color mana symbol count in descending order - pickedCards.sort(new Comparator() { - @Override - public int compare(PickedCard o1, PickedCard o2) { - if (o1.score.equals(o2.score)) { - Integer i1 = RateCard.getColorManaCount(o1.card); - Integer i2 = RateCard.getColorManaCount(o2.card); - return i2.compareTo(i1); - } - return o2.score.compareTo(o1.score); + pickedCards.sort((o1, o2) -> { + if (o1.score.equals(o2.score)) { + Integer i1 = RateCard.getColorManaCount(o1.card); + Integer i2 = RateCard.getColorManaCount(o2.card); + return i2.compareTo(i1); } + return o2.score.compareTo(o1.score); }); Set chosenSymbols = new HashSet<>(); for (PickedCard picked : pickedCards) { @@ -2793,105 +1260,6 @@ public class ComputerPlayer extends PlayerImpl { } } - protected Attackers getPotentialAttackers(Game game) { - log.debug("getAvailableAttackers"); - Attackers attackers = new Attackers(); - List creatures = super.getAvailableAttackers(game); - for (Permanent creature : creatures) { - int potential = combatPotential(creature, game); - if (potential > 0 && creature.getPower().getValue() > 0) { - List l = attackers.get(potential); - if (l == null) { - attackers.put(potential, l = new ArrayList<>()); - } - l.add(creature); - } - } - return attackers; - } - - protected int combatPotential(Permanent creature, Game game) { - log.debug("combatPotential"); - if (!creature.canAttack(null, game)) { - return 0; - } - int potential = creature.getPower().getValue(); - potential += creature.getAbilities().getEvasionAbilities().size(); - potential += creature.getAbilities().getProtectionAbilities().size(); - potential += creature.getAbilities().containsKey(FirstStrikeAbility.getInstance().getId()) ? 1 : 0; - potential += creature.getAbilities().containsKey(DoubleStrikeAbility.getInstance().getId()) ? 2 : 0; - potential += creature.getAbilities().containsKey(TrampleAbility.getInstance().getId()) ? 1 : 0; - return potential; - } - - protected List getOpponentBlockers(UUID opponentId, Game game) { - FilterCreatureForCombatBlock blockFilter = new FilterCreatureForCombatBlock(); - return game.getBattlefield().getAllActivePermanents(blockFilter, opponentId, game); - } - - protected CombatSimulator simulateAttack(Attackers attackers, List blockers, UUID opponentId, Game game) { - log.debug("simulateAttack"); - List attackersList = attackers.getAttackers(); - CombatSimulator best = new CombatSimulator(); - int bestResult = 0; - //use binary digits to calculate powerset of attackers - int powerElements = (int) Math.pow(2, attackersList.size()); - for (int i = 1; i < powerElements; i++) { - String binary = Integer.toBinaryString(i); - while (binary.length() < attackersList.size()) { - binary = '0' + binary; - } - List trialAttackers = new ArrayList<>(); - for (int j = 0; j < attackersList.size(); j++) { - if (binary.charAt(j) == '1') { - trialAttackers.add(attackersList.get(j)); - } - } - CombatSimulator combat = new CombatSimulator(); - for (Permanent permanent : trialAttackers) { - combat.groups.add(new CombatGroupSimulator(opponentId, Arrays.asList(permanent.getId()), new ArrayList(), game)); - } - CombatSimulator test = simulateBlock(combat, blockers, game); - if (test.evaluate() > bestResult) { - best = test; - bestResult = test.evaluate(); - } - } - - return best; - } - - protected CombatSimulator simulateBlock(CombatSimulator combat, List blockers, Game game) { - log.debug("simulateBlock"); - - TreeNode simulations; - - simulations = new TreeNode<>(combat); - addBlockSimulations(blockers, simulations, game); - combat.simulate(game); - - return getWorstSimulation(simulations); - - } - - protected void addBlockSimulations(List blockers, TreeNode node, Game game) { - int numGroups = node.getData().groups.size(); - Copier copier = new Copier<>(); - for (Permanent blocker : blockers) { - List subList = remove(blockers, blocker); - for (int i = 0; i < numGroups; i++) { - if (node.getData().groups.get(i).canBlock(blocker, game)) { - CombatSimulator combat = copier.copy(node.getData()); - combat.groups.get(i).blockers.add(new CreatureSimulator(blocker)); - TreeNode child = new TreeNode<>(combat); - node.addChild(child); - addBlockSimulations(subList, child, game); - combat.simulate(game); - } - } - } - } - protected List remove(List source, Permanent element) { List newList = new ArrayList<>(); for (Permanent permanent : source) { @@ -2902,172 +1270,13 @@ public class ComputerPlayer extends PlayerImpl { return newList; } - protected CombatSimulator getBestSimulation(TreeNode simulations) { - CombatSimulator best = simulations.getData(); - int bestResult = best.evaluate(); - for (TreeNode node : simulations.getChildren()) { - CombatSimulator bestSub = getBestSimulation(node); - if (bestSub.evaluate() > bestResult) { - best = node.getData(); - bestResult = best.evaluate(); - } - } - return best; - } - - protected CombatSimulator getWorstSimulation(TreeNode simulations) { - CombatSimulator worst = simulations.getData(); - int worstResult = worst.evaluate(); - for (TreeNode node : simulations.getChildren()) { - CombatSimulator worstSub = getWorstSimulation(node); - if (worstSub.evaluate() < worstResult) { - worst = node.getData(); - worstResult = worst.evaluate(); - } - } - return worst; - } - - protected void findBestPermanentTargets(Outcome outcome, UUID abilityControllerId, UUID sourceId, Ability source, FilterPermanent filter, Game game, Target target, - List goodList, List badList, List allList) { - // searching for most valuable/powerfull permanents - goodList.clear(); - badList.clear(); - allList.clear(); - List usedTargets = target.getTargets(); - - // search all - for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, abilityControllerId, source, game)) { - if (usedTargets.contains(permanent.getId())) { - continue; - } - - if (outcome.isGood()) { - // good effect - if (permanent.isControlledBy(abilityControllerId)) { - goodList.add(permanent); - } else { - badList.add(permanent); - } - } else { - // bad effect - if (permanent.isControlledBy(abilityControllerId)) { - badList.add(permanent); - } else { - goodList.add(permanent); - } - } - } - - // sort from tiny to big (more valuable) - PermanentComparator comparator = new PermanentComparator(game); - goodList.sort(comparator); - badList.sort(comparator); - - // most valueable goes first in good list - Collections.reverse(goodList); - // most weakest goes first in bad list (no need to reverse) - //Collections.reverse(badList); - - allList.addAll(goodList); - allList.addAll(badList); - - // "can target all mode" don't need your/opponent lists -- all targets goes with same value - if (outcome.isCanTargetAll()) { - allList.sort(comparator); // bad sort - if (outcome.isGood()) { - Collections.reverse(allList); // good sort - } - goodList.clear(); - goodList.addAll(allList); - badList.clear(); - badList.addAll(allList); - } - } - - protected List threats(UUID playerId, Ability source, FilterPermanent filter, Game game, List targets) { - return threats(playerId, source, filter, game, targets, true); - } - - protected List threats(UUID playerId, Ability source, FilterPermanent filter, Game game, List targets, boolean mostValueableGoFirst) { - // most valuable/powerfull permanents goes at first - List threats; - if (playerId == null) { - threats = game.getBattlefield().getActivePermanents(filter, this.getId(), source, game); // all permanents within the range of the player - } else { - FilterPermanent filterCopy = filter.copy(); - filterCopy.add(new ControllerIdPredicate(playerId)); - threats = game.getBattlefield().getActivePermanents(filter, this.getId(), source, game); - } - Iterator it = threats.iterator(); - while (it.hasNext()) { // remove permanents already targeted - Permanent test = it.next(); - if (targets.contains(test.getId()) || (playerId != null && !test.getControllerId().equals(playerId))) { - it.remove(); - } - } - Collections.sort(threats, new PermanentComparator(game)); - if (mostValueableGoFirst) { - Collections.reverse(threats); - } - return threats; - } - protected void logList(String message, List list) { StringBuilder sb = new StringBuilder(); sb.append(message).append(": "); for (MageObject object : list) { sb.append(object.getName()).append(','); } - log.info(sb.toString()); - } - - protected void logAbilityList(String message, List list) { - StringBuilder sb = new StringBuilder(); - sb.append(message).append(": "); - for (Ability ability : list) { - sb.append(ability.getRule()).append(','); - } - log.debug(sb.toString()); - } - - private void playRemoval(Set creatures, Game game) { - for (UUID creatureId : creatures) { - for (Card card : this.playableInstant) { - if (card.getSpellAbility().canActivate(playerId, game).canActivate()) { - for (Effect effect : card.getSpellAbility().getEffects()) { - if (effect.getOutcome() == Outcome.DestroyPermanent || effect.getOutcome() == Outcome.ReturnToHand) { - if (card.getSpellAbility().getTargets().get(0).canTarget(creatureId, card.getSpellAbility(), game)) { - if (this.activateAbility(card.getSpellAbility(), game)) { - return; - } - } - } - } - } - } - } - } - - private void playDamage(Set creatures, Game game) { - for (UUID creatureId : creatures) { - Permanent creature = game.getPermanent(creatureId); - for (Card card : this.playableInstant) { - if (card.getSpellAbility().canActivate(playerId, game).canActivate()) { - for (Effect effect : card.getSpellAbility().getEffects()) { - if (effect instanceof DamageTargetEffect) { - if (card.getSpellAbility().getTargets().get(0).canTarget(creatureId, card.getSpellAbility(), game)) { - if (((DamageTargetEffect) effect).getAmount() > (creature.getPower().getValue() - creature.getDamage())) { - if (this.activateAbility(card.getSpellAbility(), game)) { - return; - } - } - } - } - } - } - } - } + logger.info(sb.toString()); } @Override @@ -3080,151 +1289,13 @@ public class ComputerPlayer extends PlayerImpl { return new ComputerPlayer(this); } - @Deprecated // TODO: replace by standard while cycle with cards.isempty and addTarget - private boolean tryAddTarget(Target target, UUID id, Ability source, Game game) { - // workaround to to check successfull targets add - int before = target.getTargets().size(); - target.addTarget(id, source, game); - int after = target.getTargets().size(); - return before != after; - } - - private boolean tryAddTarget(Target target, UUID id, int amount, Ability source, Game game) { - // workaround to to check successfull targets add - int before = target.getTargets().size(); - target.addTarget(id, amount, source, game); - int after = target.getTargets().size(); - return before != after; - } - - private boolean selectPlayer(Outcome outcome, Target target, UUID abilityControllerId, UUID randomOpponentId, Game game, boolean required) { - return selectPlayerInner(outcome, target, null, abilityControllerId, randomOpponentId, game, required); - } - - private boolean selectPlayerTarget(Outcome outcome, Target target, Ability targetingSource, UUID abilityControllerId, UUID randomOpponentId, Game game, boolean required) { - return selectPlayerInner(outcome, target, targetingSource, abilityControllerId, randomOpponentId, game, required); - } - - /** - * Sets a possible target player. Depends on bad/good outcome - *

- * Return false on no more valid targets, e.g. can stop choose dialog - * - * @param targetingSource null on non-target choice like choose and source on targeting choice like chooseTarget - */ - private boolean selectPlayerInner(Outcome outcome, Target target, Ability targetingSource, UUID abilityControllerId, UUID randomOpponentId, Game game, boolean required) { - Outcome affectedOutcome; - if (abilityControllerId == this.playerId) { - // selects for itself - affectedOutcome = outcome; - } else { - // selects for another player - affectedOutcome = Outcome.inverse(outcome); - } - - if (target.getOriginalTarget() instanceof TargetOpponent) { - if (targetingSource == null) { - if (target.canTarget(randomOpponentId, game)) { - if (!target.contains(randomOpponentId)) { - target.add(randomOpponentId, game); - return true; - } - } - } else if (target.canTarget(abilityControllerId, randomOpponentId, targetingSource, game)) { - if (!target.contains(randomOpponentId)) { - target.addTarget(randomOpponentId, targetingSource, game); - return true; - } - } - for (UUID possibleOpponentId : game.getOpponents(getId(), true)) { - if (targetingSource == null) { - if (target.canTarget(possibleOpponentId, game)) { - if (!target.contains(possibleOpponentId)) { - target.add(possibleOpponentId, game); - return true; - } - } - } else if (target.canTarget(abilityControllerId, possibleOpponentId, targetingSource, game)) { - if (!target.contains(possibleOpponentId)) { - target.addTarget(possibleOpponentId, targetingSource, game); - return true; - } - } - } - return false; - } - - UUID sourceId = targetingSource != null ? targetingSource.getSourceId() : null; - if (target.getOriginalTarget() instanceof TargetPlayer) { - if (affectedOutcome.isGood()) { - if (targetingSource == null) { - // good - if (target.canTarget(getId(), game) && !target.contains(getId())) { - target.add(getId(), game); - return true; - } - if (target.isRequired(sourceId, game)) { - if (target.canTarget(randomOpponentId, game) && !target.contains(randomOpponentId)) { - target.add(randomOpponentId, game); - return true; - } - } - } else { - // good - if (target.canTarget(abilityControllerId, getId(), targetingSource, game) && !target.contains(getId())) { - target.addTarget(getId(), targetingSource, game); - return true; - } - if (target.isRequired(sourceId, game)) { - if (target.canTarget(abilityControllerId, randomOpponentId, targetingSource, game) && !target.contains(randomOpponentId)) { - target.addTarget(randomOpponentId, targetingSource, game); - return true; - } - } - } - } else if (targetingSource == null) { - // bad - if (target.canTarget(randomOpponentId, game) && !target.contains(randomOpponentId)) { - target.add(randomOpponentId, game); - return true; - } - if (target.isRequired(sourceId, game)) { - if (target.canTarget(getId(), game) && !target.contains(getId())) { - target.add(getId(), game); - return true; - } - } - } else { - // bad - if (target.canTarget(abilityControllerId, randomOpponentId, targetingSource, game) && !target.contains(randomOpponentId)) { - target.addTarget(randomOpponentId, targetingSource, game); - return true; - } - if (required) { - if (target.canTarget(abilityControllerId, getId(), targetingSource, game) && !target.contains(getId())) { - target.addTarget(getId(), targetingSource, game); - return true; - } - } - } - return false; - } - - return false; - } - - /** - * Returns an opponent by random - */ - @Deprecated // TODO: rework all usages and replace to all possible opponents instead single - private UUID getRandomOpponent(Game game) { - return RandomUtil.randomFromCollection(game.getOpponents(getId(), true)); - } - @Override public SpellAbility chooseAbilityForCast(Card card, Game game, boolean noMana) { - Map useable = PlayerImpl.getCastableSpellAbilities(game, this.getId(), card, game.getState().getZone(card.getId()), noMana); - return useable.values().stream().findFirst().orElse(null); + Map usable = PlayerImpl.getCastableSpellAbilities(game, this.getId(), card, game.getState().getZone(card.getId()), noMana); + return usable.values().stream() + .filter(a -> a.getTargets().canChoose(getId(), a, game)) + .findFirst() + .orElse(null); } @Override @@ -3262,12 +1333,4 @@ public class ComputerPlayer extends PlayerImpl { // all human players converted to computer and analyse this.human = false; } - - public long getLastThinkTime() { - return lastThinkTime; - } - - public void setLastThinkTime(long lastThinkTime) { - this.lastThinkTime = lastThinkTime; - } -} +} \ No newline at end of file diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/PossibleTargetsComparator.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/PossibleTargetsComparator.java new file mode 100644 index 00000000000..7f4f199b5ab --- /dev/null +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/PossibleTargetsComparator.java @@ -0,0 +1,152 @@ +package mage.player.ai; + +import mage.MageItem; +import mage.MageObject; +import mage.cards.Card; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.player.ai.score.GameStateEvaluator2; +import mage.players.PlayableObjectsList; +import mage.players.Player; + +import java.util.Comparator; +import java.util.UUID; + +/** + * AI related code - compare and sort possible targets due target/effect type + * + * @author JayDi85 + */ +public class PossibleTargetsComparator { + + UUID abilityControllerId; + Game game; + PlayableObjectsList playableItems = new PlayableObjectsList(); + + public PossibleTargetsComparator(UUID abilityControllerId, Game game) { + this.abilityControllerId = abilityControllerId; + this.game = game; + } + + public void findPlayableItems() { + this.playableItems = this.game.getPlayer(this.abilityControllerId).getPlayableObjects(this.game, Zone.ALL); + } + + private int getScoreFromBattlefield(MageItem item) { + if (item instanceof Permanent) { + // use battlefield score instead simple life + return GameStateEvaluator2.evaluatePermanent((Permanent) item, game, false); + } else { + return getScoreFromLife(item); + } + } + + private String getName(MageItem item) { + if (item instanceof Player) { + return ((Player) item).getName(); + } else if (item instanceof MageObject) { + return ((MageObject) item).getName(); + } else { + return "unknown"; + } + } + + public static int getLifeForDamage(MageItem item, Game game) { + int res = 0; + if (item instanceof Player) { + res = ((Player) item).getLife(); + } else if (item instanceof Card) { + Card card = (Card) item; + if (card.isPlaneswalker(game)) { + res = card.getCounters(game).getCount(CounterType.LOYALTY); + } else if (card.isBattle(game)) { + res = card.getCounters(game).getCount(CounterType.DEFENSE); + } else { + int damage = 0; + if (card instanceof Permanent) { + damage = ((Permanent) card).getDamage(); + } + res = Math.max(0, card.getToughness().getValue() - damage); + } + } + return res; + } + + private int getScoreFromLife(MageItem item) { + // TODO: replace permanent/card life by battlefield score? + int res = getLifeForDamage(item, game); + if (res == 0 && item instanceof Card) { + res = ((Card) item).getManaValue(); + } + return res; + } + + private boolean isMyItem(MageItem item) { + return PossibleTargetsSelector.isMyItem(this.abilityControllerId, item); + } + + // sort by name-id at the end, so AI will use same choices in all simulations + private final Comparator BY_NAME = (o1, o2) -> getName(o2).compareTo(getName(o1)); + private final Comparator BY_ID = Comparator.comparing(MageItem::getId); + + private final Comparator BY_ME = (o1, o2) -> Boolean.compare( + isMyItem(o2), + isMyItem(o1) + ); + + private final Comparator BY_BIGGER_SCORE = (o1, o2) -> Integer.compare( + getScoreFromBattlefield(o2), + getScoreFromBattlefield(o1) + ); + + private final Comparator BY_PLAYABLE = (o1, o2) -> Boolean.compare( + this.playableItems.containsObject(o2.getId()), + this.playableItems.containsObject(o1.getId()) + ); + + private final Comparator BY_LAND = (o1, o2) -> { + boolean isLand1 = o1 instanceof MageObject && ((MageObject) o1).isLand(game); + boolean isLand2 = o2 instanceof MageObject && ((MageObject) o2).isLand(game); + return Boolean.compare(isLand2, isLand1); + }; + + private final Comparator BY_TYPE_PLAYER = (o1, o2) -> Boolean.compare( + o2 instanceof Player, + o1 instanceof Player + ); + + private final Comparator BY_TYPE_PLANESWALKER = (o1, o2) -> { + boolean isPlaneswalker1 = o1 instanceof MageObject && ((MageObject) o1).isPlaneswalker(game); + boolean isPlaneswalker2 = o2 instanceof MageObject && ((MageObject) o2).isPlaneswalker(game); + return Boolean.compare(isPlaneswalker2, isPlaneswalker1); + }; + + private final Comparator BY_TYPE_BATTLE = (o1, o2) -> { + boolean isBattle1 = o1 instanceof MageObject && ((MageObject) o1).isBattle(game); + boolean isBattle2 = o2 instanceof MageObject && ((MageObject) o2).isBattle(game); + return Boolean.compare(isBattle2, isBattle1); + }; + + private final Comparator BY_TYPES = BY_TYPE_PLANESWALKER + .thenComparing(BY_TYPE_BATTLE) + .thenComparing(BY_TYPE_PLAYER); + + /** + * Default sorting for good effects - put the biggest items to the top + */ + public final Comparator ANY_MOST_VALUABLE_FIRST = BY_TYPES + .thenComparing(BY_BIGGER_SCORE) + .thenComparing(BY_NAME) + .thenComparing(BY_ID); + public final Comparator ANY_MOST_VALUABLE_LAST = ANY_MOST_VALUABLE_FIRST.reversed(); + + /** + * Sorting for discard effects - put the biggest unplayable at the top, lands at the end anyway + */ + public final Comparator ANY_UNPLAYABLE_AND_USELESS = BY_LAND.reversed() + .thenComparing(BY_PLAYABLE.reversed()) + .thenComparing(ANY_MOST_VALUABLE_FIRST); + +} diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/PossibleTargetsSelector.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/PossibleTargetsSelector.java new file mode 100644 index 00000000000..49422bcbdbe --- /dev/null +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/PossibleTargetsSelector.java @@ -0,0 +1,188 @@ +package mage.player.ai; + +import mage.MageItem; +import mage.abilities.Ability; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.ControllableOrOwnerable; +import mage.game.Game; +import mage.players.Player; +import mage.target.Target; +import mage.target.common.TargetCardInGraveyardBattlefieldOrStack; +import mage.target.common.TargetDiscard; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * AI related code - find possible targets and sort it due priority + * + * @author JayDi85 + */ +public class PossibleTargetsSelector { + + Outcome outcome; + Target target; + UUID abilityControllerId; + Ability source; + Game game; + + PossibleTargetsComparator comparators; + + // possible targets lists + List me = new ArrayList<>(); + List opponents = new ArrayList<>(); + List any = new ArrayList<>(); // for outcomes with any target like copy + + public PossibleTargetsSelector(Outcome outcome, Target target, UUID abilityControllerId, Ability source, Game game) { + this.outcome = outcome; + this.target = target; + this.abilityControllerId = abilityControllerId; + this.source = source; + this.game = game; + this.comparators = new PossibleTargetsComparator(abilityControllerId, game); + } + + public void findNewTargets(Set fromTargetsList) { + // collect new valid targets + List found = target.possibleTargets(abilityControllerId, source, game).stream() + .filter(id -> !target.contains(id)) + .filter(id -> fromTargetsList == null || fromTargetsList.contains(id)) + .filter(id -> target.canTarget(abilityControllerId, id, source, game)) + .map(id -> { + Player player = game.getPlayer(id); + if (player != null) { + return player; + } else { + return game.getObject(id); + } + }) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + + // split targets between me and opponents + found.forEach(item -> { + if (isMyItem(abilityControllerId, item)) { + this.me.add(item); + } else { + this.opponents.add(item); + } + this.any.add(item); + }); + + if (target instanceof TargetDiscard) { + // sort due unplayable + sortByUnplayableAndUseless(); + } else { + // sort due good/bad outcome + sortByMostValuableTargets(); + } + } + + /** + * Sorting for any good/bad effects + */ + private void sortByMostValuableTargets() { + if (isGoodEffect()) { + // for good effect must choose the biggest objects + this.me.sort(comparators.ANY_MOST_VALUABLE_FIRST); + this.opponents.sort(comparators.ANY_MOST_VALUABLE_LAST); + this.any.sort(comparators.ANY_MOST_VALUABLE_FIRST); + } else { + // for bad effect must choose the smallest objects + this.me.sort(comparators.ANY_MOST_VALUABLE_LAST); + this.opponents.sort(comparators.ANY_MOST_VALUABLE_FIRST); + this.any.sort(comparators.ANY_MOST_VALUABLE_LAST); + } + } + + /** + * Sorting for discard + */ + private void sortByUnplayableAndUseless() { + // used + // no good or bad effect - you must choose + comparators.findPlayableItems(); + this.me.sort(comparators.ANY_UNPLAYABLE_AND_USELESS); + this.opponents.sort(comparators.ANY_UNPLAYABLE_AND_USELESS); + this.any.sort(comparators.ANY_UNPLAYABLE_AND_USELESS); + } + + /** + * Priority targets. Try to use as much as possible. + */ + public List getGoodTargets() { + if (isAnyEffect()) { + return this.any; + } + + if (isGoodEffect()) { + return this.me; + } else { + return this.opponents; + } + } + + /** + * Optional targets. Try to ignore bad targets (e.g. opponent's creatures for your good effect). + */ + public List getBadTargets() { + if (isAnyEffect()) { + return Collections.emptyList(); + } + + if (isGoodEffect()) { + return this.opponents; + } else { + return this.me; + } + } + + public static boolean isMyItem(UUID abilityControllerId, MageItem item) { + if (item instanceof Player) { + return item.getId().equals(abilityControllerId); + } else if (item instanceof ControllableOrOwnerable) { + return ((ControllableOrOwnerable) item).getControllerOrOwnerId().equals(abilityControllerId); + } + return false; + } + + private boolean isAnyEffect() { + boolean isAnyEffect = outcome.anyTargetHasSameValue(); + + if (hasGoodExile()) { + isAnyEffect = true; + } + + return isAnyEffect; + } + + private boolean isGoodEffect() { + boolean isGoodEffect = outcome.isGood(); + + if (hasGoodExile()) { + isGoodEffect = true; + } + + return isGoodEffect; + } + + private boolean hasGoodExile() { + // exile workaround: exile is bad, but exile from library or graveyard in most cases is good + // (more exiled -- more good things you get, e.g. delve's pay or search cards with same name) + if (outcome == Outcome.Exile) { + if (Zone.GRAVEYARD.match(target.getZone()) + || Zone.LIBRARY.match(target.getZone())) { + // TargetCardInGraveyardBattlefieldOrStack - used for additional payment like Craft, so do not allow big cards for it + if (!(target instanceof TargetCardInGraveyardBattlefieldOrStack)) { + return true; + } + } + } + return false; + } + + boolean hasAnyTargets() { + return !this.any.isEmpty(); + } +} \ No newline at end of file diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/ArtificialScoringSystem.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/score/ArtificialScoringSystem.java similarity index 99% rename from Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/ArtificialScoringSystem.java rename to Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/score/ArtificialScoringSystem.java index 35ededd0de4..4cef32c7ec8 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/ArtificialScoringSystem.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/score/ArtificialScoringSystem.java @@ -1,4 +1,4 @@ -package mage.player.ai.ma; +package mage.player.ai.score; import mage.MageObject; import mage.abilities.Ability; diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/GameStateEvaluator2.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/score/GameStateEvaluator2.java similarity index 99% rename from Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/GameStateEvaluator2.java rename to Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/score/GameStateEvaluator2.java index ebc0dbcdade..9c96a619d10 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/GameStateEvaluator2.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/score/GameStateEvaluator2.java @@ -1,8 +1,7 @@ -package mage.player.ai; +package mage.player.ai.score; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.player.ai.ma.ArtificialScoringSystem; import mage.players.Player; import org.apache.log4j.Logger; diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/MagicAbility.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/score/MagicAbility.java similarity index 87% rename from Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/MagicAbility.java rename to Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/score/MagicAbility.java index 43fae122d17..63346dc3ed0 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ma/MagicAbility.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/score/MagicAbility.java @@ -1,4 +1,4 @@ -package mage.player.ai.ma; +package mage.player.ai.score; import mage.abilities.Ability; import mage.abilities.keyword.*; @@ -7,6 +7,7 @@ import java.util.HashMap; import java.util.Map; /** + * TODO: outdated, replace by edh or commander brackets ability score * @author nantuko */ public final class MagicAbility { @@ -18,10 +19,10 @@ public final class MagicAbility { put(DoubleStrikeAbility.getInstance().getRule(), 100); put(new ExaltedAbility().getRule(), 10); put(FirstStrikeAbility.getInstance().getRule(), 50); - put(FlashAbility.getInstance().getRule(), 0); + put(FlashAbility.getInstance().getRule(), 20); put(FlyingAbility.getInstance().getRule(), 50); put(new ForestwalkAbility().getRule(), 10); - put(HasteAbility.getInstance().getRule(), 0); + put(HasteAbility.getInstance().getRule(), 20); put(IndestructibleAbility.getInstance().getRule(), 150); put(InfectAbility.getInstance().getRule(), 60); put(IntimidateAbility.getInstance().getRule(), 50); @@ -46,7 +47,7 @@ public final class MagicAbility { if (!scores.containsKey(ability.getRule())) { //System.err.println("Couldn't find ability score: " + ability.getClass().getSimpleName() + " - " + ability.toString()); //TODO: add handling protection from ..., levelup, kicker, etc. abilities - return 0; + return 2; // more abilities - more score in any use cases } return scores.get(ability.getRule()); } diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/simulators/ActionSimulator.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/simulators/ActionSimulator.java deleted file mode 100644 index e67d6383710..00000000000 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/simulators/ActionSimulator.java +++ /dev/null @@ -1,65 +0,0 @@ - - -package mage.player.ai.simulators; - -import mage.abilities.ActivatedAbility; -import mage.cards.Card; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.player.ai.ComputerPlayer; -import mage.player.ai.PermanentEvaluator; -import mage.players.Player; - -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author BetaSteward_at_googlemail.com - */ -public class ActionSimulator { - - private ComputerPlayer player; - private List playableInstants = new ArrayList<>(); - private List playableAbilities = new ArrayList<>(); - - private Game game; - - public ActionSimulator(ComputerPlayer player) { - this.player = player; - } - - public void simulate(Game game) { - - } - - public int evaluateState() { - // must find all leaved opponents - Player opponent = game.getPlayer(game.getOpponents(player.getId(), false).stream().findFirst().orElse(null)); - if (opponent == null) { - return Integer.MAX_VALUE; - } - - if (game.checkIfGameIsOver()) { - if (player.hasLost() || opponent.hasWon()) { - return Integer.MIN_VALUE; - } - if (opponent.hasLost() || player.hasWon()) { - return Integer.MAX_VALUE; - } - } - int value = player.getLife(); - value -= opponent.getLife(); - PermanentEvaluator evaluator = new PermanentEvaluator(); - for (Permanent permanent: game.getBattlefield().getAllActivePermanents(player.getId())) { - value += evaluator.evaluate(permanent, game); - } - for (Permanent permanent: game.getBattlefield().getAllActivePermanents(player.getId())) { - value -= evaluator.evaluate(permanent, game); - } - value += player.getHand().size(); - value -= opponent.getHand().size(); - return value; - } - -} diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/simulators/CombatGroupSimulator.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/simulators/CombatGroupSimulator.java deleted file mode 100644 index ffa8bdee0e6..00000000000 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/simulators/CombatGroupSimulator.java +++ /dev/null @@ -1,148 +0,0 @@ -package mage.player.ai.simulators; - -import mage.game.Game; -import mage.game.permanent.Permanent; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -/** - * - * @author BetaSteward_at_googlemail.com - */ -public class CombatGroupSimulator implements Serializable { - public List attackers = new ArrayList<>(); - public List blockers = new ArrayList<>(); - public UUID defenderId; - public boolean defenderIsPlaneswalker; - public int unblockedDamage; - private CreatureSimulator attacker; - - public CombatGroupSimulator(UUID defenderId, List attackers, List blockers, Game game) { - this.defenderId = defenderId; - for (UUID attackerId: attackers) { - Permanent permanent = game.getPermanent(attackerId); - this.attackers.add(new CreatureSimulator(permanent)); - } - for (UUID blockerId: blockers) { - Permanent permanent = game.getPermanent(blockerId); - this.blockers.add(new CreatureSimulator(permanent)); - } - //NOTE: assumes no banding - attacker = this.attackers.get(0); - } - - private boolean hasFirstOrDoubleStrike() { - for (CreatureSimulator creature: attackers) { - if (creature.hasDoubleStrike || creature.hasFirstStrike) - return true; - } - for (CreatureSimulator creature: blockers) { - if (creature.hasDoubleStrike || creature.hasFirstStrike) - return true; - } - return false; - } - - public boolean canBlock(Permanent blocker, Game game) { - return blocker.canBlock(attacker.id, game); - } - - public void simulateCombat(Game game) { - unblockedDamage = 0; - - if (hasFirstOrDoubleStrike()) - assignDamage(true, game); - assignDamage(false, game); - } - - private void assignDamage(boolean first, Game game) { - if (blockers.isEmpty()) { - if (canDamage(attacker, first)) - unblockedDamage += attacker.power; - } - else if (blockers.size() == 1) { - CreatureSimulator blocker = blockers.get(0); - if (canDamage(attacker, first)) { - if (attacker.hasTrample) { - int lethalDamage = blocker.getLethalDamage(game); - if (attacker.power > lethalDamage) { - blocker.damage += lethalDamage; - unblockedDamage += attacker.power - lethalDamage; - } - else { - blocker.damage += attacker.power; - } - } - } - if (canDamage(blocker, first)) { - attacker.damage += blocker.power; - } - } - else { - int damage = attacker.power; - for (CreatureSimulator blocker: blockers) { - if (damage > 0 && canDamage(attacker, first)) { - int lethalDamage = blocker.getLethalDamage(game); - if (damage > lethalDamage) { - blocker.damage += lethalDamage; - damage -= lethalDamage; - } - else { - blocker.damage += damage; - damage = 0; - } - } - if (canDamage(blocker, first)) { - attacker.damage += blocker.power; - } - } - if (damage > 0) { - if (attacker.hasTrample) { - unblockedDamage += damage; - } - else { - blockers.get(0).damage += damage; - } - } - } - } - - private boolean canDamage(CreatureSimulator creature, boolean first) { - if (first && (creature.hasFirstStrike || creature.hasDoubleStrike)) - return true; - if (!first && (!creature.hasFirstStrike || creature.hasDoubleStrike)) - return true; - return false; - } - - /** - * returns 3 attacker survives blockers destroyed - * returns 2 both destroyed - * returns 1 both survive - * returns 0 attacker destroyed blockers survive - * - * @return int - */ - public int evaluateCombat() { - int survivingBlockers = 0; - for (CreatureSimulator blocker: blockers) { - if (blocker.damage < blocker.toughness) - survivingBlockers++; - } - if (attacker.isDead()) { - if (survivingBlockers > 0) { - return 0; - } - return 2; - } - else { - if (survivingBlockers > 0) { - return 1; - } - return 3; - } - } -} diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/simulators/CombatSimulator.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/simulators/CombatSimulator.java deleted file mode 100644 index 7157962a522..00000000000 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/simulators/CombatSimulator.java +++ /dev/null @@ -1,86 +0,0 @@ -package mage.player.ai.simulators; - -import mage.counters.CounterType; -import mage.game.Game; -import mage.game.combat.CombatGroup; -import mage.game.permanent.Permanent; -import mage.players.Player; - -import java.io.Serializable; -import java.util.*; -import java.util.Map.Entry; - -/** - * - * @author BetaSteward_at_googlemail.com - */ -public class CombatSimulator implements Serializable { - - public List groups = new ArrayList<>(); - public List defenders = new ArrayList<>(); - public Map playersLife = new HashMap<>(); - public Map planeswalkerLoyalty = new HashMap<>(); - public UUID attackerId; - public int rating = 0; - - public static CombatSimulator load(Game game) { - CombatSimulator simCombat = new CombatSimulator(); - for (CombatGroup group: game.getCombat().getGroups()) { - simCombat.groups.add(new CombatGroupSimulator(group.getDefenderId(), group.getAttackers(), group.getBlockers(), game)); - } - for (UUID defenderId: game.getCombat().getDefenders()) { - simCombat.defenders.add(defenderId); - Player player = game.getPlayer(defenderId); - if (player != null) { - simCombat.playersLife.put(defenderId, player.getLife()); - } - else { - Permanent permanent = game.getPermanent(defenderId); - simCombat.planeswalkerLoyalty.put(defenderId, permanent.getCounters(game).getCount(CounterType.LOYALTY)); - } - } - return simCombat; - } - - public CombatSimulator() {} - - public void clear() { - groups.clear(); - defenders.clear(); - attackerId = null; - } - - public void simulate(Game game) { - for (CombatGroupSimulator group: groups) { - group.simulateCombat(game); - } - } - - public int evaluate() { - Map damage = new HashMap<>(); - int result = 0; - for (CombatGroupSimulator group: groups) { - if (!damage.containsKey(group.defenderId)) { - damage.put(group.defenderId, group.unblockedDamage); - } - else { - damage.put(group.defenderId, damage.get(group.defenderId) + group.unblockedDamage); - } - } - //check for lethal damage to player - for (Entry entry: playersLife.entrySet()) { - if (damage.containsKey(entry.getKey()) && entry.getValue() <= damage.get(entry.getKey())) { - //TODO: check for protection - //NOTE: not applicable for mulitplayer games - return Integer.MAX_VALUE; - } - } - - for (CombatGroupSimulator group: groups) { - result += group.evaluateCombat(); - } - - rating = result; - return result; - } -} diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/simulators/CreatureSimulator.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/simulators/CreatureSimulator.java deleted file mode 100644 index 1a5e7fe7b85..00000000000 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/simulators/CreatureSimulator.java +++ /dev/null @@ -1,57 +0,0 @@ -package mage.player.ai.simulators; - -import mage.abilities.keyword.DoubleStrikeAbility; -import mage.abilities.keyword.FirstStrikeAbility; -import mage.abilities.keyword.TrampleAbility; -import mage.filter.common.FilterCreaturePermanent; -import mage.game.Game; -import mage.game.permanent.Permanent; - -import java.io.Serializable; -import java.util.List; -import java.util.UUID; - -/** - * - * @author BetaSteward_at_googlemail.com - */ -public class CreatureSimulator implements Serializable { - public UUID id; - public int damage; - public int power; - public int toughness; - public boolean hasFirstStrike; - public boolean hasDoubleStrike; - public boolean hasTrample; - public Permanent permanent; - - public CreatureSimulator(Permanent permanent) { - this.id = permanent.getId(); - this.damage = permanent.getDamage(); - this.power = permanent.getPower().getValue(); - this.toughness = permanent.getToughness().getValue(); - this.hasDoubleStrike = permanent.getAbilities().containsKey(DoubleStrikeAbility.getInstance().getId()); - this.hasFirstStrike = permanent.getAbilities().containsKey(FirstStrikeAbility.getInstance().getId()); - this.hasTrample = permanent.getAbilities().containsKey(TrampleAbility.getInstance().getId()); - this.permanent = permanent; - } - - public boolean isDead() { - return damage >= toughness; - } - - public int getLethalDamage(Game game) { - List usePowerInsteadOfToughnessForDamageLethalityFilters = game.getState().getActivePowerInsteadOfToughnessForDamageLethalityFilters(); - /* - * for handling Zilortha, Strength Incarnate: - * 2020-04-17 - * Any time the game is checking whether damage is lethal or if a creature should be destroyed for having lethal damage marked on it, use the power of your creatures rather than their toughness to check the damage against. This includes being assigned trample damage, damage from Flame Spill, and so on. - */ - boolean usePowerInsteadOfToughnessForDamageLethality = usePowerInsteadOfToughnessForDamageLethalityFilters.stream() - .anyMatch(filter -> filter.match(permanent, game)); - int lethalDamageThreshold = usePowerInsteadOfToughnessForDamageLethality ? - // Zilortha, Strength Incarnate, 2020-04-17: A creature with 0 power isn’t destroyed unless it has at least 1 damage marked on it. - Math.max(power, 1) : toughness; - return Math.max(lethalDamageThreshold - damage, 0); - } -} 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 944d9aa5135..f3dd92bb7be 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 @@ -288,6 +288,16 @@ public final class SimulatedPlayerMCTS extends MCTSPlayer { @Override public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game) { + + // nothing to choose + target.prepareAmount(source, game); + if (target.getAmountRemaining() <= 0) { + return false; + } + if (target.getMaxNumberOfTargets() == 0 && target.getMinNumberOfTargets() == 0) { + return false; + } + Set possibleTargets = target.possibleTargets(playerId, source, game); if (possibleTargets.isEmpty()) { return !target.isRequired(source); 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 c0ab0e728db..cd7b6569cf8 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 @@ -297,7 +297,7 @@ public class HumanPlayer extends PlayerImpl { return; } if (logger.isDebugEnabled()) { - logger.debug("Setting game priority for " + getId() + " [" + DebugUtil.getMethodNameWithSource(1) + ']'); + logger.debug("Setting game priority for " + getId() + " [" + DebugUtil.getMethodNameWithSource(1, "method") + ']'); } game.getState().setPriorityPlayerId(getId()); } @@ -328,7 +328,7 @@ public class HumanPlayer extends PlayerImpl { while (loop) { // start waiting for next answer response.clear(); - response.setActiveAction(game, DebugUtil.getMethodNameWithSource(1)); + response.setActiveAction(game, DebugUtil.getMethodNameWithSource(1, "method")); game.resumeTimer(getTurnControlledBy()); responseOpenedForAnswer = true; @@ -690,12 +690,8 @@ public class HumanPlayer extends PlayerImpl { return false; } - // choose one or multiple permanents - UUID abilityControllerId = playerId; - if (target.getTargetController() != null - && target.getAbilityController() != null) { - abilityControllerId = target.getAbilityController(); - } + // choose one or multiple targets + UUID abilityControllerId = target.getAffectedAbilityControllerId(this.getId()); if (options == null) { options = new HashMap<>(); } @@ -782,11 +778,7 @@ public class HumanPlayer extends PlayerImpl { } // choose one or multiple targets - UUID abilityControllerId = playerId; - if (target.getAbilityController() != null) { - abilityControllerId = target.getAbilityController(); - } - + UUID abilityControllerId = target.getAffectedAbilityControllerId(this.getId()); Map options = new HashMap<>(); while (canRespond()) { @@ -869,13 +861,7 @@ public class HumanPlayer extends PlayerImpl { return false; } - UUID abilityControllerId; - if (target.getTargetController() != null - && target.getAbilityController() != null) { - abilityControllerId = target.getAbilityController(); - } else { - abilityControllerId = playerId; - } + UUID abilityControllerId = target.getAffectedAbilityControllerId(this.getId()); while (canRespond()) { @@ -966,13 +952,7 @@ public class HumanPlayer extends PlayerImpl { return false; } - UUID abilityControllerId; - if (target.getTargetController() != null - && target.getAbilityController() != null) { - abilityControllerId = target.getAbilityController(); - } else { - abilityControllerId = playerId; - } + UUID abilityControllerId = target.getAffectedAbilityControllerId(this.getId()); while (canRespond()) { boolean required = target.isRequiredExplicitlySet() ? target.isRequired() : target.isRequired(source); @@ -1042,14 +1022,20 @@ public class HumanPlayer extends PlayerImpl { return false; } + // nothing to choose + target.prepareAmount(source, game); + if (target.getAmountRemaining() <= 0) { + return false; + } + if (target.getMaxNumberOfTargets() == 0 && target.getMinNumberOfTargets() == 0) { + return false; + } + if (source == null) { return false; } - UUID abilityControllerId = playerId; - if (target.getAbilityController() != null) { - abilityControllerId = target.getAbilityController(); - } + UUID abilityControllerId = target.getAffectedAbilityControllerId(this.getId()); int amountTotal = target.getAmountTotal(game, source); if (amountTotal == 0) { diff --git a/Mage.Sets/src/mage/cards/a/AbunaAcolyte.java b/Mage.Sets/src/mage/cards/a/AbunaAcolyte.java index 2b4699f8d01..f072fd4e51a 100644 --- a/Mage.Sets/src/mage/cards/a/AbunaAcolyte.java +++ b/Mage.Sets/src/mage/cards/a/AbunaAcolyte.java @@ -14,6 +14,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetAnyTarget; import mage.target.common.TargetCreaturePermanent; @@ -39,7 +40,7 @@ public final class AbunaAcolyte extends CardImpl { Ability ability1 = new SimpleActivatedAbility(new PreventDamageToTargetEffect(Duration.EndOfTurn, 1), new TapSourceCost()); ability1.addTarget(new TargetAnyTarget()); Ability ability2 = new SimpleActivatedAbility(new PreventDamageToTargetEffect(Duration.EndOfTurn, 2), new TapSourceCost()); - ability2.addTarget(new TargetCreaturePermanent(filter)); + ability2.addTarget(new TargetPermanent(filter)); this.addAbility(ability1); this.addAbility(ability2); } diff --git a/Mage.Sets/src/mage/cards/a/AbzanCharm.java b/Mage.Sets/src/mage/cards/a/AbzanCharm.java index 288f3e1c380..64e1e67de45 100644 --- a/Mage.Sets/src/mage/cards/a/AbzanCharm.java +++ b/Mage.Sets/src/mage/cards/a/AbzanCharm.java @@ -13,6 +13,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanentAmount; @@ -33,7 +34,7 @@ public final class AbzanCharm extends CardImpl { // Choose one - // *Exile target creature with power 3 or greater - this.getSpellAbility().addTarget(new TargetCreaturePermanent(FILTER)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER)); this.getSpellAbility().addEffect(new ExileTargetEffect()); // *You draw two cards and you lose 2 life diff --git a/Mage.Sets/src/mage/cards/a/AcademyJourneymage.java b/Mage.Sets/src/mage/cards/a/AcademyJourneymage.java index a3b3893e1ba..dd12271e5c0 100644 --- a/Mage.Sets/src/mage/cards/a/AcademyJourneymage.java +++ b/Mage.Sets/src/mage/cards/a/AcademyJourneymage.java @@ -16,10 +16,13 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.StaticFilters; import mage.filter.common.FilterControlledPermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * @author JRHerlehy */ @@ -47,7 +50,7 @@ public final class AcademyJourneymage extends CardImpl { // When Academy Journeymage enters the battlefield, return target creature an opponent controls to its owner's hand. ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AccumulatedKnowledge.java b/Mage.Sets/src/mage/cards/a/AccumulatedKnowledge.java index 9089d5f3d76..ab3716f78c3 100644 --- a/Mage.Sets/src/mage/cards/a/AccumulatedKnowledge.java +++ b/Mage.Sets/src/mage/cards/a/AccumulatedKnowledge.java @@ -1,7 +1,6 @@ package mage.cards.a; -import java.util.UUID; import mage.abilities.dynamicvalue.common.CardsInAllGraveyardsCount; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; @@ -11,8 +10,9 @@ import mage.constants.CardType; import mage.filter.FilterCard; import mage.filter.predicate.mageobject.NamePredicate; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class AccumulatedKnowledge extends CardImpl { @@ -24,13 +24,13 @@ public final class AccumulatedKnowledge extends CardImpl { } public AccumulatedKnowledge(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); // Draw a card, then draw cards equal to the number of cards named Accumulated Knowledge in all graveyards. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); Effect effect = new DrawCardSourceControllerEffect(new CardsInAllGraveyardsCount(filter)); - effect.setText(", then draw cards equal to the number of cards named {this} in all graveyards"); + effect.setText(", then draw cards equal to the number of cards named Accumulated Knowledge in all graveyards"); this.getSpellAbility().addEffect(effect); } diff --git a/Mage.Sets/src/mage/cards/a/AcererakTheArchlich.java b/Mage.Sets/src/mage/cards/a/AcererakTheArchlich.java index d429f82da8c..7e2a4356737 100644 --- a/Mage.Sets/src/mage/cards/a/AcererakTheArchlich.java +++ b/Mage.Sets/src/mage/cards/a/AcererakTheArchlich.java @@ -44,9 +44,7 @@ public final class AcererakTheArchlich extends CardImpl { Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandSourceEffect(true)) .withInterveningIf(AcererakTheArchlichCondition.instance); ability.addEffect(new VentureIntoTheDungeonEffect().concatBy("and")); - ability.addHint(CurrentDungeonHint.instance); - ability.addHint(CompletedDungeonCondition.getHint()); - this.addAbility(ability, new CompletedDungeonWatcher()); + this.addAbility(ability.addHint(CurrentDungeonHint.instance).addHint(CompletedDungeonCondition.getHint()), new CompletedDungeonWatcher()); // Whenever Acererak the Archlich attacks, for each opponent, you create a 2/2 black Zombie creature token unless that player sacrifices a creature. this.addAbility(new AttacksTriggeredAbility(new AcererakTheArchlichEffect())); @@ -83,7 +81,7 @@ class AcererakTheArchlichEffect extends OneShotEffect { AcererakTheArchlichEffect() { super(Outcome.Benefit); staticText = "for each opponent, you create a 2/2 black Zombie creature " + - "token unless that player sacrifices a creature"; + "token unless that player sacrifices a creature of their choice"; } private AcererakTheArchlichEffect(final AcererakTheArchlichEffect effect) { diff --git a/Mage.Sets/src/mage/cards/a/AcesBaseballBat.java b/Mage.Sets/src/mage/cards/a/AcesBaseballBat.java index 0a54026f17a..2eca11d118b 100644 --- a/Mage.Sets/src/mage/cards/a/AcesBaseballBat.java +++ b/Mage.Sets/src/mage/cards/a/AcesBaseballBat.java @@ -15,7 +15,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.common.FilterControlledCreaturePermanent; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -60,7 +60,7 @@ public final class AcesBaseballBat extends CardImpl { // Equip legendary creature (1) this.addAbility(new EquipAbility( Outcome.AddAbility, new GenericManaCost(1), - new TargetControlledCreaturePermanent(filterLegendary), false + new TargetPermanent(filterLegendary), false )); // Equip {3} diff --git a/Mage.Sets/src/mage/cards/a/AcidicDagger.java b/Mage.Sets/src/mage/cards/a/AcidicDagger.java index a33f2c051fe..5cd4d7e2e98 100644 --- a/Mage.Sets/src/mage/cards/a/AcidicDagger.java +++ b/Mage.Sets/src/mage/cards/a/AcidicDagger.java @@ -5,7 +5,7 @@ import mage.abilities.DelayedTriggeredAbility; import mage.abilities.condition.common.BeforeBlockersAreDeclaredCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.DestroyTargetEffect; @@ -39,7 +39,7 @@ public final class AcidicDagger extends CardImpl { // {4}, {tap}: Whenever target creature deals combat damage to a non-Wall creature this turn, // destroy that non-Wall creature. When the targeted creature leaves the battlefield this turn, // sacrifice Acidic Dagger. Activate this ability only before blockers are declared. - Ability ability = new ConditionalActivatedAbility( + Ability ability = new ActivateIfConditionActivatedAbility( new CreateDelayedTriggeredAbilityEffect(new AcidicDaggerDestroyNonWallAbility()), new GenericManaCost(4), BeforeBlockersAreDeclaredCondition.instance); diff --git a/Mage.Sets/src/mage/cards/a/ActOfAggression.java b/Mage.Sets/src/mage/cards/a/ActOfAggression.java index 468e53e5f16..8787eaedb16 100644 --- a/Mage.Sets/src/mage/cards/a/ActOfAggression.java +++ b/Mage.Sets/src/mage/cards/a/ActOfAggression.java @@ -11,8 +11,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author North @@ -21,7 +24,7 @@ public final class ActOfAggression extends CardImpl { public ActOfAggression(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{R/P}{R/P}"); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.EndOfTurn)); this.getSpellAbility().addEffect(new UntapTargetEffect().setText("Untap that creature")); this.getSpellAbility().addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn).setText("It gains haste until end of turn.")); diff --git a/Mage.Sets/src/mage/cards/a/AdaptiveOmnitool.java b/Mage.Sets/src/mage/cards/a/AdaptiveOmnitool.java index f88856700d9..7e9d1901c0f 100644 --- a/Mage.Sets/src/mage/cards/a/AdaptiveOmnitool.java +++ b/Mage.Sets/src/mage/cards/a/AdaptiveOmnitool.java @@ -1,7 +1,5 @@ package mage.cards.a; -import java.util.UUID; - import mage.abilities.common.AttacksAttachedTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; @@ -9,35 +7,35 @@ import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; +import mage.abilities.hint.common.ArtifactYouControlHint; import mage.abilities.keyword.EquipAbility; -import mage.constants.Outcome; -import mage.constants.PutCards; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.PutCards; +import mage.constants.SubType; import mage.filter.StaticFilters; import mage.filter.common.FilterControlledArtifactPermanent; import mage.target.common.TargetControlledCreaturePermanent; +import java.util.UUID; + /** - * * @author sobiech */ public final class AdaptiveOmnitool extends CardImpl { + private final static DynamicValue artifactYouControlCount = new PermanentsOnBattlefieldCount(new FilterControlledArtifactPermanent()); - private final static Hint hint = new ValueHint("Artifacts you control", artifactYouControlCount); public AdaptiveOmnitool(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); - + this.subtype.add(SubType.EQUIPMENT); // Equipped creature gets +1/+1 for each artifact you control. this.addAbility( - new SimpleStaticAbility(new BoostEquippedEffect(artifactYouControlCount, artifactYouControlCount)).addHint(hint) + new SimpleStaticAbility(new BoostEquippedEffect(artifactYouControlCount, artifactYouControlCount)).addHint(ArtifactYouControlHint.instance) ); // Whenever equipped creature attacks, look at the top six cards of your library. You may reveal an artifact card from among them and put it into your hand. Put the rest on the bottom of your library in a random order. diff --git a/Mage.Sets/src/mage/cards/a/AdaptiveTrainingPost.java b/Mage.Sets/src/mage/cards/a/AdaptiveTrainingPost.java index 36f48cb6f75..b53f18cfd23 100644 --- a/Mage.Sets/src/mage/cards/a/AdaptiveTrainingPost.java +++ b/Mage.Sets/src/mage/cards/a/AdaptiveTrainingPost.java @@ -31,7 +31,7 @@ public final class AdaptiveTrainingPost extends CardImpl { this.addAbility(new SpellCastControllerTriggeredAbility( new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false - ).withInterveningIf(condition)); + ).withInterveningIf(condition).withRuleTextReplacement(true)); // Remove three charge counters from this artifact: When you next cast an instant or sorcery spell this turn, copy it and you may choose new targets for the copy. this.addAbility(new SimpleActivatedAbility( diff --git a/Mage.Sets/src/mage/cards/a/AdmonitionAngel.java b/Mage.Sets/src/mage/cards/a/AdmonitionAngel.java index a7597e37970..4a0c7e97325 100644 --- a/Mage.Sets/src/mage/cards/a/AdmonitionAngel.java +++ b/Mage.Sets/src/mage/cards/a/AdmonitionAngel.java @@ -1,7 +1,6 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.TriggeredAbility; @@ -20,13 +19,15 @@ import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.target.TargetPermanent; +import java.util.UUID; + /** * * @author jeffwadsworth */ public final class AdmonitionAngel extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("nonland permanent other than Admonition Angel"); + private static final FilterPermanent filter = new FilterPermanent("nonland permanent other than {this}"); static { filter.add(AnotherPredicate.instance); diff --git a/Mage.Sets/src/mage/cards/a/AdvocateOfTheBeast.java b/Mage.Sets/src/mage/cards/a/AdvocateOfTheBeast.java index a72aa079675..1b3220379d8 100644 --- a/Mage.Sets/src/mage/cards/a/AdvocateOfTheBeast.java +++ b/Mage.Sets/src/mage/cards/a/AdvocateOfTheBeast.java @@ -14,6 +14,7 @@ import mage.constants.TargetController; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,7 +39,7 @@ public final class AdvocateOfTheBeast extends CardImpl { // At the beginning of your end step, put a +1/+1 counter on target Beast creature you control. Ability ability = new BeginningOfEndStepTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance())); - Target target = new TargetCreaturePermanent(filter); + Target target = new TargetPermanent(filter); ability.addTarget(target); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AegisAutomaton.java b/Mage.Sets/src/mage/cards/a/AegisAutomaton.java index db0ea3472ea..ee80a59768b 100644 --- a/Mage.Sets/src/mage/cards/a/AegisAutomaton.java +++ b/Mage.Sets/src/mage/cards/a/AegisAutomaton.java @@ -1,6 +1,5 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -10,12 +9,12 @@ 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.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author fireshoes */ public final class AegisAutomaton extends CardImpl { @@ -29,7 +28,7 @@ public final class AegisAutomaton extends CardImpl { // {4}{W}: Return another target creature you control to its owner's hand. Ability ability = new SimpleActivatedAbility(new ReturnToHandTargetEffect(), new ManaCostsImpl<>("{4}{W}")); - ability.addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AegisOfTheMeek.java b/Mage.Sets/src/mage/cards/a/AegisOfTheMeek.java index 96bbbbfc9c8..b7ae289da89 100644 --- a/Mage.Sets/src/mage/cards/a/AegisOfTheMeek.java +++ b/Mage.Sets/src/mage/cards/a/AegisOfTheMeek.java @@ -16,6 +16,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; import mage.filter.predicate.mageobject.ToughnessPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -37,7 +38,7 @@ public final class AegisOfTheMeek extends CardImpl { // {1}, {T}: Target 1/1 creature gets +1/+2 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(1, 2, Duration.EndOfTurn), new ManaCostsImpl<>("{1}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AerialPredation.java b/Mage.Sets/src/mage/cards/a/AerialPredation.java index e0abfba71bd..e3e9164983e 100644 --- a/Mage.Sets/src/mage/cards/a/AerialPredation.java +++ b/Mage.Sets/src/mage/cards/a/AerialPredation.java @@ -12,6 +12,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -31,7 +32,7 @@ public final class AerialPredation extends CardImpl { // Destroy target creature with flying. You gain 2 life. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); this.getSpellAbility().addEffect(new GainLifeEffect(2)); } diff --git a/Mage.Sets/src/mage/cards/a/AerialSurveyor.java b/Mage.Sets/src/mage/cards/a/AerialSurveyor.java index 0aaed9d279b..b8199c1a008 100644 --- a/Mage.Sets/src/mage/cards/a/AerialSurveyor.java +++ b/Mage.Sets/src/mage/cards/a/AerialSurveyor.java @@ -84,7 +84,7 @@ enum AerialSurveyorCondition implements Condition { @Override public String toString() { - return ""; + return "defending player controls more lands than you"; } } diff --git a/Mage.Sets/src/mage/cards/a/AerieOuphes.java b/Mage.Sets/src/mage/cards/a/AerieOuphes.java index cbe0fccb147..588d018cefd 100644 --- a/Mage.Sets/src/mage/cards/a/AerieOuphes.java +++ b/Mage.Sets/src/mage/cards/a/AerieOuphes.java @@ -16,6 +16,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -42,7 +43,7 @@ public final class AerieOuphes extends CardImpl { // Sacrifice Aerie Ouphes: Aerie Ouphes deals damage equal to its power to target creature with flying. Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(SourcePermanentPowerValue.NOT_NEGATIVE) .setText("it deals damage equal to its power to target creature with flying"), new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // Persist diff --git a/Mage.Sets/src/mage/cards/a/AetherBarrier.java b/Mage.Sets/src/mage/cards/a/AetherBarrier.java index 170ea126d00..8378d421e33 100644 --- a/Mage.Sets/src/mage/cards/a/AetherBarrier.java +++ b/Mage.Sets/src/mage/cards/a/AetherBarrier.java @@ -44,7 +44,7 @@ class AetherBarrierEffect extends SacrificeEffect { AetherBarrierEffect() { super(new FilterPermanent("permanent to sacrifice"), 1, "that player"); - this.staticText = "that player sacrifices a permanent unless they pay {1}"; + this.staticText = "that player sacrifices a permanent of their choice unless they pay {1}"; } private AetherBarrierEffect(final AetherBarrierEffect effect) { diff --git a/Mage.Sets/src/mage/cards/a/AethershieldArtificer.java b/Mage.Sets/src/mage/cards/a/AethershieldArtificer.java index 834f30d8126..381028cfea3 100644 --- a/Mage.Sets/src/mage/cards/a/AethershieldArtificer.java +++ b/Mage.Sets/src/mage/cards/a/AethershieldArtificer.java @@ -1,22 +1,22 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.IndestructibleAbility; -import mage.constants.SubType; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; +import mage.constants.SubType; import mage.filter.common.FilterControlledCreaturePermanent; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class AethershieldArtificer extends CardImpl { @@ -45,7 +45,7 @@ public final class AethershieldArtificer extends CardImpl { IndestructibleAbility.getInstance(), Duration.EndOfTurn ).setText("and gains indestructible until end of turn")); - ability.addTarget(new TargetControlledCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/Aethertow.java b/Mage.Sets/src/mage/cards/a/Aethertow.java index 7db15f9b34d..834eff2e808 100644 --- a/Mage.Sets/src/mage/cards/a/Aethertow.java +++ b/Mage.Sets/src/mage/cards/a/Aethertow.java @@ -13,6 +13,7 @@ import mage.filter.common.FilterAttackingOrBlockingCreature; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -28,7 +29,7 @@ public final class Aethertow extends CardImpl { // Put target attacking or blocking creature on top of its owner's library. this.getSpellAbility().addEffect(new AethertowEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // Conspire this.addAbility(new ConspireAbility(ConspireAbility.ConspireTargets.ONE)); diff --git a/Mage.Sets/src/mage/cards/a/AffectionateIndrik.java b/Mage.Sets/src/mage/cards/a/AffectionateIndrik.java index 3e469e6ebb1..644bb7447eb 100644 --- a/Mage.Sets/src/mage/cards/a/AffectionateIndrik.java +++ b/Mage.Sets/src/mage/cards/a/AffectionateIndrik.java @@ -9,10 +9,13 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author TheElk801 */ @@ -32,7 +35,7 @@ public final class AffectionateIndrik extends CardImpl { "(Each deals damage equal to its power to the other.)"), true ); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + ability.addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AgadeemOccultist.java b/Mage.Sets/src/mage/cards/a/AgadeemOccultist.java index b5bf7698444..0db9443e93b 100644 --- a/Mage.Sets/src/mage/cards/a/AgadeemOccultist.java +++ b/Mage.Sets/src/mage/cards/a/AgadeemOccultist.java @@ -5,7 +5,9 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.OneShotEffect; +import mage.abilities.hint.ValueHint; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -13,9 +15,9 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.Zone; -import mage.filter.FilterCard; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.common.FilterCreatureCard; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCardInOpponentsGraveyard; @@ -37,7 +39,10 @@ public final class AgadeemOccultist extends CardImpl { this.toughness = new MageInt(2); // {tap}: Put target creature card from an opponent's graveyard onto the battlefield under your control if its converted mana cost is less than or equal to the number of Allies you control. - this.addAbility(new SimpleActivatedAbility(new AgadeemOccultistEffect(), new TapSourceCost())); + Ability ability = new SimpleActivatedAbility(new AgadeemOccultistEffect(), new TapSourceCost()); + ability.addTarget(new TargetCardInOpponentsGraveyard(new FilterCreatureCard("target creature card from an opponent's graveyard"))); + ability.addHint(new ValueHint("Allies you control", new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.ALLY)))); + this.addAbility(ability); } @@ -50,7 +55,6 @@ public final class AgadeemOccultist extends CardImpl { return new AgadeemOccultist(this); } } - class AgadeemOccultistEffect extends OneShotEffect { AgadeemOccultistEffect() { @@ -70,26 +74,12 @@ class AgadeemOccultistEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - int allycount = 0; - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) { - if (permanent.hasSubtype(SubType.ALLY, game)) { - allycount++; - } - } - FilterCard filter = new FilterCard("creature card in an opponent's graveyard"); - filter.add(CardType.CREATURE.getPredicate()); - TargetCardInOpponentsGraveyard target = new TargetCardInOpponentsGraveyard(1, 1, filter); - if (controller != null) { - if (target.canChoose(source.getControllerId(), source, game) - && controller.choose(Outcome.GainControl, target, source, game)) { - if (!target.getTargets().isEmpty()) { - Card card = game.getCard(target.getFirstTarget()); - if (card != null) { - if (card.getManaValue() <= allycount) { - return controller.moveCards(card, Zone.BATTLEFIELD, source, game); - } - } + Card card = game.getCard(source.getFirstTarget()); + if (card != null) { + int allycount = new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.ALLY)).calculate(game, source, this); + if (card.getManaValue() <= allycount) { + return controller.moveCards(card, Zone.BATTLEFIELD, source, game); } } return true; diff --git a/Mage.Sets/src/mage/cards/a/AgentOfAcquisitions.java b/Mage.Sets/src/mage/cards/a/AgentOfAcquisitions.java index abd5645d229..88cd9f907c8 100644 --- a/Mage.Sets/src/mage/cards/a/AgentOfAcquisitions.java +++ b/Mage.Sets/src/mage/cards/a/AgentOfAcquisitions.java @@ -1,15 +1,16 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.InfoEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; -import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.common.InfoEffect; + +import java.util.UUID; /** * @@ -27,7 +28,7 @@ public final class AgentOfAcquisitions extends CardImpl { // TODO: Draft specific abilities not implemented // Draft Agent of Acquisitions face up. - this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Draft Agent of Acquisitions face up - not implemented."))); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Draft {this} face up - not implemented."))); // Instead of drafting a card from a booster pack, you may draft each card in that booster pack, one at a time. If you do, turn Agent of Acquisitions face down and you can’t draft cards for the rest of this draft round. this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Instead of drafting a card from a booster pack, " diff --git a/Mage.Sets/src/mage/cards/a/AggressiveInstinct.java b/Mage.Sets/src/mage/cards/a/AggressiveInstinct.java index 5b7bad83ffd..b2b09bf3928 100644 --- a/Mage.Sets/src/mage/cards/a/AggressiveInstinct.java +++ b/Mage.Sets/src/mage/cards/a/AggressiveInstinct.java @@ -5,11 +5,14 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author TheElk801 */ @@ -21,7 +24,7 @@ public final class AggressiveInstinct extends CardImpl { // Target creature you control deals damage equal to its power to target creature you don't control. this.getSpellAbility().addEffect(new DamageWithPowerFromOneToAnotherTargetEffect()); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); } private AggressiveInstinct(final AggressiveInstinct card) { diff --git a/Mage.Sets/src/mage/cards/a/AgonizingDemise.java b/Mage.Sets/src/mage/cards/a/AgonizingDemise.java index 35bca60480d..d55c3c7a4ad 100644 --- a/Mage.Sets/src/mage/cards/a/AgonizingDemise.java +++ b/Mage.Sets/src/mage/cards/a/AgonizingDemise.java @@ -10,10 +10,13 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * @author FenrisulfrX */ @@ -27,7 +30,7 @@ public final class AgonizingDemise extends CardImpl { // Destroy target nonblack creature. It can't be regenerated. this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); // If Agonizing Demise was kicked, it deals damage equal to that creature's power to the creature's controller. this.getSpellAbility().addEffect(new ConditionalOneShotEffect( diff --git a/Mage.Sets/src/mage/cards/a/AgrusKosEternalSoldier.java b/Mage.Sets/src/mage/cards/a/AgrusKosEternalSoldier.java index c2090ee031a..31cbd6f881b 100644 --- a/Mage.Sets/src/mage/cards/a/AgrusKosEternalSoldier.java +++ b/Mage.Sets/src/mage/cards/a/AgrusKosEternalSoldier.java @@ -23,7 +23,6 @@ import mage.game.stack.Spell; import mage.game.stack.StackObject; import mage.players.Player; import mage.target.Target; -import mage.util.CardUtil; import java.util.Collection; import java.util.List; @@ -90,7 +89,7 @@ class AgrusKosEternalSoldierTriggeredAbility extends TriggeredAbilityImpl { if (!event.getTargetId().equals(getSourceId())) { return false; } - StackObject targetingObject = CardUtil.findTargetingStackObject(this.getId().toString(), event, game); + StackObject targetingObject = game.findTargetingStackObject(this.getId().toString(), event); if (targetingObject == null || targetingObject instanceof Spell) { return false; } diff --git a/Mage.Sets/src/mage/cards/a/AidFromTheCowl.java b/Mage.Sets/src/mage/cards/a/AidFromTheCowl.java index 3cd45e595ad..ade3ca20c8f 100644 --- a/Mage.Sets/src/mage/cards/a/AidFromTheCowl.java +++ b/Mage.Sets/src/mage/cards/a/AidFromTheCowl.java @@ -50,7 +50,7 @@ class AidFromTheCowlEffect extends OneShotEffect { AidFromTheCowlEffect() { super(Outcome.PutCreatureInPlay); this.staticText = "reveal the top card of your library. If it's a permanent card, " + - "you may put it onto the battlefield. Otherwise, you may put that card on the bottom of your library"; + "you may put it onto the battlefield. Otherwise, you may put it on the bottom of your library"; } private AidFromTheCowlEffect(final AidFromTheCowlEffect effect) { diff --git a/Mage.Sets/src/mage/cards/a/AirCultElemental.java b/Mage.Sets/src/mage/cards/a/AirCultElemental.java index 173b62f090d..f7689e5385c 100644 --- a/Mage.Sets/src/mage/cards/a/AirCultElemental.java +++ b/Mage.Sets/src/mage/cards/a/AirCultElemental.java @@ -1,21 +1,21 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.common.ReturnToHandTargetEffect; -import mage.constants.SubType; 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.AnotherPredicate; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author weirddan455 */ public final class AirCultElemental extends CardImpl { @@ -38,7 +38,7 @@ public final class AirCultElemental extends CardImpl { // Whirlwind — When Air-Cult Elemental enters the battlefield, return up to one other target creature to its owner's hand. Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()); - ability.addTarget(new TargetCreaturePermanent(0, 1, filter, false)); + ability.addTarget(new TargetPermanent(0, 1, filter)); this.addAbility(ability.withFlavorWord("Whirlwind")); } diff --git a/Mage.Sets/src/mage/cards/a/AirServant.java b/Mage.Sets/src/mage/cards/a/AirServant.java index 59d071fe21f..da105691266 100644 --- a/Mage.Sets/src/mage/cards/a/AirServant.java +++ b/Mage.Sets/src/mage/cards/a/AirServant.java @@ -16,6 +16,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,7 +39,7 @@ public final class AirServant extends CardImpl { this.toughness = new MageInt(3); this.addAbility(FlyingAbility.getInstance()); Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new ManaCostsImpl<>("{2}{U}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AjaniFellsTheGodsire.java b/Mage.Sets/src/mage/cards/a/AjaniFellsTheGodsire.java index 96391abd3e0..aaa321844a5 100644 --- a/Mage.Sets/src/mage/cards/a/AjaniFellsTheGodsire.java +++ b/Mage.Sets/src/mage/cards/a/AjaniFellsTheGodsire.java @@ -23,6 +23,8 @@ import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.constants.SagaChapter.CHAPTER_I; + /** * @author Susucr */ @@ -45,8 +47,8 @@ public final class AjaniFellsTheGodsire extends CardImpl { // I -- Exile target creature an opponent controls with power 3 or greater. sagaAbility.addChapterEffect( - this, SagaChapter.CHAPTER_I, SagaChapter.CHAPTER_I, - new ExileTargetEffect(), new TargetCreaturePermanent(filter) + this, CHAPTER_I, CHAPTER_I, + new ExileTargetEffect(), new TargetPermanent(filter) ); // II -- Create a 2/1 white Cat Warrior creature token, then put a vigilance counter on a creature you control. @@ -104,4 +106,4 @@ class AjaniFellsTheGodsireCounterEffect extends OneShotEffect { Permanent permanent = game.getPermanent(target.getFirstTarget()); return permanent != null && permanent.addCounters(CounterType.VIGILANCE.createInstance(), source, game); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/a/AjanisMantra.java b/Mage.Sets/src/mage/cards/a/AjanisMantra.java index 24cf9c68bc0..ea8ca8f9a2c 100644 --- a/Mage.Sets/src/mage/cards/a/AjanisMantra.java +++ b/Mage.Sets/src/mage/cards/a/AjanisMantra.java @@ -1,24 +1,22 @@ - - package mage.cards.a; -import java.util.UUID; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.game.events.GameEvent.EventType; + +import java.util.UUID; /** - * * @author BetaSteward_at_googlemail.com */ public final class AjanisMantra extends CardImpl { public AjanisMantra(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}"); - this.addAbility(new OnEventTriggeredAbility(EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", new GainLifeEffect(1), true)); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}"); + + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new GainLifeEffect(1), true)); } private AjanisMantra(final AjanisMantra card) { @@ -29,5 +27,4 @@ public final class AjanisMantra extends CardImpl { public AjanisMantra copy() { return new AjanisMantra(this); } - } diff --git a/Mage.Sets/src/mage/cards/a/AkroanConscriptor.java b/Mage.Sets/src/mage/cards/a/AkroanConscriptor.java index 519e4086dff..1911476f4a3 100644 --- a/Mage.Sets/src/mage/cards/a/AkroanConscriptor.java +++ b/Mage.Sets/src/mage/cards/a/AkroanConscriptor.java @@ -16,8 +16,11 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * * @author LevelX2 @@ -40,7 +43,7 @@ public final class AkroanConscriptor extends CardImpl { effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn); effect.setText("It gains haste until end of turn"); ability.addEffect(effect); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AkutaBornOfAsh.java b/Mage.Sets/src/mage/cards/a/AkutaBornOfAsh.java index 44822285a72..7be6f3b471a 100644 --- a/Mage.Sets/src/mage/cards/a/AkutaBornOfAsh.java +++ b/Mage.Sets/src/mage/cards/a/AkutaBornOfAsh.java @@ -1,12 +1,12 @@ package mage.cards.a; import mage.MageInt; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.MoreCardsInHandThanOpponentsCondition; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; import mage.abilities.keyword.HasteAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -15,18 +15,14 @@ import mage.filter.common.FilterControlledPermanent; import java.util.UUID; /** - * * @author LevelX2 */ public final class AkutaBornOfAsh extends CardImpl { - private static final FilterControlledPermanent filterSwamp = new FilterControlledPermanent("a Swamp"); - static { - filterSwamp.add(SubType.SWAMP.getPredicate()); - } + private static final FilterControlledPermanent filterSwamp = new FilterControlledPermanent(SubType.SWAMP, "a Swamp"); public AkutaBornOfAsh(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.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.SPIRIT); @@ -37,9 +33,14 @@ public final class AkutaBornOfAsh extends CardImpl { this.addAbility(HasteAbility.getInstance()); // At the beginning of your upkeep, if you have more cards in hand than each opponent, you may sacrifice a Swamp. If you do, return Akuta, Born of Ash from your graveyard to the battlefield. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.GRAVEYARD, - TargetController.YOU, new DoIfCostPaid(new ReturnSourceFromGraveyardToBattlefieldEffect(), new SacrificeTargetCost(filterSwamp)), - false).withInterveningIf(MoreCardsInHandThanOpponentsCondition.instance)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + Zone.GRAVEYARD, TargetController.YOU, + new DoIfCostPaid( + new ReturnSourceFromGraveyardToBattlefieldEffect() + .setText("return {this} from your graveyard to the battlefield"), + new SacrificeTargetCost(filterSwamp) + ), false + ).withInterveningIf(MoreCardsInHandThanOpponentsCondition.instance)); } private AkutaBornOfAsh(final AkutaBornOfAsh card) { diff --git a/Mage.Sets/src/mage/cards/a/AlabornVeteran.java b/Mage.Sets/src/mage/cards/a/AlabornVeteran.java index a9280a62891..80ade8c4ea7 100644 --- a/Mage.Sets/src/mage/cards/a/AlabornVeteran.java +++ b/Mage.Sets/src/mage/cards/a/AlabornVeteran.java @@ -1,7 +1,5 @@ - package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; @@ -13,25 +11,27 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class AlabornVeteran extends CardImpl { public AlabornVeteran(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.KNIGHT); this.power = new MageInt(2); this.toughness = new MageInt(2); // {tap}: Target creature gets +2/+2 until end of turn. Activate this ability only during your turn, before attackers are declared. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new BoostTargetEffect(2, 2, Duration.EndOfTurn), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new BoostTargetEffect(2, 2, Duration.EndOfTurn), + new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance + ); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AlaniaDivergentStorm.java b/Mage.Sets/src/mage/cards/a/AlaniaDivergentStorm.java index 693347ae678..5b73990ab2e 100644 --- a/Mage.Sets/src/mage/cards/a/AlaniaDivergentStorm.java +++ b/Mage.Sets/src/mage/cards/a/AlaniaDivergentStorm.java @@ -42,10 +42,13 @@ public final class AlaniaDivergentStorm extends CardImpl { // Whenever you cast a spell, if it's the first instant spell, the first sorcery spell, or the first Otter // spell other than Alania you've cast this turn, you may have target opponent draw a card. If you do, copy // that spell. You may choose new targets for the copy. - this.addAbility(new SpellCastControllerTriggeredAbility( - new DoIfCostPaid(new CopyTargetStackObjectEffect(true), new AlaniaDivergentStormCost()), + Ability ability = new SpellCastControllerTriggeredAbility( + new DoIfCostPaid(new CopyTargetStackObjectEffect(true).setText("copy that spell. You may choose new targets for the copy") + , new AlaniaDivergentStormCost()), null, false, SetTargetPointer.SPELL - ).withInterveningIf(AlaniaDivergentStormCondition.instance), new AlaniaDivergentStormWatcher()); + ).withInterveningIf(AlaniaDivergentStormCondition.instance); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability, new AlaniaDivergentStormWatcher()); } private AlaniaDivergentStorm(final AlaniaDivergentStorm card) { @@ -58,12 +61,10 @@ public final class AlaniaDivergentStorm extends CardImpl { } } -// Based on MarathWillOfTheWildRemoveCountersCost class AlaniaDivergentStormCost extends CostImpl { AlaniaDivergentStormCost() { this.text = "have target opponent draw a card"; - this.addTarget(new TargetOpponent()); } private AlaniaDivergentStormCost(AlaniaDivergentStormCost cost) { @@ -73,32 +74,18 @@ class AlaniaDivergentStormCost extends CostImpl { @Override public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) { Player player = game.getPlayer(controllerId); - if (player == null) { - return false; - } - for (UUID opponentID : game.getOpponents(controllerId)) { - Player opponent = game.getPlayer(opponentID); - if (opponent == null) { - continue; - } - if (opponent.canBeTargetedBy(source.getSourceObject(game), controllerId, source, game)) { - return true; - } - } - return false; + Player opponent = game.getPlayer(source.getFirstTarget()); + return player != null && opponent != null; } @Override public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) { - this.getTargets().clearChosen(); paid = false; - if (this.getTargets().choose(Outcome.DrawCard, controllerId, source.getSourceId(), source, game)) { - Player opponent = game.getPlayer(this.getTargets().getFirstTarget()); - if (opponent == null || !opponent.canRespond()) { - return false; - } - paid = opponent.drawCards(1, source, game) > 0; + Player opponent = game.getPlayer(source.getFirstTarget()); + if (opponent == null || !opponent.canRespond()) { + return false; } + paid = opponent.drawCards(1, source, game) > 0; return paid; } diff --git a/Mage.Sets/src/mage/cards/a/Alarum.java b/Mage.Sets/src/mage/cards/a/Alarum.java index 5c00fd4bc74..42489867e0f 100644 --- a/Mage.Sets/src/mage/cards/a/Alarum.java +++ b/Mage.Sets/src/mage/cards/a/Alarum.java @@ -12,6 +12,7 @@ import mage.constants.Duration; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.AttackingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -34,7 +35,7 @@ public final class Alarum extends CardImpl { Effect effect = new BoostTargetEffect(1, 3, Duration.EndOfTurn); effect.setText("It gets +1/+3 until end of turn"); this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private Alarum(final Alarum card) { diff --git a/Mage.Sets/src/mage/cards/a/AlchemistsTalent.java b/Mage.Sets/src/mage/cards/a/AlchemistsTalent.java index 65dfb59a6c2..47f1f7f5c33 100644 --- a/Mage.Sets/src/mage/cards/a/AlchemistsTalent.java +++ b/Mage.Sets/src/mage/cards/a/AlchemistsTalent.java @@ -66,7 +66,7 @@ public final class AlchemistsTalent extends CardImpl { new SpellCastControllerTriggeredAbility( new DamagePlayersEffect(AlchemistsTalentValue.instance, TargetController.OPPONENT) .setText("{this} deals damage equal to that spell's mana value to each opponent"), - StaticFilters.FILTER_SPELL, false, SetTargetPointer.SPELL + StaticFilters.FILTER_SPELL_A, false, SetTargetPointer.SPELL ).withInterveningIf(AlchemistsTalentCondition.instance), 3 ))); } diff --git a/Mage.Sets/src/mage/cards/a/AlibansTower.java b/Mage.Sets/src/mage/cards/a/AlibansTower.java index 5f05ea33259..7eb354c3f1e 100644 --- a/Mage.Sets/src/mage/cards/a/AlibansTower.java +++ b/Mage.Sets/src/mage/cards/a/AlibansTower.java @@ -8,6 +8,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.filter.common.FilterBlockingCreature; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -21,7 +22,7 @@ public final class AlibansTower extends CardImpl { // Target blocking creature gets +3/+1 until end of turn. this.getSpellAbility().addEffect(new BoostTargetEffect(3, 1, Duration.EndOfTurn)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterBlockingCreature())); + this.getSpellAbility().addTarget(new TargetPermanent(new FilterBlockingCreature())); } private AlibansTower(final AlibansTower card) { diff --git a/Mage.Sets/src/mage/cards/a/AlluringSiren.java b/Mage.Sets/src/mage/cards/a/AlluringSiren.java index 14dc35dbfae..389bae04d87 100644 --- a/Mage.Sets/src/mage/cards/a/AlluringSiren.java +++ b/Mage.Sets/src/mage/cards/a/AlluringSiren.java @@ -12,8 +12,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author BetaSteward_at_googlemail.com @@ -29,7 +32,7 @@ public final class AlluringSiren extends CardImpl { // {T}: Target creature an opponent controls attacks you this turn if able. Ability ability = new SimpleActivatedAbility(new AttacksIfAbleTargetEffect(Duration.EndOfTurn, TargetController.YOU), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AlphaBrawl.java b/Mage.Sets/src/mage/cards/a/AlphaBrawl.java index 096cb3bbe81..f22422b10bf 100644 --- a/Mage.Sets/src/mage/cards/a/AlphaBrawl.java +++ b/Mage.Sets/src/mage/cards/a/AlphaBrawl.java @@ -14,8 +14,11 @@ import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author BetaSteward @@ -27,7 +30,7 @@ public final class AlphaBrawl extends CardImpl { // Target creature an opponent controls deals damage equal to its power to each other creature that player controls, then each of those creatures deals damage equal to its power to that creature. this.getSpellAbility().addEffect(new AlphaBrawlEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); } diff --git a/Mage.Sets/src/mage/cards/a/AlphaKavu.java b/Mage.Sets/src/mage/cards/a/AlphaKavu.java index 15dd7d09277..c26d92e0eea 100644 --- a/Mage.Sets/src/mage/cards/a/AlphaKavu.java +++ b/Mage.Sets/src/mage/cards/a/AlphaKavu.java @@ -14,6 +14,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -37,7 +38,7 @@ public final class AlphaKavu extends CardImpl { // {1}{G}: Target Kavu creature gets -1/+1 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(-1, 1, Duration.EndOfTurn), new ManaCostsImpl<>("{1}{G}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AlpharaelDreamingAcolyte.java b/Mage.Sets/src/mage/cards/a/AlpharaelDreamingAcolyte.java new file mode 100644 index 00000000000..e3a4313bdb4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AlpharaelDreamingAcolyte.java @@ -0,0 +1,63 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.MyTurnCondition; +import mage.abilities.costs.common.DiscardCardCost; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.effects.common.discard.DiscardControllerEffect; +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 mage.constants.SuperType; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AlpharaelDreamingAcolyte extends CardImpl { + + public AlpharaelDreamingAcolyte(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{B}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.CLERIC); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // When Alpharael enters, draw two cards. Then discard two cards unless you discard an artifact card. + Ability ability = new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(2)); + ability.addEffect(new DoIfCostPaid( + null, new DiscardControllerEffect(2), + new DiscardCardCost(StaticFilters.FILTER_CARD_ARTIFACT) + .setText("discard an artifact card instead of discarding two cards") + ).setText("Then discard two cards unless you discard an artifact card")); + this.addAbility(ability); + + // During your turn, Alpharael has deathtouch. + this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect( + new GainAbilitySourceEffect(DeathtouchAbility.getInstance(), Duration.WhileOnBattlefield), + MyTurnCondition.instance, "during your turn, {this} has deathtouch" + ))); + } + + private AlpharaelDreamingAcolyte(final AlpharaelDreamingAcolyte card) { + super(card); + } + + @Override + public AlpharaelDreamingAcolyte copy() { + return new AlpharaelDreamingAcolyte(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AltarGolem.java b/Mage.Sets/src/mage/cards/a/AltarGolem.java index 31b8571ab1a..403b8c6e9c1 100644 --- a/Mage.Sets/src/mage/cards/a/AltarGolem.java +++ b/Mage.Sets/src/mage/cards/a/AltarGolem.java @@ -1,7 +1,6 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; @@ -17,24 +16,17 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; + +import java.util.UUID; /** - * * @author jeffwadsworth - * */ public final class AltarGolem extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); - - static { - filter.add(TappedPredicate.UNTAPPED); - } - public AltarGolem(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{7}"); this.subtype.add(SubType.GOLEM); @@ -53,7 +45,7 @@ public final class AltarGolem extends CardImpl { this.addAbility(new SimpleStaticAbility(new DontUntapInControllersUntapStepSourceEffect())); // Tap five untapped creatures you control: Untap Altar Golem. - this.addAbility(new SimpleActivatedAbility(new UntapSourceEffect(), new TapTargetCost(new TargetControlledCreaturePermanent(5, 5, filter, true)))); + this.addAbility(new SimpleActivatedAbility(new UntapSourceEffect(), new TapTargetCost(new TargetControlledPermanent(5, StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURES)))); } diff --git a/Mage.Sets/src/mage/cards/a/AmbitiousFarmhand.java b/Mage.Sets/src/mage/cards/a/AmbitiousFarmhand.java index 63256a34839..cf911245785 100644 --- a/Mage.Sets/src/mage/cards/a/AmbitiousFarmhand.java +++ b/Mage.Sets/src/mage/cards/a/AmbitiousFarmhand.java @@ -11,7 +11,10 @@ import mage.abilities.hint.common.CovenHint; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.AbilityWord; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.filter.FilterCard; import mage.target.common.TargetCardInLibrary; @@ -46,8 +49,7 @@ public final class AmbitiousFarmhand extends CardImpl { // Coven—{1}{W}{W}: Transform Ambitious Farmhand. Activate only if you control three or more creatures with different powers. this.addAbility(new TransformAbility()); this.addAbility(new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new TransformSourceEffect(), - new ManaCostsImpl<>("{1}{W}{W}"), CovenCondition.instance + new TransformSourceEffect(), new ManaCostsImpl<>("{1}{W}{W}"), CovenCondition.instance ).setAbilityWord(AbilityWord.COVEN).addHint(CovenHint.instance)); } diff --git a/Mage.Sets/src/mage/cards/a/AminatouTheFateshifter.java b/Mage.Sets/src/mage/cards/a/AminatouTheFateshifter.java index ae9c55446d9..041b6e123a2 100644 --- a/Mage.Sets/src/mage/cards/a/AminatouTheFateshifter.java +++ b/Mage.Sets/src/mage/cards/a/AminatouTheFateshifter.java @@ -118,8 +118,8 @@ class AminatouUltimateEffect extends OneShotEffect { AminatouUltimateEffect() { super(Outcome.Benefit); - staticText = "Choose left or right. Each player gains control of all nonland permanents other than Aminatou," - + " the Fateshifter controlled by the next player in the chosen direction."; + staticText = "Choose left or right. Each player gains control of all nonland permanents other than {this}" + + " controlled by the next player in the chosen direction."; } private AminatouUltimateEffect(final AminatouUltimateEffect effect) { diff --git a/Mage.Sets/src/mage/cards/a/AmyRose.java b/Mage.Sets/src/mage/cards/a/AmyRose.java new file mode 100644 index 00000000000..ddc0fb6fa88 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AmyRose.java @@ -0,0 +1,94 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.dynamicvalue.common.SourcePermanentPowerValue; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.keyword.HasteAbility; +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.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.common.FilterAttackingCreature; +import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; +import mage.target.targetpointer.SecondTargetPointer; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class AmyRose extends CardImpl { + + private static final FilterPermanent filter = new FilterAttackingCreature("other attacking creature"); + + static { + filter.add(AnotherPredicate.instance); + } + + public AmyRose(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{W}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HEDGEHOG); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // Whenever Amy Rose attacks, attach up to one target Equipment to her. Then up to one other target attacking creature gets +X/+0 until end of turn, where X is Amy Rose's power. + Ability ability = new AttacksTriggeredAbility(new AmyRoseEffect()); + ability.addEffect(new BoostTargetEffect( + SourcePermanentPowerValue.NOT_NEGATIVE, StaticValue.get(0) + ).setTargetPointer(new SecondTargetPointer()) + .setText("Then up to one other target attacking creature gets +X/+0 until end of turn, where X is {this}'s power")); + ability.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_PERMANENT_EQUIPMENT)); + ability.addTarget(new TargetPermanent(0, 1, filter)); + this.addAbility(ability); + } + + private AmyRose(final AmyRose card) { + super(card); + } + + @Override + public AmyRose copy() { + return new AmyRose(this); + } +} + +class AmyRoseEffect extends OneShotEffect { + + AmyRoseEffect() { + super(Outcome.Benefit); + staticText = "attach up to one target Equipment to her"; + } + + private AmyRoseEffect(final AmyRoseEffect effect) { + super(effect); + } + + @Override + public AmyRoseEffect copy() { + return new AmyRoseEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = source.getSourcePermanentIfItStillExists(game); + Permanent equipment = game.getPermanent(getTargetPointer().getFirst(game, source)); + return permanent != null && equipment != null && permanent.addAttachment(equipment.getId(), source, game); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AnaBattlemage.java b/Mage.Sets/src/mage/cards/a/AnaBattlemage.java index f33df1df178..1def7d10026 100644 --- a/Mage.Sets/src/mage/cards/a/AnaBattlemage.java +++ b/Mage.Sets/src/mage/cards/a/AnaBattlemage.java @@ -19,6 +19,7 @@ import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.TargetPlayer; import mage.target.common.TargetCreaturePermanent; @@ -58,7 +59,7 @@ public final class AnaBattlemage extends CardImpl { // 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. ability = new EntersBattlefieldTriggeredAbility(new TapTargetEffect()).withInterveningIf(condition2); ability.addEffect(new AnaBattlemageEffect()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } @@ -76,7 +77,7 @@ class AnaBattlemageEffect extends OneShotEffect { AnaBattlemageEffect() { super(Outcome.Detriment); - this.staticText = "and it deals damage equal to its power to its controller"; + this.staticText = "and that creature deals damage equal to its power to its controller"; } private AnaBattlemageEffect(final AnaBattlemageEffect effect) { diff --git a/Mage.Sets/src/mage/cards/a/AnaSanctuary.java b/Mage.Sets/src/mage/cards/a/AnaSanctuary.java index 0b18e54890b..0c6a8f9ae49 100644 --- a/Mage.Sets/src/mage/cards/a/AnaSanctuary.java +++ b/Mage.Sets/src/mage/cards/a/AnaSanctuary.java @@ -1,24 +1,18 @@ - package mage.cards.a; -import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.common.SanctuaryInterveningIfTriggeredAbility; -import mage.abilities.effects.ContinuousEffect; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.common.SanctuaryTriggeredAbility; +import mage.abilities.effects.common.AddContinuousEffectToGame; 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.target.common.TargetCreaturePermanent; -import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class AnaSanctuary extends CardImpl { @@ -27,10 +21,11 @@ public final class AnaSanctuary extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); // At the beginning of your upkeep, if you control a blue or black permanent, target creature gets +1/+1 until end of turn. If you control a blue permanent and a black permanent, that creature gets +5/+5 until end of turn instead. - Ability ability = new SanctuaryInterveningIfTriggeredAbility( - new BoostEffect(1), new BoostEffect(5), ObjectColor.BLACK, ObjectColor.BLUE, - "At the beginning of your upkeep, if you control a blue or black permanent, " - + "target creature gets +1/+1 until end of turn. If you control a blue permanent and a black permanent, that creature gets +5/+5 until end of turn instead." + Ability ability = new SanctuaryTriggeredAbility( + new AddContinuousEffectToGame(new BoostTargetEffect(1, 1)), + new AddContinuousEffectToGame(new BoostTargetEffect(5, 5)), + ObjectColor.BLACK, ObjectColor.BLUE, "target creature gets +1/+1 until end of turn. " + + "If you control a blue permanent and a black permanent, that creature gets +5/+5 until end of turn instead." ); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); @@ -45,31 +40,3 @@ public final class AnaSanctuary extends CardImpl { return new AnaSanctuary(this); } } - -class BoostEffect extends OneShotEffect { - - private final int amount; - - BoostEffect(int amount) { - super(Outcome.Benefit); - this.amount = amount; - } - - private BoostEffect(final BoostEffect effect) { - super(effect); - this.amount = effect.amount; - } - - @Override - public BoostEffect copy() { - return new BoostEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - ContinuousEffect effect = new BoostTargetEffect(amount, amount, Duration.EndOfTurn); - effect.setTargetPointer(new FixedTarget(source.getFirstTarget(), game)); - game.addEffect(effect, source); - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/a/AnabaAncestor.java b/Mage.Sets/src/mage/cards/a/AnabaAncestor.java index 3510bc6d5c9..0604bd824fb 100644 --- a/Mage.Sets/src/mage/cards/a/AnabaAncestor.java +++ b/Mage.Sets/src/mage/cards/a/AnabaAncestor.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -39,7 +40,7 @@ public final class AnabaAncestor extends CardImpl { // {T}: Another target Minotaur creature gets +1/+1 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(1, 1, Duration.EndOfTurn), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AnafenzaTheForemost.java b/Mage.Sets/src/mage/cards/a/AnafenzaTheForemost.java index 0dc09db1b19..6c90ec2fa41 100644 --- a/Mage.Sets/src/mage/cards/a/AnafenzaTheForemost.java +++ b/Mage.Sets/src/mage/cards/a/AnafenzaTheForemost.java @@ -21,7 +21,7 @@ import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; import mage.game.permanent.PermanentToken; import mage.players.Player; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -48,7 +48,7 @@ public final class AnafenzaTheForemost extends CardImpl { // Whenever Anafenza, the Foremost attacks, put a +1/+1 counter on another target tapped creature you control. Ability ability = new AttacksTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), false); - ability.addTarget(new TargetControlledCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // If a nontoken creature an opponent owns would die or a creature card not on the battlefield would be put into an opponent's graveyard, exile that card instead. diff --git a/Mage.Sets/src/mage/cards/a/Anavolver.java b/Mage.Sets/src/mage/cards/a/Anavolver.java index bfbae67c81e..a3b08559f11 100644 --- a/Mage.Sets/src/mage/cards/a/Anavolver.java +++ b/Mage.Sets/src/mage/cards/a/Anavolver.java @@ -2,7 +2,6 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; @@ -19,9 +18,10 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; import mage.counters.CounterType; +import java.util.UUID; + /** * @author Loki */ @@ -49,9 +49,9 @@ public final class Anavolver extends CardImpl { // If Anavolver was kicked with its {B} kicker, it enters with a +1/+1 counter on it and with "Pay 3 life: Regenerate Anavolver." EntersBattlefieldAbility ability2 = new EntersBattlefieldAbility( - new AddCountersSourceEffect(CounterType.P1P1.createInstance(1),false), new KickedCostCondition("{B}"), - "If {this} was kicked with its {B} kicker, it enters with a +1/+1 counter on it and with \"Pay 3 life: Regenerate Anavolver.\"", - "{this} enters with a +1/+1 counter on it and with \"Pay 3 life: Regenerate Anavolver.\""); + new AddCountersSourceEffect(CounterType.P1P1.createInstance(1), false), new KickedCostCondition("{B}"), + "If {this} was kicked with its {B} kicker, it enters with a +1/+1 counter on it and with \"Pay 3 life: Regenerate {this}.\"", + "{this} enters with a +1/+1 counter on it and with \"Pay 3 life: Regenerate {this}.\""); ((EntersBattlefieldEffect)ability2.getEffects().get(0)).addEffect(new GainAbilitySourceEffect(new SimpleActivatedAbility(new RegenerateSourceEffect(), new PayLifeCost(3)), Duration.WhileOnBattlefield)); this.addAbility(ability2); } diff --git a/Mage.Sets/src/mage/cards/a/AncientHellkite.java b/Mage.Sets/src/mage/cards/a/AncientHellkite.java index e6fa96d7495..f8c7be121be 100644 --- a/Mage.Sets/src/mage/cards/a/AncientHellkite.java +++ b/Mage.Sets/src/mage/cards/a/AncientHellkite.java @@ -1,18 +1,16 @@ - package mage.cards.a; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.condition.common.SourceAttackingCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DamageTargetEffect; 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.predicate.permanent.DefendingPlayerControlsSourceAttackingPredicate; import mage.target.TargetPermanent; @@ -42,7 +40,9 @@ public final class AncientHellkite extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // {R}: Ancient Hellkite deals 1 damage to target creature defending player controls. Activate this ability only if Ancient Hellkite is attacking. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new ManaCostsImpl<>("{R}"), SourceAttackingCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new DamageTargetEffect(1), new ManaCostsImpl<>("{R}"), SourceAttackingCondition.instance + ); ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AngelOfCondemnation.java b/Mage.Sets/src/mage/cards/a/AngelOfCondemnation.java index acfc126d0b0..91f9e12bf74 100644 --- a/Mage.Sets/src/mage/cards/a/AngelOfCondemnation.java +++ b/Mage.Sets/src/mage/cards/a/AngelOfCondemnation.java @@ -15,10 +15,13 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * @author emerald000 */ @@ -42,14 +45,14 @@ public final class AngelOfCondemnation extends CardImpl { new ExileReturnBattlefieldNextEndStepTargetEffect(), new ManaCostsImpl<>("{2}{W}") ); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); // {2}{W}, {T}, Exert Angel of Condemnation: Exile another target creature until Angel of Condemnation leaves the battlefield. ability = new SimpleActivatedAbility(new ExileUntilSourceLeavesEffect(), new ManaCostsImpl<>("{2}{W}")); ability.addCost(new TapSourceCost()); ability.addCost(new ExertSourceCost()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AngelicPage.java b/Mage.Sets/src/mage/cards/a/AngelicPage.java index c7a1124a229..4fc2c89dbc9 100644 --- a/Mage.Sets/src/mage/cards/a/AngelicPage.java +++ b/Mage.Sets/src/mage/cards/a/AngelicPage.java @@ -15,6 +15,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterAttackingOrBlockingCreature; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -35,7 +36,7 @@ public final class AngelicPage extends CardImpl { //{T}: Target attacking or blocking creature gets +1/+1 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(1, 1, Duration.EndOfTurn), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(new FilterAttackingOrBlockingCreature())); + ability.addTarget(new TargetPermanent(new FilterAttackingOrBlockingCreature())); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AngelsTrumpet.java b/Mage.Sets/src/mage/cards/a/AngelsTrumpet.java index 082613a8c32..225e4ca3a92 100644 --- a/Mage.Sets/src/mage/cards/a/AngelsTrumpet.java +++ b/Mage.Sets/src/mage/cards/a/AngelsTrumpet.java @@ -2,14 +2,17 @@ package mage.cards.a; import mage.MageObjectReference; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.abilities.keyword.VigilanceAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; 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.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; @@ -47,7 +50,7 @@ class AngelsTrumpetTapEffect extends OneShotEffect { AngelsTrumpetTapEffect() { super(Outcome.Tap); - this.staticText = "tap all untapped creatures that player controls that didn't attack this turn. Angel's Trumpet deals damage to the player equal to the number of creatures tapped this way"; + this.staticText = "tap all untapped creatures that player controls that didn't attack this turn. {this} deals damage to the player equal to the number of creatures tapped this way"; } private AngelsTrumpetTapEffect(final AngelsTrumpetTapEffect effect) { diff --git a/Mage.Sets/src/mage/cards/a/AngusMackenzie.java b/Mage.Sets/src/mage/cards/a/AngusMackenzie.java index 1657c3914e2..8245670a062 100644 --- a/Mage.Sets/src/mage/cards/a/AngusMackenzie.java +++ b/Mage.Sets/src/mage/cards/a/AngusMackenzie.java @@ -1,28 +1,26 @@ - package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.PreventAllDamageByAllPermanentsEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.game.Game; +import java.util.UUID; + /** - * * @author shieldal */ public final class AngusMackenzie extends CardImpl { public AngusMackenzie(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}{W}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{W}{U}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.CLERIC); @@ -30,14 +28,11 @@ public final class AngusMackenzie extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - Effect effect = new PreventAllDamageByAllPermanentsEffect(Duration.EndOfTurn, true); - effect.setText("Prevent all combat damage that would be dealt this turn"); // {G}{W}{U}, {tap}: Prevent all combat damage that would be dealt this turn. Activate this ability only before the combat damage step. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, - effect, - new ManaCostsImpl<>("{G}{W}{U}"), - BeforeCombatDamageCondition.getInstance() + new PreventAllDamageByAllPermanentsEffect(Duration.EndOfTurn, true) + .setText("Prevent all combat damage that would be dealt this turn"), + new ManaCostsImpl<>("{G}{W}{U}"), BeforeCombatDamageCondition.getInstance() ); ability.addCost(new TapSourceCost()); this.addAbility(ability); @@ -62,15 +57,15 @@ class BeforeCombatDamageCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - PhaseStep phaseStep = game.getTurnStepType(); - if(phaseStep.getIndex() < PhaseStep.FIRST_COMBAT_DAMAGE.getIndex()) { - return true; - } + PhaseStep phaseStep = game.getTurnStepType(); + if (phaseStep.getIndex() < PhaseStep.FIRST_COMBAT_DAMAGE.getIndex()) { + return true; + } return false; } @Override public String toString() { - return "before the combat damage step"; + return "before the combat damage step"; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/a/AnimateWall.java b/Mage.Sets/src/mage/cards/a/AnimateWall.java index 7b852039321..a9ee511d475 100644 --- a/Mage.Sets/src/mage/cards/a/AnimateWall.java +++ b/Mage.Sets/src/mage/cards/a/AnimateWall.java @@ -34,7 +34,7 @@ public final class AnimateWall extends CardImpl { // Enchant Wall - TargetPermanent auraTarget = new TargetCreaturePermanent(filter); + TargetPermanent auraTarget = new TargetPermanent(filter); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); Ability ability = new EnchantAbility(auraTarget); diff --git a/Mage.Sets/src/mage/cards/a/Annihilate.java b/Mage.Sets/src/mage/cards/a/Annihilate.java index 20a4d080bb5..e12a50d9ffe 100644 --- a/Mage.Sets/src/mage/cards/a/Annihilate.java +++ b/Mage.Sets/src/mage/cards/a/Annihilate.java @@ -7,8 +7,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author LevelX2 @@ -20,7 +23,7 @@ public final class Annihilate extends CardImpl { // Destroy target nonblack creature. It can't be regenerated. this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("
")); } diff --git a/Mage.Sets/src/mage/cards/a/AnointedDeacon.java b/Mage.Sets/src/mage/cards/a/AnointedDeacon.java index 139850bd6ad..cc5f6f5b894 100644 --- a/Mage.Sets/src/mage/cards/a/AnointedDeacon.java +++ b/Mage.Sets/src/mage/cards/a/AnointedDeacon.java @@ -10,6 +10,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -36,7 +37,7 @@ public final class AnointedDeacon extends CardImpl { // At the beginning of combat on your turn, you may have target Vampire get +2/+0 until end of turn. Ability ability = new BeginningOfCombatTriggeredAbility( new BoostTargetEffect(2, 0, Duration.EndOfTurn), true); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AnotherRound.java b/Mage.Sets/src/mage/cards/a/AnotherRound.java index 8353ebb028f..4ede5800889 100644 --- a/Mage.Sets/src/mage/cards/a/AnotherRound.java +++ b/Mage.Sets/src/mage/cards/a/AnotherRound.java @@ -9,9 +9,9 @@ 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.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.targetpointer.FixedTargets; @@ -61,12 +61,8 @@ class AnotherRoundEffect extends OneShotEffect { } int xValue = GetXValue.instance.calculate(game, source, this); - TargetControlledCreaturePermanent target = - new TargetControlledCreaturePermanent( - 0, Integer.MAX_VALUE, - StaticFilters.FILTER_CONTROLLED_CREATURE, true - ); - + TargetPermanent target = new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE); + target.withNotTarget(true); for (int i = 0; i <= xValue; ++i) { target.clearChosen(); controller.chooseTarget(Outcome.Benefit, target, source, game); diff --git a/Mage.Sets/src/mage/cards/a/AntlerSkulkin.java b/Mage.Sets/src/mage/cards/a/AntlerSkulkin.java index 924656efdb4..0970db0a0c5 100644 --- a/Mage.Sets/src/mage/cards/a/AntlerSkulkin.java +++ b/Mage.Sets/src/mage/cards/a/AntlerSkulkin.java @@ -17,6 +17,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -41,7 +42,7 @@ public final class AntlerSkulkin extends CardImpl { // {2}: Target white creature gains persist until end of turn. Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(new PersistAbility(), Duration.EndOfTurn), new ManaCostsImpl<>("{2}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/ApprenticeSorcerer.java b/Mage.Sets/src/mage/cards/a/ApprenticeSorcerer.java index 8576032e6e7..355e39e2a0c 100644 --- a/Mage.Sets/src/mage/cards/a/ApprenticeSorcerer.java +++ b/Mage.Sets/src/mage/cards/a/ApprenticeSorcerer.java @@ -1,7 +1,5 @@ - package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; @@ -12,25 +10,27 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** - * * @author fireshoes */ public final class ApprenticeSorcerer extends CardImpl { public ApprenticeSorcerer(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.subtype.add(SubType.WIZARD); this.power = new MageInt(1); this.toughness = new MageInt(1); // {tap}: Apprentice Sorcerer deals 1 damage to any target. Activate this ability only during your turn, before attackers are declared. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new DamageTargetEffect(1), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new DamageTargetEffect(1), new TapSourceCost(), + MyTurnBeforeAttackersDeclaredCondition.instance + ); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/ApproachOfTheSecondSun.java b/Mage.Sets/src/mage/cards/a/ApproachOfTheSecondSun.java index 1d8e5653f06..70aa146da9c 100644 --- a/Mage.Sets/src/mage/cards/a/ApproachOfTheSecondSun.java +++ b/Mage.Sets/src/mage/cards/a/ApproachOfTheSecondSun.java @@ -48,7 +48,7 @@ class ApproachOfTheSecondSunEffect extends OneShotEffect { ApproachOfTheSecondSunEffect() { super(Outcome.Win); this.staticText - = "If this spell was cast from your hand and you've cast another spell named {this} this game, you win the game. " + = "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 {this} into its owner's library seventh from the top and you gain 7 life."; } diff --git a/Mage.Sets/src/mage/cards/a/AquastrandSpider.java b/Mage.Sets/src/mage/cards/a/AquastrandSpider.java index c7baca16d32..061d37ceb52 100644 --- a/Mage.Sets/src/mage/cards/a/AquastrandSpider.java +++ b/Mage.Sets/src/mage/cards/a/AquastrandSpider.java @@ -16,8 +16,11 @@ import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_CREATURE_P1P1; + /** * * @author JotaPeRL @@ -38,7 +41,7 @@ public final class AquastrandSpider extends CardImpl { Ability ability = new SimpleActivatedAbility( new GainAbilityTargetEffect(ReachAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{G}")); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_P1P1)); + ability.addTarget(new TargetPermanent(FILTER_CREATURE_P1P1)); this.addAbility(ability.addCustomOutcome(Outcome.Benefit)); } diff --git a/Mage.Sets/src/mage/cards/a/ArahboRoarOfTheWorld.java b/Mage.Sets/src/mage/cards/a/ArahboRoarOfTheWorld.java index 34f18a49990..257d810031d 100644 --- a/Mage.Sets/src/mage/cards/a/ArahboRoarOfTheWorld.java +++ b/Mage.Sets/src/mage/cards/a/ArahboRoarOfTheWorld.java @@ -20,6 +20,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; @@ -56,7 +57,7 @@ public final class ArahboRoarOfTheWorld extends CardImpl { TargetController.YOU, new BoostTargetEffect(3, 3, Duration.EndOfTurn), false).withInterveningIf( SourceOnBattlefieldOrCommandZoneCondition.instance); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); ability.setAbilityWord(AbilityWord.EMINENCE); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/a/ArashinForemost.java b/Mage.Sets/src/mage/cards/a/ArashinForemost.java index 943af6b4556..64e6a20e7a0 100644 --- a/Mage.Sets/src/mage/cards/a/ArashinForemost.java +++ b/Mage.Sets/src/mage/cards/a/ArashinForemost.java @@ -1,7 +1,6 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility; @@ -14,10 +13,11 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author fireshoes */ public final class ArashinForemost extends CardImpl { @@ -41,7 +41,7 @@ public final class ArashinForemost extends CardImpl { // Whenever Arashin Foremost enters the battlefield or attacks, another target Warrior creature you control gains double strike until end of turn. Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility(new GainAbilityTargetEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn)); - ability.addTarget(new TargetControlledCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/ArborColossus.java b/Mage.Sets/src/mage/cards/a/ArborColossus.java index 81ebd250b90..82edb9fc531 100644 --- a/Mage.Sets/src/mage/cards/a/ArborColossus.java +++ b/Mage.Sets/src/mage/cards/a/ArborColossus.java @@ -17,6 +17,7 @@ import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -44,7 +45,7 @@ public final class ArborColossus extends CardImpl { this.addAbility(new MonstrosityAbility("{3}{G}{G}{G}", 3)); // When Arbor Colossus becomes monstrous, destroy target creature with flying an opponent controls. Ability ability = new BecomesMonstrousSourceTriggeredAbility(new DestroyTargetEffect()); - Target target = new TargetCreaturePermanent(filter); + Target target = new TargetPermanent(filter); ability.addTarget(target); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/ArcRunner.java b/Mage.Sets/src/mage/cards/a/ArcRunner.java index d78e7e5f3bc..a71884c9b00 100644 --- a/Mage.Sets/src/mage/cards/a/ArcRunner.java +++ b/Mage.Sets/src/mage/cards/a/ArcRunner.java @@ -1,26 +1,24 @@ - - package mage.cards.a; -import java.util.UUID; import mage.MageInt; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.keyword.HasteAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.game.events.GameEvent.EventType; +import mage.constants.TargetController; + +import java.util.UUID; /** - * * @author BetaSteward_at_googlemail.com */ public final class ArcRunner extends CardImpl { public ArcRunner(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); this.subtype.add(SubType.ELEMENTAL); this.subtype.add(SubType.OX); @@ -28,7 +26,10 @@ public final class ArcRunner extends CardImpl { this.toughness = new MageInt(1); this.addAbility(HasteAbility.getInstance()); - this.addAbility(new OnEventTriggeredAbility(EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new SacrificeSourceEffect())); + + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.NEXT, new SacrificeSourceEffect(), false + )); } private ArcRunner(final ArcRunner card) { diff --git a/Mage.Sets/src/mage/cards/a/ArcadesTheStrategist.java b/Mage.Sets/src/mage/cards/a/ArcadesTheStrategist.java index 511f2d74e1d..40235c7d597 100644 --- a/Mage.Sets/src/mage/cards/a/ArcadesTheStrategist.java +++ b/Mage.Sets/src/mage/cards/a/ArcadesTheStrategist.java @@ -2,7 +2,7 @@ package mage.cards.a; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.combat.CanAttackAsThoughItDidntHaveDefenderAllEffect; @@ -12,7 +12,11 @@ import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.VigilanceAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; @@ -24,7 +28,7 @@ import java.util.UUID; */ public final class ArcadesTheStrategist extends CardImpl { - private static final FilterControlledCreaturePermanent defenderSingle = new FilterControlledCreaturePermanent("a creature with defender"); + private static final FilterPermanent defenderSingle = new FilterControlledCreaturePermanent("a creature you control with defender"); private static final FilterCreaturePermanent defenderPlural = new FilterCreaturePermanent("creature you control with defender"); static { @@ -48,7 +52,7 @@ public final class ArcadesTheStrategist extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // Whenever a creature with defender you control enters, draw a card. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + this.addAbility(new EntersBattlefieldAllTriggeredAbility( new DrawCardSourceControllerEffect(1), defenderSingle )); diff --git a/Mage.Sets/src/mage/cards/a/ArcboundOverseer.java b/Mage.Sets/src/mage/cards/a/ArcboundOverseer.java index 2fd4ffb9a12..408d815fc1f 100644 --- a/Mage.Sets/src/mage/cards/a/ArcboundOverseer.java +++ b/Mage.Sets/src/mage/cards/a/ArcboundOverseer.java @@ -1,27 +1,26 @@ - package mage.cards.a; -import java.util.UUID; import mage.MageInt; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersAllEffect; import mage.abilities.keyword.ModularAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.mageobject.AbilityPredicate; -import mage.game.events.GameEvent; + +import java.util.UUID; /** - * * @author jonubuu */ public final class ArcboundOverseer extends CardImpl { - private static final FilterControlledCreaturePermanent filter; + private static final FilterPermanent filter; static { filter = new FilterControlledCreaturePermanent("creature you control with modular"); @@ -29,16 +28,16 @@ public final class ArcboundOverseer extends CardImpl { } public ArcboundOverseer(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{8}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{8}"); this.subtype.add(SubType.GOLEM); this.power = new MageInt(0); this.toughness = new MageInt(0); // At the beginning of your upkeep, put a +1/+1 counter on each creature with modular you control. - this.addAbility(new OnEventTriggeredAbility( - GameEvent.EventType.UPKEEP_STEP_PRE, - "beginning of your upkeep", - new AddCountersAllEffect(CounterType.P1P1.createInstance(), filter))); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new AddCountersAllEffect(CounterType.P1P1.createInstance(), filter) + )); + // Modular 6 this.addAbility(new ModularAbility(this, 6)); } diff --git a/Mage.Sets/src/mage/cards/a/ArchOfOrazca.java b/Mage.Sets/src/mage/cards/a/ArchOfOrazca.java index 4adb04546f0..b4c32e6729b 100644 --- a/Mage.Sets/src/mage/cards/a/ArchOfOrazca.java +++ b/Mage.Sets/src/mage/cards/a/ArchOfOrazca.java @@ -4,7 +4,7 @@ import mage.abilities.Ability; import mage.abilities.condition.common.CitysBlessingCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.hint.common.CitysBlessingHint; import mage.abilities.keyword.AscendAbility; @@ -12,7 +12,6 @@ import mage.abilities.mana.ColorlessManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; import java.util.UUID; @@ -31,10 +30,9 @@ public final class ArchOfOrazca extends CardImpl { this.addAbility(new ColorlessManaAbility()); // {5}, {T}: Draw a card. Activate this ability only if you have the city's blessing. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, - new DrawCardSourceControllerEffect(1), - new GenericManaCost(5), - CitysBlessingCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new DrawCardSourceControllerEffect(1), new GenericManaCost(5), CitysBlessingCondition.instance + ); ability.addCost(new TapSourceCost()); ability.addHint(CitysBlessingHint.instance); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/a/ArchdemonOfGreed.java b/Mage.Sets/src/mage/cards/a/ArchdemonOfGreed.java index cf60947b69f..b4c8c7a0518 100644 --- a/Mage.Sets/src/mage/cards/a/ArchdemonOfGreed.java +++ b/Mage.Sets/src/mage/cards/a/ArchdemonOfGreed.java @@ -2,10 +2,10 @@ package mage.cards.a; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -13,7 +13,6 @@ import mage.constants.Outcome; import mage.constants.SubType; import mage.filter.common.FilterControlledPermanent; import mage.game.Game; -import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetSacrifice; @@ -43,8 +42,9 @@ public final class ArchdemonOfGreed extends CardImpl { this.addAbility(FlyingAbility.getInstance()); this.addAbility(TrampleAbility.getInstance()); + // At the beginning of your upkeep, sacrifice a Human. If you can't, tap Archdemon of Greed and it deals 9 damage to you. - this.addAbility(new OnEventTriggeredAbility(GameEvent.EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", new ArchdemonOfGreedEffect(), false)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new ArchdemonOfGreedEffect())); } private ArchdemonOfGreed(final ArchdemonOfGreed card) { @@ -60,7 +60,7 @@ public final class ArchdemonOfGreed extends CardImpl { public ArchdemonOfGreedEffect() { super(Outcome.Damage); - this.staticText = "Sacrifice a Human. If you can't, tap {this} and it deals 9 damage to you."; + this.staticText = "sacrifice a Human. If you can't, tap {this} and it deals 9 damage to you."; } private ArchdemonOfGreedEffect(final ArchdemonOfGreedEffect effect) { diff --git a/Mage.Sets/src/mage/cards/a/ArchdemonOfPaliano.java b/Mage.Sets/src/mage/cards/a/ArchdemonOfPaliano.java index b0d10693a7e..36b1783e9a6 100644 --- a/Mage.Sets/src/mage/cards/a/ArchdemonOfPaliano.java +++ b/Mage.Sets/src/mage/cards/a/ArchdemonOfPaliano.java @@ -1,14 +1,14 @@ package mage.cards.a; import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.InfoEffect; 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.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.common.InfoEffect; import java.util.UUID; @@ -27,12 +27,12 @@ public final class ArchdemonOfPaliano extends CardImpl { // TODO: Draft specific abilities not implemented // Draft Archdemon of Paliano face up. - this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Draft Archdemon of Paliano face up - not implemented."))); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Draft {this} face up - not implemented."))); // As long as Archdemon of Paliano is face up during the draft, you can’t look at booster packs and must draft cards at random. After you draft three cards this way, turn Archdemon of Paliano face down. - this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("As long as Archdemon of Paliano is face up during the draft, " + this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("As long as {this} is face up during the draft, " + "you can't look at booster packs and must draft cards at random. " - + "After you draft three cards this way, turn Archdemon of Paliano face down. - not implemented."))); + + "After you draft three cards this way, turn {this} face down. - not implemented."))); // Flying this.addAbility(FlyingAbility.getInstance()); diff --git a/Mage.Sets/src/mage/cards/a/ArchdruidsCharm.java b/Mage.Sets/src/mage/cards/a/ArchdruidsCharm.java index 7f9b0caa593..5dd587a2e5e 100644 --- a/Mage.Sets/src/mage/cards/a/ArchdruidsCharm.java +++ b/Mage.Sets/src/mage/cards/a/ArchdruidsCharm.java @@ -25,6 +25,8 @@ import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import mage.util.CardUtil; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * * @author jimga150 @@ -50,7 +52,7 @@ public final class ArchdruidsCharm extends CardImpl { Mode mode2 = new Mode(new AddCountersTargetEffect(CounterType.P1P1.createInstance())); mode2.addTarget(new TargetControlledCreaturePermanent()); mode2.addEffect(new DamageWithPowerFromOneToAnotherTargetEffect("it")); - mode2.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + mode2.addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.getSpellAbility().addMode(mode2); // * Exile target artifact or enchantment. diff --git a/Mage.Sets/src/mage/cards/a/ArchelosLagoonMystic.java b/Mage.Sets/src/mage/cards/a/ArchelosLagoonMystic.java index c7c8872e7fe..e8518bf64d4 100644 --- a/Mage.Sets/src/mage/cards/a/ArchelosLagoonMystic.java +++ b/Mage.Sets/src/mage/cards/a/ArchelosLagoonMystic.java @@ -53,7 +53,7 @@ class ArchelosLagoonMysticEffect extends ReplacementEffectImpl { super(Duration.WhileOnBattlefield, Outcome.Benefit); this.tapped = tapped; staticText = "as long as {this} is " - + (tapped ? "" : "un") + "tapped, other permanents enter the battlefield " + + (tapped ? "" : "un") + "tapped, other permanents enter " + (tapped ? "" : "un") + "tapped"; } diff --git a/Mage.Sets/src/mage/cards/a/ArchmageAscension.java b/Mage.Sets/src/mage/cards/a/ArchmageAscension.java index 2ae3ec86cfd..3437c7391de 100644 --- a/Mage.Sets/src/mage/cards/a/ArchmageAscension.java +++ b/Mage.Sets/src/mage/cards/a/ArchmageAscension.java @@ -30,7 +30,7 @@ public final class ArchmageAscension extends CardImpl { // At the beginning of each end step, if you drew two or more cards this turn, you may put a quest counter on Archmage Ascension. this.addAbility(new BeginningOfEndStepTriggeredAbility( - TargetController.EACH_PLAYER, new AddCountersSourceEffect(CounterType.QUEST.createInstance()), + TargetController.ANY, new AddCountersSourceEffect(CounterType.QUEST.createInstance()), true, ArchmageAscensionCondition.instance ), new CardsAmountDrawnThisTurnWatcher()); diff --git a/Mage.Sets/src/mage/cards/a/ArcticMerfolk.java b/Mage.Sets/src/mage/cards/a/ArcticMerfolk.java index 87c0e234f97..e55cbf13bf8 100644 --- a/Mage.Sets/src/mage/cards/a/ArcticMerfolk.java +++ b/Mage.Sets/src/mage/cards/a/ArcticMerfolk.java @@ -12,7 +12,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.counters.CounterType; -import mage.filter.StaticFilters; import mage.target.common.TargetControlledCreaturePermanent; import java.util.UUID; @@ -30,9 +29,9 @@ public final class ArcticMerfolk extends CardImpl { this.toughness = new MageInt(1); // Kicker—Return a creature you control to its owner's hand. (You may return a creature you control to its owner's hand in addition to any other costs as you cast this spell.) - this.addAbility(new KickerAbility(new ReturnToHandChosenControlledPermanentCost( - new TargetControlledCreaturePermanent(1, 1, StaticFilters.FILTER_CONTROLLED_CREATURE, true) - ))); + this.addAbility(new KickerAbility( + new ReturnToHandChosenControlledPermanentCost(new TargetControlledCreaturePermanent()) + )); // If Arctic Merfolk was kicked, it enters with a +1/+1 counter on it. this.addAbility(new EntersBattlefieldAbility( diff --git a/Mage.Sets/src/mage/cards/a/ArcumsSleigh.java b/Mage.Sets/src/mage/cards/a/ArcumsSleigh.java index 8601c8c0fe5..2939f784eb1 100644 --- a/Mage.Sets/src/mage/cards/a/ArcumsSleigh.java +++ b/Mage.Sets/src/mage/cards/a/ArcumsSleigh.java @@ -8,7 +8,7 @@ import mage.abilities.condition.common.DefendingPlayerControlsNoSourceCondition; import mage.abilities.condition.common.IsPhaseCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.VigilanceAbility; import mage.cards.CardImpl; @@ -41,7 +41,7 @@ public final class ArcumsSleigh extends CardImpl { new DefendingPlayerControlsNoSourceCondition(filter) // Only if defending player controls a snow land ); - Ability ability = new ConditionalActivatedAbility( + Ability ability = new ActivateIfConditionActivatedAbility( new GainAbilityTargetEffect(VigilanceAbility.getInstance()), new GenericManaCost(2), condition); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent()); diff --git a/Mage.Sets/src/mage/cards/a/ArdenAngel.java b/Mage.Sets/src/mage/cards/a/ArdenAngel.java index b67b4dc5947..2742b2f918f 100644 --- a/Mage.Sets/src/mage/cards/a/ArdenAngel.java +++ b/Mage.Sets/src/mage/cards/a/ArdenAngel.java @@ -49,7 +49,7 @@ class ArdenAngelEffect extends OneShotEffect { ArdenAngelEffect() { super(Outcome.Benefit); - this.staticText = "roll a four-sided die. If the result is 1, return {this} from your graveyard to the battlefield"; + this.staticText = "roll a four-sided die. If the result is 1, return this card from your graveyard to the battlefield"; } private ArdenAngelEffect(final ArdenAngelEffect effect) { diff --git a/Mage.Sets/src/mage/cards/a/ArenaAthlete.java b/Mage.Sets/src/mage/cards/a/ArenaAthlete.java index 2e79284fd8b..5372fa8fddf 100644 --- a/Mage.Sets/src/mage/cards/a/ArenaAthlete.java +++ b/Mage.Sets/src/mage/cards/a/ArenaAthlete.java @@ -1,7 +1,5 @@ - package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.effects.common.combat.CantBlockTargetEffect; @@ -11,17 +9,17 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.filter.StaticFilters; -import mage.target.common.TargetCreaturePermanent; +import mage.target.common.TargetOpponentsCreaturePermanent; + +import java.util.UUID; /** - * * @author Plopman */ public final class ArenaAthlete extends CardImpl { - + public ArenaAthlete(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.HUMAN); this.power = new MageInt(2); @@ -29,8 +27,7 @@ public final class ArenaAthlete extends CardImpl { // Heroic Whenever you cast a spell that targets Arena Athlete, target creature an opponent controls can't block this turn. Ability ability = new HeroicAbility(new CantBlockTargetEffect(Duration.EndOfTurn)); - TargetCreaturePermanent target = new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE); - ability.addTarget(target); + ability.addTarget(new TargetOpponentsCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/ArgentSphinx.java b/Mage.Sets/src/mage/cards/a/ArgentSphinx.java index 807b1241d4e..c23ce165654 100644 --- a/Mage.Sets/src/mage/cards/a/ArgentSphinx.java +++ b/Mage.Sets/src/mage/cards/a/ArgentSphinx.java @@ -37,13 +37,9 @@ public final class ArgentSphinx extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Metalcraft — {U}: Exile Argent Sphinx. Return it to the battlefield under your control at the beginning of the next end step. Activate this ability only if you control three or more artifacts. - Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new ArgentSphinxEffect(), - new ManaCostsImpl<>("{U}"), MetalcraftCondition.instance - ); - ability.setAbilityWord(AbilityWord.METALCRAFT); - ability.addHint(MetalcraftHint.instance); - this.addAbility(ability); + this.addAbility(new ActivateIfConditionActivatedAbility( + new ArgentSphinxEffect(), new ManaCostsImpl<>("{U}"), MetalcraftCondition.instance + ).setAbilityWord(AbilityWord.METALCRAFT).addHint(MetalcraftHint.instance)); } private ArgentSphinx(final ArgentSphinx card) { diff --git a/Mage.Sets/src/mage/cards/a/AriaOfFlame.java b/Mage.Sets/src/mage/cards/a/AriaOfFlame.java index 2856347067a..ae2fbda0afd 100644 --- a/Mage.Sets/src/mage/cards/a/AriaOfFlame.java +++ b/Mage.Sets/src/mage/cards/a/AriaOfFlame.java @@ -5,17 +5,15 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.CountersSourceCount; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.GainLifeAllEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; 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.StaticFilters; -import mage.game.Game; -import mage.players.Player; import mage.target.common.TargetPlayerOrPlaneswalker; import java.util.UUID; @@ -31,7 +29,7 @@ public final class AriaOfFlame extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); // When Aria of Flame enters the battlefield, each opponent gains 10 life. - this.addAbility(new EntersBattlefieldTriggeredAbility(new AriaOfFlameEffect())); + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeAllEffect(10, TargetController.OPPONENT))); // Whenever you cast an instant or sorcery spell, put a verse counter on Aria of Flame, then it deals damage equal to the number of verse counters on it to target player or planeswalker. Ability ability = new SpellCastControllerTriggeredAbility( @@ -54,31 +52,3 @@ public final class AriaOfFlame extends CardImpl { return new AriaOfFlame(this); } } - -class AriaOfFlameEffect extends OneShotEffect { - - AriaOfFlameEffect() { - super(Outcome.Benefit); - staticText = "each opponent gains 10 life"; - } - - private AriaOfFlameEffect(AriaOfFlameEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - for (UUID playerId : game.getOpponents(source.getControllerId())) { - Player player = game.getPlayer(playerId); - if (player != null) { - player.gainLife(10, game, source); - } - } - return true; - } - - @Override - public AriaOfFlameEffect copy() { - return new AriaOfFlameEffect(this); - } -} diff --git a/Mage.Sets/src/mage/cards/a/ArmTheCathars.java b/Mage.Sets/src/mage/cards/a/ArmTheCathars.java index f81384f8255..13d4cf1d25f 100644 --- a/Mage.Sets/src/mage/cards/a/ArmTheCathars.java +++ b/Mage.Sets/src/mage/cards/a/ArmTheCathars.java @@ -8,7 +8,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.other.AnotherTargetPredicate; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.targetpointer.EachTargetPointer; import mage.target.targetpointer.SecondTargetPointer; import mage.target.targetpointer.ThirdTargetPointer; @@ -35,28 +35,22 @@ public final class ArmTheCathars extends CardImpl { // Until end of turn, target creature gets +3/+3, up to one other target creature gets +2/+2, and up to one other target creature gets +1/+1. Those creatures gain vigilance until end of turn. this.getSpellAbility().addEffect(new BoostTargetEffect(3, 3) .setText("until end of turn, target creature gets +3/+3")); - TargetCreaturePermanent target1 = new TargetCreaturePermanent(filter1); - target1.setTargetTag(1); - this.getSpellAbility().addTarget(target1.withChooseHint("+3/+3")); + this.getSpellAbility().addTarget(new TargetPermanent(filter1).setTargetTag(1).withChooseHint("+3/+3")); this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2) .setTargetPointer(new SecondTargetPointer()) .setText(", up to one other target creature gets +2/+2")); - TargetCreaturePermanent target2 = new TargetCreaturePermanent(0, 1, filter2, false); - target2.setTargetTag(2); - this.getSpellAbility().addTarget(target2.withChooseHint("+2/+2")); + this.getSpellAbility().addTarget(new TargetPermanent(0, 1, filter2).setTargetTag(2).withChooseHint("+2/+2")); this.getSpellAbility().addEffect(new BoostTargetEffect(1, 1) .setTargetPointer(new ThirdTargetPointer()) .setText(", and up to one other target creature gets +1/+1")); - TargetCreaturePermanent target3 = new TargetCreaturePermanent(0, 1, filter3, false); - target3.setTargetTag(3); - this.getSpellAbility().addTarget(target3.withChooseHint("+1/+1")); + this.getSpellAbility().addTarget(new TargetPermanent(0, 1, filter3).setTargetTag(3).withChooseHint("+1/+1")); this.getSpellAbility().addEffect( new GainAbilityTargetEffect(VigilanceAbility.getInstance()) - .setTargetPointer(new EachTargetPointer()) - .setText("Those creatures gain vigilance until end of turn")); + .setTargetPointer(new EachTargetPointer()) + .setText("Those creatures gain vigilance until end of turn")); } private ArmTheCathars(final ArmTheCathars card) { diff --git a/Mage.Sets/src/mage/cards/a/ArmageddonClock.java b/Mage.Sets/src/mage/cards/a/ArmageddonClock.java index e373888d3ca..8d02db5fa89 100644 --- a/Mage.Sets/src/mage/cards/a/ArmageddonClock.java +++ b/Mage.Sets/src/mage/cards/a/ArmageddonClock.java @@ -1,19 +1,21 @@ package mage.cards.a; -import mage.abilities.ActivatedAbilityImpl; -import mage.abilities.triggers.BeginningOfDrawTriggeredAbility; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.IsStepCondition; -import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.dynamicvalue.common.CountersSourceCount; -import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.common.DamagePlayersEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; +import mage.abilities.triggers.BeginningOfDrawTriggeredAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.PhaseStep; +import mage.constants.TargetController; import mage.counters.CounterType; import java.util.UUID; @@ -23,24 +25,24 @@ import java.util.UUID; */ public final class ArmageddonClock extends CardImpl { + private static final Condition condition = new IsStepCondition(PhaseStep.UPKEEP, false); + public ArmageddonClock(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}"); // At the beginning of your upkeep, put a doom counter on Armageddon Clock. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.DOOM.createInstance(), StaticValue.get(1), true))); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.DOOM.createInstance()))); // At the beginning of your draw step, Armageddon Clock deals damage equal to the number of doom counters on it to each player. - this.addAbility(new BeginningOfDrawTriggeredAbility(new DamagePlayersEffect(Outcome.Damage, new CountersSourceCount(CounterType.DOOM)) - .setText("{this} deals damage equal to the number of doom counters on it to each player"), false)); + this.addAbility(new BeginningOfDrawTriggeredAbility( + new DamagePlayersEffect(Outcome.Damage, new CountersSourceCount(CounterType.DOOM)) + .setText("{this} deals damage equal to the number of doom counters on it to each player"), false + )); // {4}: Remove a doom counter from Armageddon Clock. Any player may activate this ability but only during any upkeep step. - ActivatedAbilityImpl ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, - new RemoveCounterSourceEffect(CounterType.DOOM.createInstance()), new ManaCostsImpl<>("{4}"), new IsStepCondition(PhaseStep.UPKEEP, false), - "{4}: Remove a doom counter from {this}. Any player may activate this ability but only during any upkeep step."); - - ability.setMayActivate(TargetController.ANY); - this.addAbility(ability); - + this.addAbility(new ActivateIfConditionActivatedAbility( + new RemoveCounterSourceEffect(CounterType.DOOM.createInstance()), new GenericManaCost(4), condition + ).withConditionText("any player may activate this ability but only during any upkeep step").setMayActivate(TargetController.ANY)); } private ArmageddonClock(final ArmageddonClock card) { diff --git a/Mage.Sets/src/mage/cards/a/ArmedProtocolDroid.java b/Mage.Sets/src/mage/cards/a/ArmedProtocolDroid.java index 861c904c6ec..45928233f06 100644 --- a/Mage.Sets/src/mage/cards/a/ArmedProtocolDroid.java +++ b/Mage.Sets/src/mage/cards/a/ArmedProtocolDroid.java @@ -14,6 +14,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -37,7 +38,7 @@ public final class ArmedProtocolDroid extends CardImpl { // When {this} enters, target nonartifact creature gets -2/-0 until end of turn. Ability ability = new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(-2, 0, Duration.EndOfTurn), false); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // Repair 3 diff --git a/Mage.Sets/src/mage/cards/a/ArmorOfThorns.java b/Mage.Sets/src/mage/cards/a/ArmorOfThorns.java index 6f2740c6efd..9017a215ad3 100644 --- a/Mage.Sets/src/mage/cards/a/ArmorOfThorns.java +++ b/Mage.Sets/src/mage/cards/a/ArmorOfThorns.java @@ -15,6 +15,8 @@ import mage.filter.StaticFilters; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author LoneFox @@ -29,7 +31,7 @@ public final class ArmorOfThorns extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.ALL, new CastAsThoughItHadFlashSourceEffect(Duration.EndOfGame))); this.addAbility(new SacrificeIfCastAtInstantTimeTriggeredAbility()); // Enchant nonblack creature - TargetPermanent auraTarget = new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK); + TargetPermanent auraTarget = new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); Ability ability = new EnchantAbility(auraTarget); diff --git a/Mage.Sets/src/mage/cards/a/ArtfulTakedown.java b/Mage.Sets/src/mage/cards/a/ArtfulTakedown.java index 0cd8dd68646..e661ab5ce18 100644 --- a/Mage.Sets/src/mage/cards/a/ArtfulTakedown.java +++ b/Mage.Sets/src/mage/cards/a/ArtfulTakedown.java @@ -8,6 +8,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -33,14 +34,14 @@ public final class ArtfulTakedown extends CardImpl { this.getSpellAbility().addEffect( new TapTargetEffect("tap target creature") ); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter1).withChooseHint("tap")); + this.getSpellAbility().addTarget(new TargetPermanent(filter1).withChooseHint("tap")); // • Target creature gets -2/-4 until end of turn. Mode mode = new Mode( new BoostTargetEffect(-2, -4, Duration.EndOfTurn) .setText("target creature gets -2/-4 until end of turn") ); - mode.addTarget(new TargetCreaturePermanent(filter2).withChooseHint("gets -2/-4 until end of turn")); + mode.addTarget(new TargetPermanent(filter2).withChooseHint("gets -2/-4 until end of turn")); this.getSpellAbility().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/a/ArtifactPossession.java b/Mage.Sets/src/mage/cards/a/ArtifactPossession.java index 5b0981dc1c0..981e1a181c6 100644 --- a/Mage.Sets/src/mage/cards/a/ArtifactPossession.java +++ b/Mage.Sets/src/mage/cards/a/ArtifactPossession.java @@ -1,7 +1,6 @@ package mage.cards.a; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.common.AttachEffect; @@ -19,6 +18,8 @@ import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetArtifactPermanent; +import java.util.UUID; + /** * * @author MarcoMarin @@ -87,6 +88,6 @@ class AbilityActivatedTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever enchanted artifact becomes tapped or a player activates an ability of enchanted artifact without {T} in its activation cost, Artifact Possession deals 2 damage to that artifact's controller."; + return "Whenever enchanted artifact becomes tapped or a player activates an ability of enchanted artifact without {T} in its activation cost, {this} deals 2 damage to that artifact's controller."; } } diff --git a/Mage.Sets/src/mage/cards/a/ArtilleryBlast.java b/Mage.Sets/src/mage/cards/a/ArtilleryBlast.java index 10172041867..8688ff875fc 100644 --- a/Mage.Sets/src/mage/cards/a/ArtilleryBlast.java +++ b/Mage.Sets/src/mage/cards/a/ArtilleryBlast.java @@ -12,6 +12,7 @@ import mage.constants.AbilityWord; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -32,7 +33,7 @@ public final class ArtilleryBlast extends CardImpl { // Domain--Artillery Blast deals X damage to target tapped creature, where X is 1 plus the number of basic land types among lands you control. this.getSpellAbility().addEffect(new DamageTargetEffect(new IntPlusDynamicValue(1, DomainValue.REGULAR)) .setText("{this} deals X damage to target tapped creature, where X is 1 plus the number of basic land types among lands you control")); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().setAbilityWord(AbilityWord.DOMAIN); this.getSpellAbility().addHint(DomainHint.instance); } diff --git a/Mage.Sets/src/mage/cards/a/AshenGhoul.java b/Mage.Sets/src/mage/cards/a/AshenGhoul.java index 739c9488d1e..5e9a82f57e3 100644 --- a/Mage.Sets/src/mage/cards/a/AshenGhoul.java +++ b/Mage.Sets/src/mage/cards/a/AshenGhoul.java @@ -1,12 +1,11 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; import mage.abilities.keyword.HasteAbility; import mage.cards.Card; @@ -19,8 +18,9 @@ import mage.constants.Zone; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class AshenGhoul extends CardImpl { @@ -36,7 +36,7 @@ public final class AshenGhoul extends CardImpl { this.addAbility(HasteAbility.getInstance()); // {B}: Return Ashen Ghoul from your graveyard to the battlefield. Activate this ability only during your upkeep and only if three or more creature cards are above Ashen Ghoul. - this.addAbility(new ConditionalActivatedAbility( + this.addAbility(new ActivateIfConditionActivatedAbility( Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldEffect(), new ManaCostsImpl<>("{B}"), @@ -85,6 +85,6 @@ enum AshenGhoulCondition implements Condition { @Override public String toString() { - return "only during your upkeep and only if three or more creature cards are above {this}"; + return "during your upkeep and only if three or more creature cards are above this card"; } } diff --git a/Mage.Sets/src/mage/cards/a/AshnodsTransmogrant.java b/Mage.Sets/src/mage/cards/a/AshnodsTransmogrant.java index d0a58762aa3..ad1872df42b 100644 --- a/Mage.Sets/src/mage/cards/a/AshnodsTransmogrant.java +++ b/Mage.Sets/src/mage/cards/a/AshnodsTransmogrant.java @@ -17,6 +17,7 @@ import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -41,7 +42,7 @@ public final class AshnodsTransmogrant extends CardImpl { Effect effect = new AddCardTypeTargetEffect(Duration.WhileOnBattlefield, CardType.ARTIFACT); effect.setText("That creature becomes an artifact in addition to its other types"); ability.addEffect(effect); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AshrootAnimist.java b/Mage.Sets/src/mage/cards/a/AshrootAnimist.java index 7de59b0f0a3..e7cabaea139 100644 --- a/Mage.Sets/src/mage/cards/a/AshrootAnimist.java +++ b/Mage.Sets/src/mage/cards/a/AshrootAnimist.java @@ -14,19 +14,17 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.filter.StaticFilters; import mage.target.TargetPermanent; -import mage.target.common.TargetControlledCreaturePermanent; import java.util.UUID; /** - * * @author ciaccona007 */ public final class AshrootAnimist extends CardImpl { public AshrootAnimist(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{G}"); - + this.subtype.add(SubType.LIZARD); this.subtype.add(SubType.DRUID); this.power = new MageInt(4); @@ -40,9 +38,9 @@ public final class AshrootAnimist extends CardImpl { new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn).setText("another target creature you control gains trample"), false ); - ability.addEffect( new BoostTargetEffect(SourcePermanentPowerValue.NOT_NEGATIVE, SourcePermanentPowerValue.NOT_NEGATIVE, Duration.EndOfTurn) + ability.addEffect(new BoostTargetEffect(SourcePermanentPowerValue.NOT_NEGATIVE, SourcePermanentPowerValue.NOT_NEGATIVE, Duration.EndOfTurn) .setText("and gets +X/+X until end of turn, where X is this creature's power")); - ability.addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/Asphyxiate.java b/Mage.Sets/src/mage/cards/a/Asphyxiate.java index adf83884a2a..794f196ea4b 100644 --- a/Mage.Sets/src/mage/cards/a/Asphyxiate.java +++ b/Mage.Sets/src/mage/cards/a/Asphyxiate.java @@ -8,6 +8,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -28,7 +29,7 @@ public final class Asphyxiate extends CardImpl { // Destroy target untapped creature. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private Asphyxiate(final Asphyxiate card) { diff --git a/Mage.Sets/src/mage/cards/a/Assassinate.java b/Mage.Sets/src/mage/cards/a/Assassinate.java index 63c1d2eca44..8c8ae1ea963 100644 --- a/Mage.Sets/src/mage/cards/a/Assassinate.java +++ b/Mage.Sets/src/mage/cards/a/Assassinate.java @@ -9,6 +9,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -26,7 +27,7 @@ public final class Assassinate extends CardImpl { public Assassinate(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{B}"); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); } diff --git a/Mage.Sets/src/mage/cards/a/AssassinsBlade.java b/Mage.Sets/src/mage/cards/a/AssassinsBlade.java index 9db8d9510d6..501b3e06b28 100644 --- a/Mage.Sets/src/mage/cards/a/AssassinsBlade.java +++ b/Mage.Sets/src/mage/cards/a/AssassinsBlade.java @@ -16,6 +16,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.permanent.AttackingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.watchers.common.PlayerAttackedStepWatcher; @@ -45,7 +46,7 @@ public final class AssassinsBlade extends CardImpl { // Destroy target nonblack attacking creature. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private AssassinsBlade(final AssassinsBlade card) { diff --git a/Mage.Sets/src/mage/cards/a/AssaultFormation.java b/Mage.Sets/src/mage/cards/a/AssaultFormation.java index 5b4e7179c4c..9f546d6edd0 100644 --- a/Mage.Sets/src/mage/cards/a/AssaultFormation.java +++ b/Mage.Sets/src/mage/cards/a/AssaultFormation.java @@ -15,6 +15,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -38,7 +39,7 @@ public final class AssaultFormation extends CardImpl { // {G}: Target creature with defender can attack this turn as though it didn't have defender. Ability ability = new SimpleActivatedAbility(new CanAttackAsThoughItDidntHaveDefenderTargetEffect(Duration.EndOfTurn), new ManaCostsImpl<>("{G}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // {2}{G}: Creatures you control get +0/+1 until end of turn. diff --git a/Mage.Sets/src/mage/cards/a/AstromechDroid.java b/Mage.Sets/src/mage/cards/a/AstromechDroid.java index b856816dbb0..02ead94b018 100644 --- a/Mage.Sets/src/mage/cards/a/AstromechDroid.java +++ b/Mage.Sets/src/mage/cards/a/AstromechDroid.java @@ -16,6 +16,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -44,7 +45,7 @@ public final class AstromechDroid extends CardImpl { new TapSourceCost()); ability.addEffect(new GainAbilityTargetEffect(VigilanceAbility.getInstance(), Duration.EndOfTurn) .setText("and gains vigilance until end of turn")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // Repair 4 diff --git a/Mage.Sets/src/mage/cards/a/AsylumVisitor.java b/Mage.Sets/src/mage/cards/a/AsylumVisitor.java index 3d01de1043e..2e9eafc3189 100644 --- a/Mage.Sets/src/mage/cards/a/AsylumVisitor.java +++ b/Mage.Sets/src/mage/cards/a/AsylumVisitor.java @@ -34,7 +34,7 @@ public final class AsylumVisitor extends CardImpl { // At the beginning of each player's upkeep, if that player has no cards in hand, you draw a card and you lose 1 life. Ability ability = new BeginningOfUpkeepTriggeredAbility( - TargetController.ANY, new DrawCardSourceControllerEffect(1, true), false + TargetController.EACH_PLAYER, new DrawCardSourceControllerEffect(1, true), false ).withInterveningIf(condition); ability.addEffect(new LoseLifeSourceControllerEffect(1).concatBy("and")); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/a/AtarkaBeastbreaker.java b/Mage.Sets/src/mage/cards/a/AtarkaBeastbreaker.java index e7013ddb2af..97681efaafd 100644 --- a/Mage.Sets/src/mage/cards/a/AtarkaBeastbreaker.java +++ b/Mage.Sets/src/mage/cards/a/AtarkaBeastbreaker.java @@ -1,38 +1,36 @@ - package mage.cards.a; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.common.FormidableCondition; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.AbilityWord; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class AtarkaBeastbreaker extends CardImpl { public AtarkaBeastbreaker(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WARRIOR); this.power = new MageInt(2); this.toughness = new MageInt(2); // Formidable — {4}{G}: Atarka Beastbreaker gets +4/+4 until end of turn. Activate this only if creatures you control have total power 8 or greater. - Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, - new BoostSourceEffect(4,4, Duration.EndOfTurn), - new ManaCostsImpl<>("{4}{G}"), - FormidableCondition.instance); - ability.setAbilityWord(AbilityWord.FORMIDABLE); - this.addAbility(ability); + this.addAbility(new ActivateIfConditionActivatedAbility( + new BoostSourceEffect(4, 4, Duration.EndOfTurn), + new ManaCostsImpl<>("{4}{G}"), FormidableCondition.instance + ).setAbilityWord(AbilityWord.FORMIDABLE)); } private AtarkaBeastbreaker(final AtarkaBeastbreaker card) { diff --git a/Mage.Sets/src/mage/cards/a/AtarkaPummeler.java b/Mage.Sets/src/mage/cards/a/AtarkaPummeler.java index a42c030a66a..c01968c39af 100644 --- a/Mage.Sets/src/mage/cards/a/AtarkaPummeler.java +++ b/Mage.Sets/src/mage/cards/a/AtarkaPummeler.java @@ -1,8 +1,6 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.common.FormidableCondition; import mage.abilities.costs.mana.ManaCostsImpl; @@ -10,31 +8,30 @@ import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.abilities.keyword.MenaceAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.AbilityWord; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; import mage.filter.StaticFilters; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class AtarkaPummeler extends CardImpl { public AtarkaPummeler(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}"); this.subtype.add(SubType.OGRE); this.subtype.add(SubType.WARRIOR); this.power = new MageInt(4); this.toughness = new MageInt(5); // Formidable — {3}{R}{R}: Creatures you control gain menace until end of turn. Activate this ability only if creature you control have total power 8 or greater. (They can't be blocked except by two or more creatures.) - Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, - new GainAbilityAllEffect(new MenaceAbility(), Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURES), - new ManaCostsImpl<>("{3}{R}{R}"), - FormidableCondition.instance); - ability.setAbilityWord(AbilityWord.FORMIDABLE); - this.addAbility(ability); - + this.addAbility(new ActivateIfConditionActivatedAbility(new GainAbilityAllEffect( + new MenaceAbility(false), Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURES + ), new ManaCostsImpl<>("{3}{R}{R}"), FormidableCondition.instance).setAbilityWord(AbilityWord.FORMIDABLE)); } private AtarkaPummeler(final AtarkaPummeler card) { diff --git a/Mage.Sets/src/mage/cards/a/AtraxiWarden.java b/Mage.Sets/src/mage/cards/a/AtraxiWarden.java index 00c4b0e3474..8103813cf06 100644 --- a/Mage.Sets/src/mage/cards/a/AtraxiWarden.java +++ b/Mage.Sets/src/mage/cards/a/AtraxiWarden.java @@ -13,7 +13,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -28,7 +28,6 @@ public final class AtraxiWarden extends CardImpl { filter.add(TappedPredicate.TAPPED); } - public AtraxiWarden(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}{W}"); @@ -42,7 +41,7 @@ public final class AtraxiWarden extends CardImpl { // When Atraxi Warden enters the battlefield, exile up to one target tapped creature. Ability ability = new EntersBattlefieldTriggeredAbility(new ExileTargetEffect()); - ability.addTarget(new TargetCreaturePermanent(0, 1, filter, false)); + ability.addTarget(new TargetPermanent(0, 1, filter)); this.addAbility(ability); // Suspend 5--{1}{W} diff --git a/Mage.Sets/src/mage/cards/a/Attrition.java b/Mage.Sets/src/mage/cards/a/Attrition.java index c662c24a2ef..bda95864562 100644 --- a/Mage.Sets/src/mage/cards/a/Attrition.java +++ b/Mage.Sets/src/mage/cards/a/Attrition.java @@ -10,9 +10,12 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ColoredManaSymbol; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author Backfir3 @@ -25,7 +28,7 @@ public final class Attrition extends CardImpl { //{B}, Sacrifice a creature: Destroy target nonblack creature. SimpleActivatedAbility ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new ColoredManaCost(ColoredManaSymbol.B)); ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_CREATURE)); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK).withChooseHint("to destroy")); + ability.addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK).withChooseHint("to destroy")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AtzocanArcher.java b/Mage.Sets/src/mage/cards/a/AtzocanArcher.java index 4e7ca252211..dda10676363 100644 --- a/Mage.Sets/src/mage/cards/a/AtzocanArcher.java +++ b/Mage.Sets/src/mage/cards/a/AtzocanArcher.java @@ -13,8 +13,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * * @author TheElk801 @@ -37,7 +40,7 @@ public final class AtzocanArcher extends CardImpl { effect.setText("you may have it fight another target creature. " + "(Each deals damage equal to its power to the other.)"); Ability ability = new EntersBattlefieldTriggeredAbility(effect, true); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AugurIlVec.java b/Mage.Sets/src/mage/cards/a/AugurIlVec.java index 82ee55d7db2..36f5a8ac220 100644 --- a/Mage.Sets/src/mage/cards/a/AugurIlVec.java +++ b/Mage.Sets/src/mage/cards/a/AugurIlVec.java @@ -1,28 +1,25 @@ - package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.SacrificeSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.keyword.ShadowAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.PhaseStep; import mage.constants.SubType; -import mage.constants.Zone; + +import java.util.UUID; /** - * * @author fireshoes */ public final class AugurIlVec extends CardImpl { public AugurIlVec(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.CLERIC); this.power = new MageInt(1); @@ -30,12 +27,11 @@ public final class AugurIlVec extends CardImpl { // Shadow this.addAbility(ShadowAbility.getInstance()); - + // Sacrifice Augur il-Vec: You gain 4 life. Activate this ability only during your upkeep. - this.addAbility(new ConditionalActivatedAbility(Zone.BATTLEFIELD, - new GainLifeEffect(4), - new SacrificeSourceCost(), - new IsStepCondition(PhaseStep.UPKEEP))); + this.addAbility(new ActivateIfConditionActivatedAbility( + new GainLifeEffect(4), new SacrificeSourceCost(), IsStepCondition.getMyUpkeep() + )); } private AugurIlVec(final AugurIlVec card) { diff --git a/Mage.Sets/src/mage/cards/a/AugurOfSkulls.java b/Mage.Sets/src/mage/cards/a/AugurOfSkulls.java index 249ab1a1faa..ac611228f2f 100644 --- a/Mage.Sets/src/mage/cards/a/AugurOfSkulls.java +++ b/Mage.Sets/src/mage/cards/a/AugurOfSkulls.java @@ -1,32 +1,29 @@ - package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.RegenerateSourceEffect; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.PhaseStep; import mage.constants.SubType; -import mage.constants.Zone; import mage.target.TargetPlayer; +import java.util.UUID; + /** - * * @author fireshoes */ public final class AugurOfSkulls extends CardImpl { public AugurOfSkulls(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.SKELETON); this.subtype.add(SubType.WIZARD); this.power = new MageInt(1); @@ -34,11 +31,10 @@ public final class AugurOfSkulls extends CardImpl { // {1}{B}: Regenerate Augur of Skulls. this.addAbility(new SimpleActivatedAbility(new RegenerateSourceEffect(), new ManaCostsImpl<>("{1}{B}"))); + // Sacrifice Augur of Skulls: Target player discards two cards. Activate this ability only during your upkeep. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, - new DiscardTargetEffect(2), - new SacrificeSourceCost(), - new IsStepCondition(PhaseStep.UPKEEP) + Ability ability = new ActivateIfConditionActivatedAbility( + new DiscardTargetEffect(2), new SacrificeSourceCost(), IsStepCondition.getMyUpkeep() ); ability.addTarget(new TargetPlayer()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/a/AuntiesSnitch.java b/Mage.Sets/src/mage/cards/a/AuntiesSnitch.java index cc27792c2ed..7f05cabec0f 100644 --- a/Mage.Sets/src/mage/cards/a/AuntiesSnitch.java +++ b/Mage.Sets/src/mage/cards/a/AuntiesSnitch.java @@ -44,7 +44,7 @@ public final class AuntiesSnitch extends CardImpl { // Whenever a Goblin or Rogue you control deals combat damage to a player, if Auntie's Snitch is in your graveyard, you may return Auntie's Snitch to your hand. this.addAbility(new DealsDamageToAPlayerAllTriggeredAbility(Zone.GRAVEYARD, - new ReturnSourceFromGraveyardToHandEffect().setText("return {this} to your hand"), + new ReturnSourceFromGraveyardToHandEffect().setText("return this card to your hand"), filter, true, SetTargetPointer.NONE, true, false ).withInterveningIf(SourceInGraveyardCondition.instance)); } diff --git a/Mage.Sets/src/mage/cards/a/AuraOfDominion.java b/Mage.Sets/src/mage/cards/a/AuraOfDominion.java index 9b68395a9f7..33795e7c34a 100644 --- a/Mage.Sets/src/mage/cards/a/AuraOfDominion.java +++ b/Mage.Sets/src/mage/cards/a/AuraOfDominion.java @@ -1,8 +1,5 @@ - - package mage.cards.a; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapTargetCost; @@ -15,35 +12,29 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; -import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.permanent.TappedPredicate; +import mage.filter.StaticFilters; import mage.target.TargetPermanent; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * @author Loki */ public final class AuraOfDominion extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); - - static { - filter.add(TappedPredicate.UNTAPPED); - } - - public AuraOfDominion(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}{U}"); this.subtype.add(SubType.AURA); TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.Untap)); this.addAbility(new EnchantAbility(auraTarget)); + Ability ability = new SimpleActivatedAbility(new UntapAttachedEffect(), new GenericManaCost(1)); - ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, false))); + ability.addCost(new TapTargetCost(new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURE))); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AuriokSiegeSled.java b/Mage.Sets/src/mage/cards/a/AuriokSiegeSled.java index bb360508011..46e06b9eefb 100644 --- a/Mage.Sets/src/mage/cards/a/AuriokSiegeSled.java +++ b/Mage.Sets/src/mage/cards/a/AuriokSiegeSled.java @@ -13,8 +13,11 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_ARTIFACT_CREATURE; + /** * * @author Galatolol @@ -31,7 +34,7 @@ public final class AuriokSiegeSled extends CardImpl { MustBeBlockedByTargetSourceEffect effect = new MustBeBlockedByTargetSourceEffect(Duration.EndOfTurn); effect.setText("target artifact creature blocks {this} this turn if able"); Ability ability1 = new SimpleActivatedAbility(effect, new GenericManaCost(1)); - ability1.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_CREATURE)); + ability1.addTarget(new TargetPermanent(FILTER_PERMANENT_ARTIFACT_CREATURE)); this.addAbility(ability1); // {1}: Target artifact creature can't block Auriok Siege Sled this turn. @@ -39,7 +42,7 @@ public final class AuriokSiegeSled extends CardImpl { new CantBeBlockedByTargetSourceEffect(Duration.EndOfTurn), new GenericManaCost(1) ); - ability2.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_CREATURE)); + ability2.addTarget(new TargetPermanent(FILTER_PERMANENT_ARTIFACT_CREATURE)); this.addAbility(ability2); } diff --git a/Mage.Sets/src/mage/cards/a/AutomatedAssemblyLine.java b/Mage.Sets/src/mage/cards/a/AutomatedAssemblyLine.java index 3bf19b3aff3..ba1f028e7de 100644 --- a/Mage.Sets/src/mage/cards/a/AutomatedAssemblyLine.java +++ b/Mage.Sets/src/mage/cards/a/AutomatedAssemblyLine.java @@ -11,7 +11,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; -import mage.game.permanent.token.RobotToken; +import mage.game.permanent.token.Robot33Token; /** * @author Cguy7777 @@ -27,7 +27,7 @@ public final class AutomatedAssemblyLine extends CardImpl { // Pay {E}{E}{E}: Create a tapped 3/3 colorless Robot artifact creature token. this.addAbility(new SimpleActivatedAbility( - new CreateTokenEffect(new RobotToken(), 1, true), + new CreateTokenEffect(new Robot33Token(), 1, true), new PayEnergyCost(3))); } diff --git a/Mage.Sets/src/mage/cards/a/AutumnWillow.java b/Mage.Sets/src/mage/cards/a/AutumnWillow.java index a85dc1b5875..065302601e9 100644 --- a/Mage.Sets/src/mage/cards/a/AutumnWillow.java +++ b/Mage.Sets/src/mage/cards/a/AutumnWillow.java @@ -1,7 +1,6 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -15,6 +14,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPlayer; +import java.util.UUID; + /** * * @author L_J @@ -51,7 +52,7 @@ class AutumnWillowEffect extends AsThoughEffectImpl { AutumnWillowEffect() { super(AsThoughEffectType.SHROUD, Duration.EndOfTurn, Outcome.Benefit); - staticText = "Until end of turn, Autumn Willow can be the target of spells and abilities controlled by target player as though it didn't have shroud"; + staticText = "Until end of turn, {this} can be the target of spells and abilities controlled by target player as though it didn't have shroud"; } private AutumnWillowEffect(final AutumnWillowEffect effect) { diff --git a/Mage.Sets/src/mage/cards/a/AvacynGuardianAngel.java b/Mage.Sets/src/mage/cards/a/AvacynGuardianAngel.java index 9ab15663f99..f29f15689ee 100644 --- a/Mage.Sets/src/mage/cards/a/AvacynGuardianAngel.java +++ b/Mage.Sets/src/mage/cards/a/AvacynGuardianAngel.java @@ -18,11 +18,14 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetPlayerOrPlaneswalker; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * @author LevelX2 */ @@ -44,7 +47,7 @@ public final class AvacynGuardianAngel extends CardImpl { Ability ability = new SimpleActivatedAbility( new AvacynGuardianAngelPreventToCreatureEffect(), new ManaCostsImpl<>("{1}{W}")); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); // {5}{W}{W}: Prevent all damage that would be dealt to target player this turn by sources of the color of your choice. diff --git a/Mage.Sets/src/mage/cards/a/AvacynianPriest.java b/Mage.Sets/src/mage/cards/a/AvacynianPriest.java index 889728f9d37..de66425a2af 100644 --- a/Mage.Sets/src/mage/cards/a/AvacynianPriest.java +++ b/Mage.Sets/src/mage/cards/a/AvacynianPriest.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -39,7 +40,7 @@ public final class AvacynianPriest extends CardImpl { // {1}, {T}: Tap target non-Human creature. Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new GenericManaCost(1)); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AvalancheTusker.java b/Mage.Sets/src/mage/cards/a/AvalancheTusker.java index 0606733a476..c14155cfaec 100644 --- a/Mage.Sets/src/mage/cards/a/AvalancheTusker.java +++ b/Mage.Sets/src/mage/cards/a/AvalancheTusker.java @@ -1,21 +1,20 @@ package mage.cards.a; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.effects.common.combat.MustBeBlockedByTargetSourceEffect; 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.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.game.events.GameEvent; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster; + +import java.util.UUID; /** * @@ -32,7 +31,11 @@ public final class AvalancheTusker extends CardImpl { this.toughness = new MageInt(4); // Whenever Avalanche Tusker attacks, target creature defending player controls blocks it this turn if able. - this.addAbility(new AvalancheTuskerAbility()); + Ability ability = new AttacksTriggeredAbility(new MustBeBlockedByTargetSourceEffect(Duration.EndOfCombat) + .setText("target creature defending player controls blocks it this combat if able"), false, null, SetTargetPointer.PLAYER); + ability.addTarget(new TargetCreaturePermanent()); + ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster()); + this.addAbility(ability); } private AvalancheTusker(final AvalancheTusker card) { @@ -44,44 +47,3 @@ public final class AvalancheTusker extends CardImpl { return new AvalancheTusker(this); } } - -class AvalancheTuskerAbility extends TriggeredAbilityImpl { - - public AvalancheTuskerAbility() { - super(Zone.BATTLEFIELD, new MustBeBlockedByTargetSourceEffect(Duration.EndOfCombat), false); - } - - private AvalancheTuskerAbility(final AvalancheTuskerAbility ability) { - super(ability); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ATTACKER_DECLARED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getSourceId().equals(this.getSourceId())) { - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); - UUID defenderId = game.getCombat().getDefendingPlayerId(sourceId, game); - filter.add(new ControllerIdPredicate(defenderId)); - - this.getTargets().clear(); - TargetCreaturePermanent target = new TargetCreaturePermanent(filter); - this.addTarget(target); - return true; - } - return false; - } - - @Override - public String getRule() { - return "Whenever {this} attacks, target creature defending player controls blocks it this combat if able."; - } - - @Override - public AvalancheTuskerAbility copy() { - return new AvalancheTuskerAbility(this); - } -} diff --git a/Mage.Sets/src/mage/cards/a/AvenAugur.java b/Mage.Sets/src/mage/cards/a/AvenAugur.java index a5e4429c544..ff46d3db90c 100644 --- a/Mage.Sets/src/mage/cards/a/AvenAugur.java +++ b/Mage.Sets/src/mage/cards/a/AvenAugur.java @@ -1,30 +1,27 @@ - package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.SacrificeSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; 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.PhaseStep; import mage.constants.SubType; -import mage.constants.Zone; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class AvenAugur extends CardImpl { public AvenAugur(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); this.subtype.add(SubType.BIRD); this.subtype.add(SubType.WIZARD); this.power = new MageInt(2); @@ -32,12 +29,11 @@ public final class AvenAugur extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); - + // Sacrifice Aven Augur: Return up to two target creatures to their owners' hands. Activate this ability only during your upkeep. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, - new ReturnToHandTargetEffect(), - new SacrificeSourceCost(), - new IsStepCondition(PhaseStep.UPKEEP)); + Ability ability = new ActivateIfConditionActivatedAbility( + new ReturnToHandTargetEffect(), new SacrificeSourceCost(), IsStepCondition.getMyUpkeep() + ); ability.addTarget(new TargetCreaturePermanent(0, 2)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AvenSoulgazer.java b/Mage.Sets/src/mage/cards/a/AvenSoulgazer.java index b2838c20677..2587e2e60b5 100644 --- a/Mage.Sets/src/mage/cards/a/AvenSoulgazer.java +++ b/Mage.Sets/src/mage/cards/a/AvenSoulgazer.java @@ -19,6 +19,7 @@ import mage.filter.predicate.card.FaceDownPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -47,7 +48,7 @@ public final class AvenSoulgazer extends CardImpl { // {2}{W}: Look at target face-down creature. Ability ability = new SimpleActivatedAbility(new AvenSoulgazerLookFaceDownEffect(), new ManaCostsImpl<>("{2}{W}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AyarasOathsworn.java b/Mage.Sets/src/mage/cards/a/AyarasOathsworn.java index 28783a8319b..dec15fd7839 100644 --- a/Mage.Sets/src/mage/cards/a/AyarasOathsworn.java +++ b/Mage.Sets/src/mage/cards/a/AyarasOathsworn.java @@ -42,7 +42,7 @@ public final class AyarasOathsworn extends CardImpl { Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility( new AddCountersSourceEffect(CounterType.P1P1.createInstance()) .setText("put a +1/+1 counter on it"), false - ).withInterveningIf(condition1); + ).withInterveningIf(condition1).withRuleTextReplacement(true); ability.addEffect(new ConditionalOneShotEffect( new SearchLibraryPutInHandEffect(new TargetCardInLibrary(), false), condition2, "Then if it has exactly four +1/+1 counters on it, " + diff --git a/Mage.Sets/src/mage/cards/a/AyliEternalPilgrim.java b/Mage.Sets/src/mage/cards/a/AyliEternalPilgrim.java index 69dbeb75a4d..5a88961c075 100644 --- a/Mage.Sets/src/mage/cards/a/AyliEternalPilgrim.java +++ b/Mage.Sets/src/mage/cards/a/AyliEternalPilgrim.java @@ -7,7 +7,7 @@ import mage.abilities.condition.common.MoreThanStartingLifeTotalCondition; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.dynamicvalue.common.SacrificeCostCreaturesToughness; import mage.abilities.effects.Effect; import mage.abilities.effects.common.ExileTargetEffect; @@ -18,7 +18,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; -import mage.constants.Zone; import mage.filter.StaticFilters; import mage.target.common.TargetNonlandPermanent; @@ -47,11 +46,8 @@ public final class AyliEternalPilgrim extends CardImpl { this.addAbility(ability); // {1}{W}{B}, Sacrifice another creature: Exile target nonland permanent. Activate only if you have at least 10 life more than your starting life total. - ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, - new ExileTargetEffect(), - new ManaCostsImpl<>("{1}{W}{B}"), - MoreThanStartingLifeTotalCondition.TEN + ability = new ActivateIfConditionActivatedAbility( + new ExileTargetEffect(), new ManaCostsImpl<>("{1}{W}{B}"), MoreThanStartingLifeTotalCondition.TEN ); ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE)); ability.addTarget(new TargetNonlandPermanent().withChooseHint("to exile")); diff --git a/Mage.Sets/src/mage/cards/a/AysenBureaucrats.java b/Mage.Sets/src/mage/cards/a/AysenBureaucrats.java index 4c6b5280596..f29dbe22230 100644 --- a/Mage.Sets/src/mage/cards/a/AysenBureaucrats.java +++ b/Mage.Sets/src/mage/cards/a/AysenBureaucrats.java @@ -16,6 +16,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,7 +39,7 @@ public final class AysenBureaucrats extends CardImpl { // {tap}: Tap target creature with power 2 or less. Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new TapSourceCost()); - Target target = new TargetCreaturePermanent(filter); + Target target = new TargetPermanent(filter); ability.addTarget(target); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AzoriusArrester.java b/Mage.Sets/src/mage/cards/a/AzoriusArrester.java index 689a8c32388..92cdbdd1731 100644 --- a/Mage.Sets/src/mage/cards/a/AzoriusArrester.java +++ b/Mage.Sets/src/mage/cards/a/AzoriusArrester.java @@ -1,7 +1,5 @@ - package mage.cards.a; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -10,17 +8,17 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.StaticFilters; -import mage.target.common.TargetCreaturePermanent; +import mage.target.common.TargetOpponentsCreaturePermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class AzoriusArrester extends CardImpl { - + public AzoriusArrester(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); @@ -29,8 +27,7 @@ public final class AzoriusArrester extends CardImpl { // When Azorius Arrester enters the battlefield, detain target creature an opponent controls. Ability ability = new EntersBattlefieldTriggeredAbility(new DetainTargetEffect(), false); - TargetCreaturePermanent target = new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE); - ability.addTarget(target); + ability.addTarget(new TargetOpponentsCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/a/AzoriusPloy.java b/Mage.Sets/src/mage/cards/a/AzoriusPloy.java index b2b1517383a..cc6ce3218e1 100644 --- a/Mage.Sets/src/mage/cards/a/AzoriusPloy.java +++ b/Mage.Sets/src/mage/cards/a/AzoriusPloy.java @@ -11,6 +11,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.filter.common.FilterCreaturePermanent; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.SecondTargetPointer; @@ -28,7 +29,7 @@ public final class AzoriusPloy extends CardImpl { Effect effect = new PreventDamageByTargetEffect( Duration.EndOfTurn, true); effect.setText("Prevent all combat damage target creature would deal this turn."); this.getSpellAbility().addEffect(effect); - Target target = new TargetCreaturePermanent(new FilterCreaturePermanent("first creature")); + Target target = new TargetPermanent(new FilterCreaturePermanent("first creature")); this.getSpellAbility().addTarget(target); // Prevent all combat damage that would be dealt to target creature this turn. @@ -36,7 +37,7 @@ public final class AzoriusPloy extends CardImpl { effect2.setText("

Prevent all combat damage that would be dealt to target creature this turn."); effect2.setTargetPointer(new SecondTargetPointer()); this.getSpellAbility().addEffect(effect2); - target = new TargetCreaturePermanent(new FilterCreaturePermanent("second creature (can be the same as the first)")); + target = new TargetPermanent(new FilterCreaturePermanent("second creature (can be the same as the first)")); this.getSpellAbility().addTarget(target); } @@ -49,4 +50,4 @@ public final class AzoriusPloy extends CardImpl { public AzoriusPloy copy() { return new AzoriusPloy(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/a/AzorsGateway.java b/Mage.Sets/src/mage/cards/a/AzorsGateway.java index a5c4062569b..6ac44610cf8 100644 --- a/Mage.Sets/src/mage/cards/a/AzorsGateway.java +++ b/Mage.Sets/src/mage/cards/a/AzorsGateway.java @@ -1,10 +1,6 @@ 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.common.SimpleActivatedAbility; @@ -20,13 +16,16 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SuperType; -import mage.constants.Zone; import mage.game.ExileZone; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInHand; import mage.util.CardUtil; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + /** * @author LevelX2 */ @@ -63,7 +62,7 @@ class AzorsGatewayEffect extends OneShotEffect { super(Outcome.Benefit); this.staticText = "Draw a card, then exile a card from your hand. " + "If cards with five or more different mana values are exiled with {this}, " + - "you gain 5 life, untap Azor's Gateway, and transform it"; + "you gain 5 life, untap {this}, and transform it"; } private AzorsGatewayEffect(final AzorsGatewayEffect effect) { diff --git a/Mage.Sets/src/mage/cards/b/Backlash.java b/Mage.Sets/src/mage/cards/b/Backlash.java index 526ad3e8ede..194f482c527 100644 --- a/Mage.Sets/src/mage/cards/b/Backlash.java +++ b/Mage.Sets/src/mage/cards/b/Backlash.java @@ -11,6 +11,7 @@ import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -30,7 +31,7 @@ public final class Backlash extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}{R}"); // Tap target untapped creature. That creature deals damage equal to its power to its controller. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new BacklashEffect()); } diff --git a/Mage.Sets/src/mage/cards/b/Backslide.java b/Mage.Sets/src/mage/cards/b/Backslide.java index 55244f2a08e..ad4b9c58451 100644 --- a/Mage.Sets/src/mage/cards/b/Backslide.java +++ b/Mage.Sets/src/mage/cards/b/Backslide.java @@ -19,6 +19,7 @@ import mage.filter.predicate.mageobject.AbilityPredicate; import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.game.Game; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,7 +39,7 @@ public final class Backslide extends CardImpl { // Turn target creature with a morph ability face down. this.getSpellAbility().addEffect(new BackslideEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // Cycling {U} this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{U}"))); diff --git a/Mage.Sets/src/mage/cards/b/BakisCurse.java b/Mage.Sets/src/mage/cards/b/BakisCurse.java index 5ef672b66dc..3d9620bc454 100644 --- a/Mage.Sets/src/mage/cards/b/BakisCurse.java +++ b/Mage.Sets/src/mage/cards/b/BakisCurse.java @@ -1,8 +1,6 @@ package mage.cards.b; -import java.util.List; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; @@ -14,6 +12,9 @@ import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.List; +import java.util.UUID; + /** * * @author L_J @@ -40,8 +41,8 @@ public final class BakisCurse extends CardImpl { class BakisCurseEffect extends OneShotEffect { public BakisCurseEffect() { - super(Outcome.Detriment); - staticText = "Baki's Curse deals 2 damage to each creature for each Aura attached to that creature."; + super(Outcome.Detriment); + staticText = "{this} deals 2 damage to each creature for each Aura attached to that creature."; } private BakisCurseEffect(final BakisCurseEffect effect) { diff --git a/Mage.Sets/src/mage/cards/b/BalaGedScorpion.java b/Mage.Sets/src/mage/cards/b/BalaGedScorpion.java index 715f714f211..3f9017502b7 100644 --- a/Mage.Sets/src/mage/cards/b/BalaGedScorpion.java +++ b/Mage.Sets/src/mage/cards/b/BalaGedScorpion.java @@ -12,6 +12,7 @@ import mage.constants.ComparisonType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -34,7 +35,7 @@ public final class BalaGedScorpion extends CardImpl { this.toughness = new MageInt(3); EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), true); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/BalduvianHydra.java b/Mage.Sets/src/mage/cards/b/BalduvianHydra.java index a73a65fe5af..a4ea88e3b0d 100644 --- a/Mage.Sets/src/mage/cards/b/BalduvianHydra.java +++ b/Mage.Sets/src/mage/cards/b/BalduvianHydra.java @@ -1,4 +1,3 @@ - package mage.cards.b; import mage.MageInt; @@ -7,19 +6,20 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.RemoveCountersSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect; import mage.abilities.effects.common.PreventDamageToSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +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 BalduvianHydra extends CardImpl { @@ -35,11 +35,16 @@ public final class BalduvianHydra extends CardImpl { this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.P1P0.createInstance()))); // Remove a +1/+0 counter from Balduvian Hydra: Prevent the next 1 damage that would be dealt to Balduvian Hydra this turn. - this.addAbility(new SimpleActivatedAbility(new PreventDamageToSourceEffect(Duration.EndOfTurn, 1), new RemoveCountersSourceCost(CounterType.P1P0.createInstance()))); + this.addAbility(new SimpleActivatedAbility( + new PreventDamageToSourceEffect(Duration.EndOfTurn, 1), + new RemoveCountersSourceCost(CounterType.P1P0.createInstance()) + )); // {R}{R}{R}: Put a +1/+0 counter on Balduvian Hydra. Activate this ability only during your upkeep. - this.addAbility(new ConditionalActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P0.createInstance(1)), new ManaCostsImpl<>("{R}{R}{R}"), new IsStepCondition(PhaseStep.UPKEEP), null)); - + this.addAbility(new ActivateIfConditionActivatedAbility( + new AddCountersSourceEffect(CounterType.P1P0.createInstance(1)), + new ManaCostsImpl<>("{R}{R}{R}"), IsStepCondition.getMyUpkeep() + )); } private BalduvianHydra(final BalduvianHydra card) { diff --git a/Mage.Sets/src/mage/cards/b/BalduvianRage.java b/Mage.Sets/src/mage/cards/b/BalduvianRage.java index 8adf853365b..bca99675940 100644 --- a/Mage.Sets/src/mage/cards/b/BalduvianRage.java +++ b/Mage.Sets/src/mage/cards/b/BalduvianRage.java @@ -13,6 +13,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.filter.common.FilterAttackingCreature; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; @@ -26,7 +27,7 @@ public final class BalduvianRage extends CardImpl { // Target attacking creature gets +X/+0 until end of turn. this.getSpellAbility().addEffect(new BoostTargetEffect(GetXValue.instance, StaticValue.get(0), Duration.EndOfTurn)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterAttackingCreature())); + this.getSpellAbility().addTarget(new TargetPermanent(new FilterAttackingCreature())); // Draw a card at the beginning of the next turn's upkeep. this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect( diff --git a/Mage.Sets/src/mage/cards/b/BalduvianWarlord.java b/Mage.Sets/src/mage/cards/b/BalduvianWarlord.java index 43420c8bd1a..40e0af18fb4 100644 --- a/Mage.Sets/src/mage/cards/b/BalduvianWarlord.java +++ b/Mage.Sets/src/mage/cards/b/BalduvianWarlord.java @@ -5,13 +5,16 @@ import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.RemoveFromCombatTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.PhaseStep; +import mage.constants.SubType; import mage.filter.common.FilterAttackingCreature; import mage.filter.common.FilterBlockingCreature; import mage.filter.predicate.permanent.PermanentReferenceInCollectionPredicate; @@ -38,7 +41,7 @@ public final class BalduvianWarlord extends CardImpl { this.toughness = new MageInt(2); // {T}: Remove target blocking creature from combat. Creatures it was blocking that hadn't become blocked by another creature this combat become unblocked, then it blocks an attacking creature of your choice. Activate this ability only during the declare blockers step. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new BalduvianWarlordUnblockEffect(), new TapSourceCost(), new IsStepCondition(PhaseStep.DECLARE_BLOCKERS, false)); + Ability ability = new ActivateIfConditionActivatedAbility(new BalduvianWarlordUnblockEffect(), new TapSourceCost(), new IsStepCondition(PhaseStep.DECLARE_BLOCKERS, false)); ability.addTarget(new TargetPermanent(new FilterBlockingCreature())); this.addAbility(ability, new BlockedByOnlyOneCreatureThisCombatWatcher()); } diff --git a/Mage.Sets/src/mage/cards/b/BallLightning.java b/Mage.Sets/src/mage/cards/b/BallLightning.java index 697df3a9446..45a6e9a2c15 100644 --- a/Mage.Sets/src/mage/cards/b/BallLightning.java +++ b/Mage.Sets/src/mage/cards/b/BallLightning.java @@ -1,27 +1,25 @@ - - package mage.cards.b; -import java.util.UUID; import mage.MageInt; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.game.events.GameEvent.EventType; +import mage.constants.TargetController; + +import java.util.UUID; /** - * * @author BetaSteward_at_googlemail.com */ public final class BallLightning extends CardImpl { public BallLightning(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{R}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}{R}{R}"); this.subtype.add(SubType.ELEMENTAL); this.power = new MageInt(6); @@ -29,7 +27,9 @@ public final class BallLightning extends CardImpl { this.addAbility(TrampleAbility.getInstance()); this.addAbility(HasteAbility.getInstance()); - this.addAbility(new OnEventTriggeredAbility(EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new SacrificeSourceEffect())); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.NEXT, new SacrificeSourceEffect(), false + )); } private BallLightning(final BallLightning card) { diff --git a/Mage.Sets/src/mage/cards/b/BalladOfTheBlackFlag.java b/Mage.Sets/src/mage/cards/b/BalladOfTheBlackFlag.java index a6a9df732da..786bd942454 100644 --- a/Mage.Sets/src/mage/cards/b/BalladOfTheBlackFlag.java +++ b/Mage.Sets/src/mage/cards/b/BalladOfTheBlackFlag.java @@ -6,6 +6,7 @@ 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.SagaChapter; import mage.constants.SubType; import mage.filter.FilterCard; @@ -40,7 +41,8 @@ public final class BalladOfTheBlackFlag extends CardImpl { // IV - Historic spells you cast this turn cost {2} less to cast. sagaAbility.addChapterEffect( this, SagaChapter.CHAPTER_IV, - new SpellsCostReductionControllerEffect(filter, 2) + new SpellsCostReductionControllerEffect(filter, 2).setDuration(Duration.EndOfTurn) + .setText("historic spells you cast this turn cost {2} less to cast") ); this.addAbility(sagaAbility); diff --git a/Mage.Sets/src/mage/cards/b/BalustradeWurm.java b/Mage.Sets/src/mage/cards/b/BalustradeWurm.java index e81434332fb..f25e700c470 100644 --- a/Mage.Sets/src/mage/cards/b/BalustradeWurm.java +++ b/Mage.Sets/src/mage/cards/b/BalustradeWurm.java @@ -41,8 +41,8 @@ public final class BalustradeWurm extends CardImpl { this.addAbility(new ActivateIfConditionActivatedAbility( Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldWithCounterEffect(CounterType.FINALITY.createInstance(), false), - new ManaCostsImpl<>("{2}{G}{G}"), DeliriumCondition.instance, TimingRule.SORCERY - ).setAbilityWord(AbilityWord.DELIRIUM).addHint(CardTypesInGraveyardCount.YOU.getHint())); + new ManaCostsImpl<>("{2}{G}{G}"), DeliriumCondition.instance + ).setTiming(TimingRule.SORCERY).setAbilityWord(AbilityWord.DELIRIUM).addHint(CardTypesInGraveyardCount.YOU.getHint())); } private BalustradeWurm(final BalustradeWurm card) { diff --git a/Mage.Sets/src/mage/cards/b/Banshee.java b/Mage.Sets/src/mage/cards/b/Banshee.java index 0f3c320bf73..e37dd596e2b 100644 --- a/Mage.Sets/src/mage/cards/b/Banshee.java +++ b/Mage.Sets/src/mage/cards/b/Banshee.java @@ -1,23 +1,23 @@ package mage.cards.b; -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.costs.common.TapSourceCost; -import mage.abilities.dynamicvalue.common.HalfValue; +import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.dynamicvalue.common.GetXValue; +import mage.abilities.dynamicvalue.common.HalfValue; import mage.abilities.effects.common.DamageControllerEffect; 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.target.common.TargetAnyTarget; +import java.util.UUID; + /** * * @author L_J @@ -31,7 +31,7 @@ public final class Banshee extends CardImpl { this.toughness = new MageInt(1); // {X}, {T}: Banshee deals half X damage, rounded down, to any target, and half X damage, rounded up, to you. - Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(new HalfValue(GetXValue.instance, false)).setText("Banshee deals half X damage, rounded down, to any target,"), new ManaCostsImpl<>("{X}")); + Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(new HalfValue(GetXValue.instance, false)).setText("{this} deals half X damage, rounded down, to any target,"), new ManaCostsImpl<>("{X}")); ability.addCost(new TapSourceCost()); ability.addEffect(new DamageControllerEffect(new HalfValue(GetXValue.instance, true)).setText(" and half X damage, rounded up, to you")); ability.addTarget(new TargetAnyTarget()); diff --git a/Mage.Sets/src/mage/cards/b/BaradDur.java b/Mage.Sets/src/mage/cards/b/BaradDur.java index 18328b28d58..d51f2572517 100644 --- a/Mage.Sets/src/mage/cards/b/BaradDur.java +++ b/Mage.Sets/src/mage/cards/b/BaradDur.java @@ -9,13 +9,13 @@ import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.dynamicvalue.common.GetXValue; import mage.abilities.effects.keyword.AmassEffect; +import mage.abilities.hint.common.MorbidHint; import mage.abilities.mana.BlackManaAbility; 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.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; @@ -47,13 +47,11 @@ public final class BaradDur extends CardImpl { // {X}{X}{B}, {T}: Amass Orcs X. Activate only if a creature died this turn. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new AmassEffect(GetXValue.instance, SubType.ORC, false), - new ManaCostsImpl<>("{X}{X}{B}"), - MorbidCondition.instance + new ManaCostsImpl<>("{X}{X}{B}"), MorbidCondition.instance ); ability.addCost(new TapSourceCost()); - this.addAbility(ability); + this.addAbility(ability.addHint(MorbidHint.instance)); } private BaradDur(final BaradDur card) { diff --git a/Mage.Sets/src/mage/cards/b/BarbarianRing.java b/Mage.Sets/src/mage/cards/b/BarbarianRing.java index bc645427ae1..8b6de7af953 100644 --- a/Mage.Sets/src/mage/cards/b/BarbarianRing.java +++ b/Mage.Sets/src/mage/cards/b/BarbarianRing.java @@ -5,7 +5,7 @@ import mage.abilities.condition.common.ThresholdCondition; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DamageControllerEffect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.mana.RedManaAbility; @@ -31,7 +31,7 @@ public final class BarbarianRing extends CardImpl { this.addAbility(redManaAbility); // Threshold - {R}, {T}, Sacrifice Barbarian Ring: Barbarian Ring deals 2 damage to any target. Activate this ability only if seven or more cards are in your graveyard. - Ability thresholdAbility = new ConditionalActivatedAbility( + Ability thresholdAbility = new ActivateIfConditionActivatedAbility( new DamageTargetEffect(2, "it"), new ManaCostsImpl<>("{R}"), ThresholdCondition.instance ); diff --git a/Mage.Sets/src/mage/cards/b/BaronSengir.java b/Mage.Sets/src/mage/cards/b/BaronSengir.java index 3ee91c88308..65dab278ccc 100644 --- a/Mage.Sets/src/mage/cards/b/BaronSengir.java +++ b/Mage.Sets/src/mage/cards/b/BaronSengir.java @@ -17,6 +17,7 @@ import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -48,7 +49,7 @@ public final class BaronSengir extends CardImpl { // {tap}: Regenerate another target Vampire. Ability ability = new SimpleActivatedAbility(new RegenerateTargetEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/BarrinTolarianArchmage.java b/Mage.Sets/src/mage/cards/b/BarrinTolarianArchmage.java index e18e185f475..c998c308c4a 100644 --- a/Mage.Sets/src/mage/cards/b/BarrinTolarianArchmage.java +++ b/Mage.Sets/src/mage/cards/b/BarrinTolarianArchmage.java @@ -15,7 +15,7 @@ import mage.filter.predicate.mageobject.AnotherPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; -import mage.target.common.TargetCreatureOrPlaneswalker; +import mage.target.TargetPermanent; import mage.watchers.Watcher; import java.util.HashSet; @@ -45,7 +45,7 @@ public final class BarrinTolarianArchmage extends CardImpl { // 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 TargetCreatureOrPlaneswalker(0, 1, filter, false)); + ability.addTarget(new TargetPermanent(0, 1, filter)); 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. diff --git a/Mage.Sets/src/mage/cards/b/BattleOfHooverDam.java b/Mage.Sets/src/mage/cards/b/BattleOfHooverDam.java index b8e39e72ee1..10b56ed7e5e 100644 --- a/Mage.Sets/src/mage/cards/b/BattleOfHooverDam.java +++ b/Mage.Sets/src/mage/cards/b/BattleOfHooverDam.java @@ -29,7 +29,7 @@ import java.util.UUID; */ public final class BattleOfHooverDam extends CardImpl { - private static final FilterCard filter = new FilterCreatureCard(); + private static final FilterCard filter = new FilterCreatureCard("creature card with mana value 3 or less from your graveyard"); static { filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 4)); diff --git a/Mage.Sets/src/mage/cards/b/BattleScreech.java b/Mage.Sets/src/mage/cards/b/BattleScreech.java index feb673697ce..5e3273f9b47 100644 --- a/Mage.Sets/src/mage/cards/b/BattleScreech.java +++ b/Mage.Sets/src/mage/cards/b/BattleScreech.java @@ -1,7 +1,5 @@ - package mage.cards.b; -import java.util.UUID; import mage.ObjectColor; import mage.abilities.costs.common.TapTargetCost; import mage.abilities.effects.common.CreateTokenEffect; @@ -9,15 +7,15 @@ import mage.abilities.keyword.FlashbackAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.TimingRule; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.permanent.TappedPredicate; import mage.game.permanent.token.BirdToken; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class BattleScreech extends CardImpl { @@ -30,14 +28,13 @@ public final class BattleScreech extends CardImpl { } public BattleScreech(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{W}{W}"); - + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{W}{W}"); // Create two 1/1 white Bird creature tokens with flying. this.getSpellAbility().addEffect(new CreateTokenEffect(new BirdToken(), 2)); // Flashback-Tap three untapped white creatures you control. - this.addAbility(new FlashbackAbility(this, new TapTargetCost(new TargetControlledCreaturePermanent(3,3, filter, true)))); + this.addAbility(new FlashbackAbility(this, new TapTargetCost(new TargetControlledPermanent(3, filter)))); } private BattleScreech(final BattleScreech card) { diff --git a/Mage.Sets/src/mage/cards/b/BeaconBehemoth.java b/Mage.Sets/src/mage/cards/b/BeaconBehemoth.java index 800b4d308b5..83fc438b83a 100644 --- a/Mage.Sets/src/mage/cards/b/BeaconBehemoth.java +++ b/Mage.Sets/src/mage/cards/b/BeaconBehemoth.java @@ -14,6 +14,7 @@ import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -36,7 +37,7 @@ public final class BeaconBehemoth extends CardImpl { this.toughness = new MageInt(3); Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(VigilanceAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{1}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/BelakorTheDarkMaster.java b/Mage.Sets/src/mage/cards/b/BelakorTheDarkMaster.java index a4c07480b7a..e0b2171298d 100644 --- a/Mage.Sets/src/mage/cards/b/BelakorTheDarkMaster.java +++ b/Mage.Sets/src/mage/cards/b/BelakorTheDarkMaster.java @@ -56,7 +56,7 @@ public final class BelakorTheDarkMaster extends CardImpl { // Prince of Chaos -- When Be'lakor, the Dark Master enters the battlefield, you draw X cards and you lose X life, where X is the number of Demons you control. Ability ability = new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(xValue).setText("you draw X cards")); - ability.addEffect(new LoseLifeSourceControllerEffect(xValue).concatBy("and")); + ability.addEffect(new LoseLifeSourceControllerEffect(xValue).setText("and you lose X life, where X is the number of Demons you control")); this.addAbility(ability.withFlavorWord("Prince of Chaos").addHint(hint)); // Lord of Torment -- Whenever another Demon you control enters, it deals damage equal to its power to any target. diff --git a/Mage.Sets/src/mage/cards/b/BenalishMissionary.java b/Mage.Sets/src/mage/cards/b/BenalishMissionary.java index e98cd1183e2..6b86c406e3e 100644 --- a/Mage.Sets/src/mage/cards/b/BenalishMissionary.java +++ b/Mage.Sets/src/mage/cards/b/BenalishMissionary.java @@ -16,6 +16,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.BlockedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -39,7 +40,7 @@ public final class BenalishMissionary extends CardImpl { // {1}{W}, {tap}: Prevent all combat damage that would be dealt by target blocked creature this turn. Ability ability = new SimpleActivatedAbility(new PreventDamageByTargetEffect(Duration.EndOfTurn, true), new ManaCostsImpl<>("{1}{W}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/BenthicAnomaly.java b/Mage.Sets/src/mage/cards/b/BenthicAnomaly.java index cb20790df48..d802d095be0 100644 --- a/Mage.Sets/src/mage/cards/b/BenthicAnomaly.java +++ b/Mage.Sets/src/mage/cards/b/BenthicAnomaly.java @@ -1,7 +1,6 @@ package mage.cards.b; import mage.MageInt; -import mage.MageItem; import mage.MageObject; import mage.ObjectColor; import mage.abilities.Ability; @@ -16,9 +15,8 @@ import mage.constants.Outcome; import mage.constants.SubType; import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.filter.predicate.permanent.PermanentIdPredicate; +import mage.filter.predicate.permanent.PermanentReferenceInCollectionPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -28,7 +26,6 @@ import mage.util.RandomUtil; import java.util.HashSet; import java.util.Set; import java.util.UUID; -import java.util.stream.Collectors; /** * @author TheElk801 @@ -114,13 +111,7 @@ class BenthicAnomalyEffect extends OneShotEffect { break; default: FilterPermanent filter = new FilterPermanent("a creature to create a copy of"); - filter.add(Predicates.or( - permanents - .stream() - .map(MageItem::getId) - .map(PermanentIdPredicate::new) - .collect(Collectors.toSet()) - )); + filter.add(new PermanentReferenceInCollectionPredicate(permanents, game)); TargetPermanent target = new TargetPermanent(filter); target.withNotTarget(true); player.choose(outcome, target, source, game); diff --git a/Mage.Sets/src/mage/cards/b/BessieTheDoctorsRoadster.java b/Mage.Sets/src/mage/cards/b/BessieTheDoctorsRoadster.java index e4d53e394d4..54742663dde 100644 --- a/Mage.Sets/src/mage/cards/b/BessieTheDoctorsRoadster.java +++ b/Mage.Sets/src/mage/cards/b/BessieTheDoctorsRoadster.java @@ -13,6 +13,7 @@ import mage.constants.SubType; import mage.constants.SuperType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -42,7 +43,7 @@ public final class BessieTheDoctorsRoadster extends CardImpl { // Whenever Bessie attacks, another target legendary creature can't be blocked this turn. Ability ability = new AttacksTriggeredAbility(new CantBeBlockedTargetEffect()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // Crew 2 diff --git a/Mage.Sets/src/mage/cards/b/BetorAncestorsVoice.java b/Mage.Sets/src/mage/cards/b/BetorAncestorsVoice.java index 88e1cac8d2a..fece40d434f 100644 --- a/Mage.Sets/src/mage/cards/b/BetorAncestorsVoice.java +++ b/Mage.Sets/src/mage/cards/b/BetorAncestorsVoice.java @@ -1,6 +1,5 @@ package mage.cards.b; -import java.util.UUID; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; @@ -8,27 +7,28 @@ import mage.abilities.dynamicvalue.common.ControllerGainedLifeCount; import mage.abilities.dynamicvalue.common.ControllerLostLifeCount; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; -import mage.constants.SubType; -import mage.constants.SuperType; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.LifelinkAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.counters.CounterType; import mage.filter.FilterCard; import mage.filter.StaticFilters; import mage.filter.predicate.ObjectSourcePlayer; import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; +import mage.target.TargetPermanent; import mage.target.common.TargetCardInGraveyard; -import mage.target.common.TargetControlledCreaturePermanent; import mage.target.targetpointer.SecondTargetPointer; import mage.watchers.common.PlayerGainedLifeWatcher; +import java.util.UUID; + /** - * * @author Grath */ public final class BetorAncestorsVoice extends CardImpl { @@ -43,7 +43,7 @@ public final class BetorAncestorsVoice extends CardImpl { public BetorAncestorsVoice(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{B}{G}"); - + this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.SPIRIT); this.subtype.add(SubType.DRAGON); @@ -64,7 +64,7 @@ public final class BetorAncestorsVoice extends CardImpl { .setText("put a number of +1/+1 counters on up to one other target creature you " + "control equal to the amount of life you gained this turn.") ); - ability.addTarget(new TargetControlledCreaturePermanent(0, 1, StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL, false)); + ability.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); ability.addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect().setTargetPointer(new SecondTargetPointer()) .setText("Return up to one target creature card with mana value less than or equal to the amount of " + "life you lost this turn from your graveyard to the battlefield.")); @@ -96,4 +96,4 @@ enum BetorPredicate implements ObjectSourcePlayerPredicate { public String toString() { return "mana value less than or equal to the amount of life you lost this turn"; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/b/Betray.java b/Mage.Sets/src/mage/cards/b/Betray.java index 3043c4c4709..b89dc0cb507 100644 --- a/Mage.Sets/src/mage/cards/b/Betray.java +++ b/Mage.Sets/src/mage/cards/b/Betray.java @@ -10,7 +10,7 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -18,13 +18,13 @@ import java.util.UUID; * @author Merlingilb */ public class Betray extends CardImpl { + public Betray(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}"); //Target creature an opponent controls deals damage to its controller equal to that creature's power. this.getSpellAbility().addEffect(new BetrayEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(1, 1, - StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE, false)); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); } private Betray(final Betray card) { diff --git a/Mage.Sets/src/mage/cards/b/Betrayal.java b/Mage.Sets/src/mage/cards/b/Betrayal.java index 7ad39a0f421..3daefdac019 100644 --- a/Mage.Sets/src/mage/cards/b/Betrayal.java +++ b/Mage.Sets/src/mage/cards/b/Betrayal.java @@ -16,6 +16,8 @@ import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * @author LoneFox */ @@ -26,7 +28,7 @@ public final class Betrayal extends CardImpl { this.subtype.add(SubType.AURA); // Enchant creature an opponent controls - TargetPermanent auraTarget = new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE); + TargetPermanent auraTarget = new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); Ability ability = new EnchantAbility(auraTarget); diff --git a/Mage.Sets/src/mage/cards/b/BetrayalAtTheVault.java b/Mage.Sets/src/mage/cards/b/BetrayalAtTheVault.java index 206c7c0f4ee..764f21e7d54 100644 --- a/Mage.Sets/src/mage/cards/b/BetrayalAtTheVault.java +++ b/Mage.Sets/src/mage/cards/b/BetrayalAtTheVault.java @@ -11,8 +11,8 @@ import mage.filter.predicate.other.AnotherTargetPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; import java.util.List; import java.util.Objects; @@ -35,7 +35,7 @@ public final class BetrayalAtTheVault extends CardImpl { // Target creature you control deals damage equal to its power to each of two other target creatures. this.getSpellAbility().addEffect(new BetrayalAtTheVaultEffect()); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent().setTargetTag(1)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(2, 2, filter, false).setTargetTag(2)); + this.getSpellAbility().addTarget(new TargetPermanent(2, filter).setTargetTag(2)); } private BetrayalAtTheVault(final BetrayalAtTheVault card) { @@ -81,4 +81,4 @@ class BetrayalAtTheVaultEffect extends OneShotEffect { .forEach(p -> p.damage(creature.getPower().getValue(), creature.getId(), source, game)); return true; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/b/Bifurcate.java b/Mage.Sets/src/mage/cards/b/Bifurcate.java index da513140c6e..51c2b09685b 100644 --- a/Mage.Sets/src/mage/cards/b/Bifurcate.java +++ b/Mage.Sets/src/mage/cards/b/Bifurcate.java @@ -15,6 +15,7 @@ import mage.filter.predicate.mageobject.NamePredicate; import mage.filter.predicate.permanent.TokenPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetCreaturePermanent; @@ -35,7 +36,7 @@ public final class Bifurcate extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}"); // Search your library for a permanent card with the same name as target nontoken creature and put that card onto the battlefield. Then shuffle your library. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new BifurcateEffect()); } diff --git a/Mage.Sets/src/mage/cards/b/BigGameHunter.java b/Mage.Sets/src/mage/cards/b/BigGameHunter.java index 8967f907e69..26544e30cc1 100644 --- a/Mage.Sets/src/mage/cards/b/BigGameHunter.java +++ b/Mage.Sets/src/mage/cards/b/BigGameHunter.java @@ -15,6 +15,7 @@ import mage.constants.ComparisonType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,7 +39,7 @@ public final class BigGameHunter extends CardImpl { // When Big Game Hunter enters the battlefield, destroy target creature with power 4 or greater. It can't be regenerated. Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(true)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // Madness {B} this.addAbility(new MadnessAbility(new ManaCostsImpl<>("{B}"))); diff --git a/Mage.Sets/src/mage/cards/b/BilboBirthdayCelebrant.java b/Mage.Sets/src/mage/cards/b/BilboBirthdayCelebrant.java index 036502e3560..943349de552 100644 --- a/Mage.Sets/src/mage/cards/b/BilboBirthdayCelebrant.java +++ b/Mage.Sets/src/mage/cards/b/BilboBirthdayCelebrant.java @@ -7,7 +7,7 @@ import mage.abilities.condition.Condition; import mage.abilities.costs.common.ExileSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.replacement.GainPlusOneLifeReplacementEffect; import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; import mage.cards.CardImpl; @@ -39,7 +39,7 @@ public final class BilboBirthdayCelebrant extends CardImpl { this.addAbility(new SimpleStaticAbility(new GainPlusOneLifeReplacementEffect())); // {2}{W}{B}{G}, {T}, Exile Bilbo, Birthday Celebrant: Search your library for any number of creature cards, put them onto the battlefield, then shuffle. Activate only if you have 111 or more life. - Ability ability = new ConditionalActivatedAbility(new SearchLibraryPutInPlayEffect( + Ability ability = new ActivateIfConditionActivatedAbility(new SearchLibraryPutInPlayEffect( new TargetCardInLibrary(0, Integer.MAX_VALUE, StaticFilters.FILTER_CARD_CREATURES) ), new ManaCostsImpl<>("{2}{W}{B}{G}"), BilboBirthdayCelebrantCondition.instance); ability.addCost(new TapSourceCost()); @@ -69,4 +69,4 @@ enum BilboBirthdayCelebrantCondition implements Condition { public String toString() { return "you have 111 or more life"; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/b/Bioshift.java b/Mage.Sets/src/mage/cards/b/Bioshift.java index b9946b01b63..6a0b81e28c0 100644 --- a/Mage.Sets/src/mage/cards/b/Bioshift.java +++ b/Mage.Sets/src/mage/cards/b/Bioshift.java @@ -1,7 +1,5 @@ - package mage.cards.b; -import java.util.UUID; import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; @@ -10,6 +8,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; import mage.counters.CounterType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.ObjectSourcePlayer; import mage.filter.predicate.ObjectSourcePlayerPredicate; @@ -18,34 +17,33 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.stack.StackObject; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class Bioshift extends CardImpl { - public Bioshift(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{G/U}"); + private static final FilterPermanent filter = new FilterCreaturePermanent("another target creature with the same controller"); - // Move any number of +1/+1 counters from target creature onto another target creature with the same controller. - getSpellAbility().addEffect(new MoveCounterFromTargetToTargetEffect()); - - TargetCreaturePermanent target = new TargetCreaturePermanent( - new FilterCreaturePermanent("creature (you take counters from)")); - target.setTargetTag(1); - this.getSpellAbility().addTarget(target); - - FilterCreaturePermanent filter = new FilterCreaturePermanent( - "another target creature with the same controller (counters go to)"); + static { filter.add(new AnotherTargetPredicate(2)); filter.add(new SameControllerPredicate()); - TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter); - target2.setTargetTag(2); - this.getSpellAbility().addTarget(target2); } - + + public Bioshift(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{G/U}"); + + // Move any number of +1/+1 counters from target creature onto another target creature with the same controller. + this.getSpellAbility().addEffect(new MoveCounterFromTargetToTargetEffect()); + + this.getSpellAbility().addTarget(new TargetCreaturePermanent().withChooseHint("to take counters from").setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPermanent(filter).withChooseHint("to put counter on").setTargetTag(2)); + } + private Bioshift(final Bioshift card) { super(card); @@ -107,7 +105,7 @@ class SameControllerPredicate implements ObjectSourcePlayerPredicate { StackObject source = game.getStack().getStackObject(input.getSourceId()); if (source != null) { if (source.getStackAbility().getTargets().isEmpty() - || source.getStackAbility().getTargets().get(0).getTargets().isEmpty()) { + || source.getStackAbility().getTargets().get(0).getTargets().isEmpty()) { return true; } Permanent firstTarget = game.getPermanent( @@ -124,5 +122,5 @@ class SameControllerPredicate implements ObjectSourcePlayerPredicate { public String toString() { return "Target with the same controller"; } - + } diff --git a/Mage.Sets/src/mage/cards/b/BirchloreRangers.java b/Mage.Sets/src/mage/cards/b/BirchloreRangers.java index 0ef117efbe6..b50024b3bde 100644 --- a/Mage.Sets/src/mage/cards/b/BirchloreRangers.java +++ b/Mage.Sets/src/mage/cards/b/BirchloreRangers.java @@ -1,8 +1,5 @@ package mage.cards.b; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; import mage.MageInt; import mage.Mana; import mage.abilities.Ability; @@ -15,19 +12,27 @@ 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.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; /** - * * @author LevelX2 */ public final class BirchloreRangers extends CardImpl { + private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.ELF, "untapped Elves you control"); + + static { + filter.add(TappedPredicate.UNTAPPED); + } + public BirchloreRangers(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}"); this.subtype.add(SubType.ELF, SubType.DRUID, SubType.RANGER); @@ -36,14 +41,11 @@ public final class BirchloreRangers extends CardImpl { this.toughness = new MageInt(1); // Tap two untapped Elves you control: Add one mana of any color. - FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Elves you control"); - filter.add(TappedPredicate.UNTAPPED); - filter.add(SubType.ELF.getPredicate()); this.addAbility(new SimpleManaAbility( - Zone.BATTLEFIELD, new BirchloreRangersManaEffect(filter), - new TapTargetCost(new TargetControlledCreaturePermanent(2, 2, filter, false)))); - + new TapTargetCost(new TargetControlledPermanent(2, filter)) + )); + // Morph {G} this.addAbility(new MorphAbility(this, new ManaCostsImpl<>("{G}"))); } @@ -90,4 +92,4 @@ class BirchloreRangersManaEffect extends AddManaOfAnyColorEffect { return super.getNetMana(game, source); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/b/BishopOfBinding.java b/Mage.Sets/src/mage/cards/b/BishopOfBinding.java index 3d7086c4845..cdfe4492213 100644 --- a/Mage.Sets/src/mage/cards/b/BishopOfBinding.java +++ b/Mage.Sets/src/mage/cards/b/BishopOfBinding.java @@ -23,9 +23,12 @@ import mage.filter.common.FilterCreaturePermanent; import mage.game.ExileZone; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.util.CardUtil; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -42,12 +45,12 @@ public final class BishopOfBinding extends CardImpl { // When Bishop of Binding enters the battlefield, exile target creature an opponent controls until Bishop of Binding leaves the battlefield. Ability ability = new EntersBattlefieldTriggeredAbility(new BishopOfBindingExileEffect()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); // Whenever Bishop of Binding attacks, target Vampire gets +X/+X until end of turn, where X is the power of the exiled card. ability = new AttacksTriggeredAbility(new BoostTargetEffect(BishopOfBindingValue.instance, BishopOfBindingValue.instance, Duration.EndOfTurn)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/BiteDownOnCrime.java b/Mage.Sets/src/mage/cards/b/BiteDownOnCrime.java index b705cba0318..067cabe2f2a 100644 --- a/Mage.Sets/src/mage/cards/b/BiteDownOnCrime.java +++ b/Mage.Sets/src/mage/cards/b/BiteDownOnCrime.java @@ -14,12 +14,15 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.filter.StaticFilters; import mage.game.Game; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import mage.util.CardUtil; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * * @author notgreat @@ -40,7 +43,7 @@ public final class BiteDownOnCrime extends CardImpl { // It deals damage equal to its power to target creature you don't control. this.getSpellAbility().addEffect(new DamageWithPowerFromOneToAnotherTargetEffect("It")); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); } private BiteDownOnCrime(final BiteDownOnCrime card) { diff --git a/Mage.Sets/src/mage/cards/b/BlackCarriage.java b/Mage.Sets/src/mage/cards/b/BlackCarriage.java index 78d9afde558..661c507e0ca 100644 --- a/Mage.Sets/src/mage/cards/b/BlackCarriage.java +++ b/Mage.Sets/src/mage/cards/b/BlackCarriage.java @@ -1,26 +1,22 @@ - package mage.cards.b; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.SacrificeTargetCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DontUntapInControllersUntapStepSourceEffect; import mage.abilities.effects.common.UntapSourceEffect; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.PhaseStep; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.StaticFilters; -import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; /** - * * @author fireshoes */ public final class BlackCarriage extends CardImpl { @@ -38,9 +34,10 @@ public final class BlackCarriage extends CardImpl { this.addAbility(new SimpleStaticAbility(new DontUntapInControllersUntapStepSourceEffect())); // Sacrifice a creature: Untap Black Carriage. Activate this ability only during your upkeep. - this.addAbility(new ConditionalActivatedAbility(Zone.BATTLEFIELD, + this.addAbility(new ActivateIfConditionActivatedAbility( new UntapSourceEffect(), new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_CREATURE), - new IsStepCondition(PhaseStep.UPKEEP), "Sacrifice a creature: Untap {this}. Activate only during your upkeep.")); + IsStepCondition.getMyUpkeep() + )); } private BlackCarriage(final BlackCarriage card) { diff --git a/Mage.Sets/src/mage/cards/b/BlackMarket.java b/Mage.Sets/src/mage/cards/b/BlackMarket.java index 044d39de677..e458e91e67a 100644 --- a/Mage.Sets/src/mage/cards/b/BlackMarket.java +++ b/Mage.Sets/src/mage/cards/b/BlackMarket.java @@ -1,13 +1,12 @@ package mage.cards.b; -import java.util.UUID; import mage.Mana; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfFirstMainTriggeredAbility; import mage.abilities.common.DiesCreatureTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.triggers.BeginningOfFirstMainTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -17,6 +16,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import java.util.UUID; + /** * * @author markedagain @@ -47,7 +48,7 @@ class BlackMarketEffect extends OneShotEffect { BlackMarketEffect() { super(Outcome.PutManaInPool); - this.staticText = "add {B} for each charge counter on Black Market"; + this.staticText = "add {B} for each charge counter on {this}"; } private BlackMarketEffect(final BlackMarketEffect effect) { diff --git a/Mage.Sets/src/mage/cards/b/BlackOakOfOdunos.java b/Mage.Sets/src/mage/cards/b/BlackOakOfOdunos.java index ba97419e572..4a52644b3a5 100644 --- a/Mage.Sets/src/mage/cards/b/BlackOakOfOdunos.java +++ b/Mage.Sets/src/mage/cards/b/BlackOakOfOdunos.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; @@ -14,27 +12,28 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; + +import java.util.UUID; /** - * * @author Quercitron */ public final class BlackOakOfOdunos extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another untapped creature you control"); + private static final FilterControlledPermanent filter = new FilterControlledCreaturePermanent("another untapped creature you control"); static { filter.add(AnotherPredicate.instance); filter.add(TappedPredicate.UNTAPPED); } - + public BlackOakOfOdunos(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.ZOMBIE, SubType.TREEFOLK); this.power = new MageInt(0); @@ -42,9 +41,12 @@ public final class BlackOakOfOdunos extends CardImpl { // Defender this.addAbility(DefenderAbility.getInstance()); + // {B}, Tap another untapped creature you control: Black Oak of Odunos gets +1/+1 until end of turn. - Ability ability = new SimpleActivatedAbility(new BoostSourceEffect(1, 1, Duration.EndOfTurn), new ManaCostsImpl<>("{B}")); - ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, true))); + Ability ability = new SimpleActivatedAbility( + new BoostSourceEffect(1, 1, Duration.EndOfTurn), new ManaCostsImpl<>("{B}") + ); + ability.addCost(new TapTargetCost(new TargetControlledPermanent(filter))); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/BlackbladeReforged.java b/Mage.Sets/src/mage/cards/b/BlackbladeReforged.java index 4cf85be7bfe..9321dafa470 100644 --- a/Mage.Sets/src/mage/cards/b/BlackbladeReforged.java +++ b/Mage.Sets/src/mage/cards/b/BlackbladeReforged.java @@ -9,12 +9,15 @@ import mage.abilities.hint.ValueHint; import mage.abilities.keyword.EquipAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; -import mage.target.common.TargetControlledCreaturePermanent; /** * @author Rystan @@ -39,7 +42,7 @@ public final class BlackbladeReforged extends CardImpl { this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(count, count)).addHint(new ValueHint("Lands you control", count))); // Equip legendary creature (3) - this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(3), new TargetControlledCreaturePermanent(filter), false)); + this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(3), new TargetPermanent(filter), false)); // Equip {7} this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(7), false)); diff --git a/Mage.Sets/src/mage/cards/b/BlacklanceParagon.java b/Mage.Sets/src/mage/cards/b/BlacklanceParagon.java index 9f488f29c39..cbf3d169236 100644 --- a/Mage.Sets/src/mage/cards/b/BlacklanceParagon.java +++ b/Mage.Sets/src/mage/cards/b/BlacklanceParagon.java @@ -16,6 +16,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -45,7 +46,7 @@ public final class BlacklanceParagon extends CardImpl { effect = new GainAbilityTargetEffect(LifelinkAbility.getInstance(), Duration.EndOfTurn); effect.setText("and lifelink until end of turn"); ability.addEffect(effect); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/BladegraftAspirant.java b/Mage.Sets/src/mage/cards/b/BladegraftAspirant.java index 2517e1981b6..fce3464a4dc 100644 --- a/Mage.Sets/src/mage/cards/b/BladegraftAspirant.java +++ b/Mage.Sets/src/mage/cards/b/BladegraftAspirant.java @@ -62,7 +62,7 @@ public final class BladegraftAspirant extends CardImpl { class BladegraftAspirantCostReductionEffect extends CostModificationEffectImpl { - private static final String effectText = "Activated abilities of Equipment you control that target Bladegraft Aspirant cost {1} less to activate."; + private static final String effectText = "Activated abilities of Equipment you control that target {this} cost {1} less to activate."; BladegraftAspirantCostReductionEffect() { super(Duration.Custom, Outcome.Benefit, CostModificationType.REDUCE_COST); diff --git a/Mage.Sets/src/mage/cards/b/BladegriffPrototype.java b/Mage.Sets/src/mage/cards/b/BladegriffPrototype.java index 64655b2405f..a08f871db1a 100644 --- a/Mage.Sets/src/mage/cards/b/BladegriffPrototype.java +++ b/Mage.Sets/src/mage/cards/b/BladegriffPrototype.java @@ -1,32 +1,37 @@ package mage.cards.b; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; 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.FilterNonlandPermanent; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.permanent.ControllerIdPredicate; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.game.Controllable; import mage.game.Game; -import mage.game.events.DamagedEvent; -import mage.game.events.GameEvent; -import mage.players.Player; +import mage.target.Target; import mage.target.TargetPermanent; +import mage.target.targetadjustment.GenericTargetAdjuster; +import mage.target.targetpointer.FirstTargetPointer; import java.util.UUID; -import java.util.stream.Collectors; /** * @author TheElk801 */ public final class BladegriffPrototype extends CardImpl { + private static final FilterNonlandPermanent filter = new FilterNonlandPermanent("nonland permanent of that player's choice that one of your opponents controls"); + + static { + filter.add(BladegriffSourceOpponentControlsPredicate.instance); + } + public BladegriffPrototype(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{5}"); @@ -38,7 +43,10 @@ public final class BladegriffPrototype extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Whenever Bladegriff Prototype deals combat damage to a player, destroy target nonland permanent of that player's choice that one of your opponents controls. - this.addAbility(new BladegriffPrototypeAbility()); + Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new DestroyTargetEffect(), false, true); + ability.addTarget(new TargetPermanent(filter)); + ability.setTargetAdjuster(new ThatPlayersChoiceTargetAdjuster()); + this.addAbility(ability); } private BladegriffPrototype(final BladegriffPrototype card) { @@ -51,54 +59,27 @@ public final class BladegriffPrototype extends CardImpl { } } -class BladegriffPrototypeAbility extends TriggeredAbilityImpl { - - BladegriffPrototypeAbility() { - super(Zone.BATTLEFIELD, new DestroyTargetEffect(), false); - } - - private BladegriffPrototypeAbility(final BladegriffPrototypeAbility ability) { - super(ability); - } +enum BladegriffSourceOpponentControlsPredicate implements ObjectSourcePlayerPredicate { + instance; @Override - public BladegriffPrototypeAbility copy() { - return new BladegriffPrototypeAbility(this); - } + public boolean apply(ObjectSourcePlayer input, Game game) { + Controllable object = input.getObject(); + UUID playerId = input.getSource().getControllerId(); - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - Player player = game.getPlayer(getControllerId()); - if (player == null - || !event.getSourceId().equals(this.sourceId) - || !((DamagedEvent) event).isCombatDamage()) { - return false; - } - FilterPermanent filter = new FilterNonlandPermanent( - "nonland permanent controlled by an opponent of " + player.getName() - ); - filter.add(Predicates.or( - game.getOpponents(getControllerId()) - .stream() - .map(ControllerIdPredicate::new) - .collect(Collectors.toSet()) - )); - TargetPermanent target = new TargetPermanent(filter); - target.setTargetController(event.getPlayerId()); - this.getTargets().clear(); - this.addTarget(target); - return true; - } - - @Override - public String getRule() { - return "Whenever {this} deals combat damage to a player, " + - "destroy target nonland permanent of that player's choice " + - "that one of your opponents controls."; + return !object.isControlledBy(playerId) + && game.getPlayer(playerId).hasOpponent(object.getControllerId(), game); + } +} + +class ThatPlayersChoiceTargetAdjuster extends GenericTargetAdjuster { + @Override + public void adjustTargets(Ability ability, Game game) { + UUID opponentId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability); + ability.getTargets().clear(); + ability.getAllEffects().setTargetPointer(new FirstTargetPointer()); + Target newTarget = blueprintTarget.copy(); + newTarget.setTargetController(opponentId); + ability.addTarget(newTarget); } } diff --git a/Mage.Sets/src/mage/cards/b/BlazeOfGlory.java b/Mage.Sets/src/mage/cards/b/BlazeOfGlory.java index b77aee8c7f5..ea41cf87049 100644 --- a/Mage.Sets/src/mage/cards/b/BlazeOfGlory.java +++ b/Mage.Sets/src/mage/cards/b/BlazeOfGlory.java @@ -14,6 +14,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.DefendingPlayerControlsNoSourcePredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -36,7 +37,7 @@ public final class BlazeOfGlory extends CardImpl { this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(TurnPhase.COMBAT, BeforeBlockersAreDeclaredCondition.instance)); // Target creature defending player controls can block any number of creatures this turn. It blocks each attacking creature this turn if able. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new CanBlockAdditionalCreatureTargetEffect(Duration.EndOfTurn, 0) .setText("target creature defending player controls can block any number of creatures this turn")); this.getSpellAbility().addEffect(new BlazeOfGloryRequirementEffect()); diff --git a/Mage.Sets/src/mage/cards/b/BlazingHope.java b/Mage.Sets/src/mage/cards/b/BlazingHope.java index da94b2584e6..4fc35abe721 100644 --- a/Mage.Sets/src/mage/cards/b/BlazingHope.java +++ b/Mage.Sets/src/mage/cards/b/BlazingHope.java @@ -11,7 +11,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -38,7 +38,7 @@ public final class BlazingHope extends CardImpl { } } -class BlazingHopeTarget extends TargetCreaturePermanent { +class BlazingHopeTarget extends TargetPermanent { public BlazingHopeTarget() { super(new FilterCreaturePermanent("creature with power greater than or equal to your life total")); diff --git a/Mage.Sets/src/mage/cards/b/BlessedAlliance.java b/Mage.Sets/src/mage/cards/b/BlessedAlliance.java index 1edb08eed24..3c99a3b6cad 100644 --- a/Mage.Sets/src/mage/cards/b/BlessedAlliance.java +++ b/Mage.Sets/src/mage/cards/b/BlessedAlliance.java @@ -2,7 +2,6 @@ package mage.cards.b; import mage.abilities.Mode; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.GainLifeTargetEffect; import mage.abilities.effects.common.SacrificeEffect; import mage.abilities.effects.common.UntapTargetEffect; @@ -10,10 +9,7 @@ import mage.abilities.keyword.EscalateAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.TargetController; -import mage.filter.FilterPlayer; import mage.filter.common.FilterAttackingCreature; -import mage.filter.common.FilterCreaturePermanent; import mage.target.TargetPlayer; import mage.target.common.TargetCreaturePermanent; @@ -24,14 +20,6 @@ import java.util.UUID; */ public final class BlessedAlliance extends CardImpl { - private static final FilterPlayer filterSacrifice = new FilterPlayer("opponent to sacrifice an attacking creature"); - private static final FilterCreaturePermanent filterCreature = new FilterCreaturePermanent("creatures to untap"); - private static final FilterPlayer filterGainLife = new FilterPlayer("player to gain life"); - - static { - filterSacrifice.add(TargetController.OPPONENT.getPlayerPredicate()); - } - public BlessedAlliance(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}"); @@ -43,21 +31,17 @@ public final class BlessedAlliance extends CardImpl { this.getSpellAbility().getModes().setMaxModes(3); // Target player gains 4 life. - Effect effect = new GainLifeTargetEffect(4); - effect.setText("Target player gains 4 life"); - this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetPlayer(1, 1, false, filterGainLife).withChooseHint("player gains 4 life")); + this.getSpellAbility().addEffect(new GainLifeTargetEffect(4)); + this.getSpellAbility().addTarget(new TargetPlayer().withChooseHint("player gains 4 life")); // Untap up to two target creatures. - effect = new UntapTargetEffect(); - effect.setText("Untap up to two target creatures"); - Mode mode = new Mode(effect); - mode.addTarget(new TargetCreaturePermanent(0, 2, filterCreature, false).withChooseHint("untap")); + Mode mode = new Mode(new UntapTargetEffect()); + mode.addTarget(new TargetCreaturePermanent(0, 2).withChooseHint("untap")); this.getSpellAbility().addMode(mode); // Target opponent sacrifices an attacking creature. mode = new Mode(new SacrificeEffect(new FilterAttackingCreature(), 1, "Target opponent")); - mode.addTarget(new TargetPlayer(1, 1, false, filterSacrifice).withChooseHint("sacrifices an attacking creature")); + mode.addTarget(new TargetPlayer().withChooseHint("sacrifices an attacking creature")); this.getSpellAbility().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/b/BlessedReincarnation.java b/Mage.Sets/src/mage/cards/b/BlessedReincarnation.java index de3561bb8c2..ae6a744003b 100644 --- a/Mage.Sets/src/mage/cards/b/BlessedReincarnation.java +++ b/Mage.Sets/src/mage/cards/b/BlessedReincarnation.java @@ -14,8 +14,11 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Library; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author fireshoes @@ -29,7 +32,7 @@ public final class BlessedReincarnation extends CardImpl { // That player reveals cards from the top of their library until a creature card is revealed. // The player puts that card onto the battlefield, then shuffles the rest into their library. this.getSpellAbility().addEffect(new BlessedReincarnationEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); // Rebound this.addAbility(new ReboundAbility()); diff --git a/Mage.Sets/src/mage/cards/b/BlindWithAnger.java b/Mage.Sets/src/mage/cards/b/BlindWithAnger.java index d9df645c333..59372af554c 100644 --- a/Mage.Sets/src/mage/cards/b/BlindWithAnger.java +++ b/Mage.Sets/src/mage/cards/b/BlindWithAnger.java @@ -14,6 +14,7 @@ import mage.constants.SubType; import mage.constants.SuperType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -34,7 +35,7 @@ public final class BlindWithAnger extends CardImpl { this.getSpellAbility().addEffect(new UntapTargetEffect().setText("Untap target nonlegendary creature")); this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.EndOfTurn).setText("and gain control of it until end of turn")); this.getSpellAbility().addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn).setText("It gains haste until end of turn.")); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private BlindWithAnger(final BlindWithAnger card) { diff --git a/Mage.Sets/src/mage/cards/b/BlisteringFirecat.java b/Mage.Sets/src/mage/cards/b/BlisteringFirecat.java index a614548fed7..e4b3d23da5e 100644 --- a/Mage.Sets/src/mage/cards/b/BlisteringFirecat.java +++ b/Mage.Sets/src/mage/cards/b/BlisteringFirecat.java @@ -1,28 +1,28 @@ package mage.cards.b; -import java.util.UUID; import mage.MageInt; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.MorphAbility; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.game.events.GameEvent; +import mage.constants.TargetController; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class BlisteringFirecat extends CardImpl { public BlisteringFirecat(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{R}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{R}{R}"); this.subtype.add(SubType.ELEMENTAL, SubType.CAT); this.power = new MageInt(7); @@ -30,10 +30,15 @@ public final class BlisteringFirecat extends CardImpl { // Trample this.addAbility(TrampleAbility.getInstance()); + // Haste this.addAbility(HasteAbility.getInstance()); + // At the beginning of the end step, sacrifice Blistering Firecat. - this.addAbility(new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new SacrificeSourceEffect())); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.NEXT, new SacrificeSourceEffect(), false + )); + // Morph {R}{R} this.addAbility(new MorphAbility(this, new ManaCostsImpl<>("{R}{R}"))); } diff --git a/Mage.Sets/src/mage/cards/b/BlizzardStrix.java b/Mage.Sets/src/mage/cards/b/BlizzardStrix.java index b412fd2f57f..f4b0f7f9fd5 100644 --- a/Mage.Sets/src/mage/cards/b/BlizzardStrix.java +++ b/Mage.Sets/src/mage/cards/b/BlizzardStrix.java @@ -52,7 +52,7 @@ public final class BlizzardStrix extends CardImpl { // When Blizzard Strix enters the battlefield, if you control another snow permanent, exile target permanent other than Blizzard Strix. Return that card to the battlefield under its owner's control at the beginning of the next end step. Ability ability = new EntersBattlefieldTriggeredAbility(new ExileReturnBattlefieldNextEndStepTargetEffect() .setText("exile target permanent other than {this}. Return that card to the " + - "battlefield under its owner's control at the beginning of the next end step")); + "battlefield under its owner's control at the beginning of the next end step")).withInterveningIf(condition); ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/BloatflySwarm.java b/Mage.Sets/src/mage/cards/b/BloatflySwarm.java index 2d8bd4db927..64c03583d53 100644 --- a/Mage.Sets/src/mage/cards/b/BloatflySwarm.java +++ b/Mage.Sets/src/mage/cards/b/BloatflySwarm.java @@ -59,7 +59,8 @@ class BloatflySwarmPreventionEffect extends PreventDamageAndRemoveCountersEffect BloatflySwarmPreventionEffect() { super(true, true, true); - staticText += ", then give each player a rad counter for each +1/+1 counter removed this way"; + staticText = "If damage would be dealt to {this} while it has a +1/+1 counter on it, prevent that damage, remove that many +1/+1 counters from it, " + + "then give each player a rad counter for each +1/+1 counter removed this way"; } private BloatflySwarmPreventionEffect(final BloatflySwarmPreventionEffect effect) { @@ -77,4 +78,4 @@ class BloatflySwarmPreventionEffect extends PreventDamageAndRemoveCountersEffect new AddCountersPlayersEffect(CounterType.RAD.createInstance(amountRemovedThisTime), TargetController.EACH_PLAYER) .apply(game, source); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/b/BloodFeud.java b/Mage.Sets/src/mage/cards/b/BloodFeud.java index d111a6aca6e..6f22087df5b 100644 --- a/Mage.Sets/src/mage/cards/b/BloodFeud.java +++ b/Mage.Sets/src/mage/cards/b/BloodFeud.java @@ -4,11 +4,13 @@ import mage.abilities.effects.common.FightTargetsEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2; + /** * @author intimidatingant */ @@ -19,13 +21,8 @@ public final class BloodFeud extends CardImpl { // Target creature fights another target creature. this.getSpellAbility().addEffect(new FightTargetsEffect()); - TargetCreaturePermanent target = new TargetCreaturePermanent(); - target.setTargetTag(1); - this.getSpellAbility().addTarget(target); - - TargetCreaturePermanent target2 = new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2); - target2.setTargetTag(2); - this.getSpellAbility().addTarget(target2); + this.getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_ANOTHER_CREATURE_TARGET_2).setTargetTag(2)); } private BloodFeud(final BloodFeud card) { diff --git a/Mage.Sets/src/mage/cards/b/BloodOperative.java b/Mage.Sets/src/mage/cards/b/BloodOperative.java index 15708ace750..cfa2b514498 100644 --- a/Mage.Sets/src/mage/cards/b/BloodOperative.java +++ b/Mage.Sets/src/mage/cards/b/BloodOperative.java @@ -1,6 +1,5 @@ package mage.cards.b; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -18,8 +17,9 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.target.common.TargetCardInGraveyard; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class BloodOperative extends CardImpl { @@ -42,7 +42,7 @@ public final class BloodOperative extends CardImpl { // Whenever you surveil, if Blood Operative is in your graveyard, you may pay 3 life. If you do, return Blood Operative to your hand. this.addAbility(new SurveilTriggeredAbility(Zone.GRAVEYARD, new DoIfCostPaid( - new ReturnSourceFromGraveyardToHandEffect().setText("return {this} to your hand"), new PayLifeCost(3) + new ReturnSourceFromGraveyardToHandEffect().setText("return this card to your hand"), new PayLifeCost(3) )).withInterveningIf(SourceInGraveyardCondition.instance)); } diff --git a/Mage.Sets/src/mage/cards/b/BloodchiefAscension.java b/Mage.Sets/src/mage/cards/b/BloodchiefAscension.java index a93045dbc35..d67884081cd 100644 --- a/Mage.Sets/src/mage/cards/b/BloodchiefAscension.java +++ b/Mage.Sets/src/mage/cards/b/BloodchiefAscension.java @@ -38,7 +38,7 @@ public final class BloodchiefAscension extends CardImpl { // Whenever a card is put into an opponent's graveyard from anywhere, if Bloodchief Ascension has three or more quest counters on it, you may have that player lose 2 life. If you do, you gain 2 life. Ability ability = new PutCardIntoGraveFromAnywhereAllTriggeredAbility( - new LoseLifeTargetEffect(2), true, StaticFilters.FILTER_CARD_A, + new LoseLifeTargetEffect(2).setText("have that player lose 2 life"), true, StaticFilters.FILTER_CARD_A, TargetController.OPPONENT, SetTargetPointer.PLAYER ).withInterveningIf(condition); ability.addEffect(new GainLifeEffect(2).concatBy("If you do,")); diff --git a/Mage.Sets/src/mage/cards/b/BloodcrazedHoplite.java b/Mage.Sets/src/mage/cards/b/BloodcrazedHoplite.java index c896e90e4b0..efa1b0069e5 100644 --- a/Mage.Sets/src/mage/cards/b/BloodcrazedHoplite.java +++ b/Mage.Sets/src/mage/cards/b/BloodcrazedHoplite.java @@ -17,8 +17,11 @@ import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -37,7 +40,7 @@ public final class BloodcrazedHoplite extends CardImpl { .withRuleTextReplacement(true)); // Whenever a +1/+1 counter is put on Bloodcrazed Hoplite, remove a +1/+1 counter from target creature an opponent controls. Ability ability = new BloodcrazedHopliteTriggeredAbility(); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/BloodgiftDemon.java b/Mage.Sets/src/mage/cards/b/BloodgiftDemon.java index 82d28154c8e..a98599644ed 100644 --- a/Mage.Sets/src/mage/cards/b/BloodgiftDemon.java +++ b/Mage.Sets/src/mage/cards/b/BloodgiftDemon.java @@ -1,40 +1,36 @@ - package mage.cards.b; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.OnEventTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DrawCardTargetEffect; import mage.abilities.effects.common.LoseLifeTargetEffect; import mage.abilities.keyword.FlyingAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.game.events.GameEvent.EventType; import mage.target.TargetPlayer; +import java.util.UUID; + /** - * * @author North */ public final class BloodgiftDemon extends CardImpl { public BloodgiftDemon(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(5); this.toughness = new MageInt(4); this.addAbility(FlyingAbility.getInstance()); + // At the beginning of your upkeep, target player draws a card and loses 1 life. - Ability ability = new OnEventTriggeredAbility(EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", new DrawCardTargetEffect(1), false); - Effect effect = new LoseLifeTargetEffect(1); - effect.setText("and loses 1 life"); - ability.addEffect(effect); + Ability ability = new BeginningOfUpkeepTriggeredAbility(new DrawCardTargetEffect(1)); + ability.addEffect(new LoseLifeTargetEffect(1).setText("and loses 1 life")); ability.addTarget(new TargetPlayer()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/BloodlineKeeper.java b/Mage.Sets/src/mage/cards/b/BloodlineKeeper.java index 32dd7d98314..8cc8653d882 100644 --- a/Mage.Sets/src/mage/cards/b/BloodlineKeeper.java +++ b/Mage.Sets/src/mage/cards/b/BloodlineKeeper.java @@ -1,18 +1,17 @@ package mage.cards.b; -import java.util.UUID; - import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; 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.costs.mana.ManaCostsImpl; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.hint.Hint; import mage.abilities.hint.ValueHint; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.TransformAbility; @@ -21,16 +20,22 @@ 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.common.FilterControlledPermanent; import mage.game.permanent.token.VampireToken; +import java.util.UUID; + /** * @author Loki */ public final class BloodlineKeeper extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.VAMPIRE, "you control five or more Vampires"); + private static final FilterPermanent filter + = new FilterControlledPermanent(SubType.VAMPIRE, "you control five or more Vampires"); + private static final Condition condition + = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 4); + private static final Hint hint = new ValueHint("Vampires you control", new PermanentsOnBattlefieldCount(filter)); public BloodlineKeeper(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{B}"); @@ -42,15 +47,15 @@ public final class BloodlineKeeper extends CardImpl { this.secondSideCardClazz = mage.cards.l.LordOfLineage.class; this.addAbility(FlyingAbility.getInstance()); + // {T}: Create a 2/2 black Vampire creature token with flying. this.addAbility(new SimpleActivatedAbility(new CreateTokenEffect(new VampireToken()), new TapSourceCost())); + // {B}: Transform Bloodline Keeper. Activate this ability only if you control five or more Vampires. this.addAbility(new TransformAbility()); - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new TransformSourceEffect(), - new ManaCostsImpl<>("{B}"), - new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 4)); - this.addAbility(ability.addHint(new ValueHint("Vampires you control", new PermanentsOnBattlefieldCount(filter)))); + this.addAbility(new ActivateIfConditionActivatedAbility( + new TransformSourceEffect(), new ManaCostsImpl<>("{B}"), condition + ).addHint(hint)); } private BloodlineKeeper(final BloodlineKeeper card) { diff --git a/Mage.Sets/src/mage/cards/b/BloodlinePretender.java b/Mage.Sets/src/mage/cards/b/BloodlinePretender.java index fde7782d705..67318b95b96 100644 --- a/Mage.Sets/src/mage/cards/b/BloodlinePretender.java +++ b/Mage.Sets/src/mage/cards/b/BloodlinePretender.java @@ -2,7 +2,7 @@ package mage.cards.b; import mage.MageInt; import mage.abilities.common.AsEntersBattlefieldAbility; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.common.ChooseCreatureTypeEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.ChangelingAbility; @@ -13,9 +13,9 @@ import mage.constants.Outcome; import mage.constants.SubType; import mage.counters.CounterType; import mage.filter.FilterPermanent; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.ChosenSubtypePredicate; +import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.predicate.mageobject.ChosenSubtypePredicate; import java.util.UUID; @@ -25,7 +25,7 @@ import java.util.UUID; public final class BloodlinePretender extends CardImpl { private static final FilterPermanent filter - = new FilterCreaturePermanent("another creature of the chosen type"); + = new FilterControlledCreaturePermanent("another creature you control of the chosen type"); static { filter.add(AnotherPredicate.instance); @@ -46,7 +46,7 @@ public final class BloodlinePretender extends CardImpl { this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.BoostCreature))); // Whenever another creature of the chosen type you control enters, put a +1/+1 counter on Bloodline Pretender. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + this.addAbility(new EntersBattlefieldAllTriggeredAbility( new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filter )); } diff --git a/Mage.Sets/src/mage/cards/b/BloodshotTrainee.java b/Mage.Sets/src/mage/cards/b/BloodshotTrainee.java index a46fbb0e55e..06e20de7583 100644 --- a/Mage.Sets/src/mage/cards/b/BloodshotTrainee.java +++ b/Mage.Sets/src/mage/cards/b/BloodshotTrainee.java @@ -10,7 +10,6 @@ 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.Permanent; import mage.target.common.TargetCreaturePermanent; @@ -31,8 +30,7 @@ public final class BloodshotTrainee extends CardImpl { this.toughness = new MageInt(3); Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new DamageTargetEffect(4), - new TapSourceCost(), BloodshotTraineeCondition.instance + new DamageTargetEffect(4), new TapSourceCost(), BloodshotTraineeCondition.instance ); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/b/BloodsoakedChampion.java b/Mage.Sets/src/mage/cards/b/BloodsoakedChampion.java index fc6dd14922e..5b1c751f4b0 100644 --- a/Mage.Sets/src/mage/cards/b/BloodsoakedChampion.java +++ b/Mage.Sets/src/mage/cards/b/BloodsoakedChampion.java @@ -1,11 +1,10 @@ package mage.cards.b; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.CantBlockAbility; import mage.abilities.condition.common.RaidCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; import mage.abilities.hint.common.RaidHint; import mage.cards.CardImpl; @@ -34,15 +33,10 @@ public final class BloodsoakedChampion extends CardImpl { this.addAbility(new CantBlockAbility()); // Raid — {1}{B}: Return Bloodstained Brave from your graveyard to the battlefield. Activate this ability only if you attacked this turn. - Ability ability = new ConditionalActivatedAbility( - Zone.GRAVEYARD, - new ReturnSourceFromGraveyardToBattlefieldEffect(), - new ManaCostsImpl<>("{1}{B}"), - RaidCondition.instance, - "Raid — {1}{B}: Return {this} from your graveyard to the battlefield. Activate only if you attacked this turn."); - ability.setAbilityWord(AbilityWord.RAID); - ability.addHint(RaidHint.instance); - this.addAbility(ability, new PlayerAttackedWatcher()); + this.addAbility(new ActivateIfConditionActivatedAbility( + Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldEffect(), + new ManaCostsImpl<>("{1}{B}"), RaidCondition.instance + ).setAbilityWord(AbilityWord.RAID).addHint(RaidHint.instance), new PlayerAttackedWatcher()); } private BloodsoakedChampion(final BloodsoakedChampion card) { diff --git a/Mage.Sets/src/mage/cards/b/BloodthirstyOgre.java b/Mage.Sets/src/mage/cards/b/BloodthirstyOgre.java index 7edbf9546fa..7700ca2cb92 100644 --- a/Mage.Sets/src/mage/cards/b/BloodthirstyOgre.java +++ b/Mage.Sets/src/mage/cards/b/BloodthirstyOgre.java @@ -1,10 +1,10 @@ package mage.cards.b; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; 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.dynamicvalue.DynamicValue; @@ -17,37 +17,40 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.common.FilterControlledPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX */ public final class BloodthirstyOgre extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.DEMON, "you control a Demon"); private static final DynamicValue xValue = new SignInversionDynamicValue(new CountersSourceCount(CounterType.DEVOTION)); + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPermanent(SubType.DEMON, "you control a Demon") + ); + public BloodthirstyOgre(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.OGRE, SubType.WARRIOR, SubType.SHAMAN); this.power = new MageInt(3); this.toughness = new MageInt(1); // {T}: Put a devotion counter on Bloodthirsty Ogre - this.addAbility(new SimpleActivatedAbility(new AddCountersSourceEffect(CounterType.DEVOTION.createInstance()),new TapSourceCost())); + this.addAbility(new SimpleActivatedAbility(new AddCountersSourceEffect(CounterType.DEVOTION.createInstance()), new TapSourceCost())); // {T}: Target creature gets -X/-X until end of turn, where X is the number of devotion counters on Bloodthirsty Ogre. Activate this ability only if you control a Demon. - - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, + Ability ability = new ActivateIfConditionActivatedAbility( new BoostTargetEffect(xValue, xValue, Duration.EndOfTurn) - .setText("target creature gets -X/-X until end of turn, where X is the number of devotion counters on {this}"), - new TapSourceCost(), - new PermanentsOnTheBattlefieldCondition(filter)); + .setText("target creature gets -X/-X until end of turn, " + + "where X is the number of devotion counters on {this}"), + new TapSourceCost(), condition + ); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/BloodthornTaunter.java b/Mage.Sets/src/mage/cards/b/BloodthornTaunter.java index 72f4f37bf0f..2ca642a082d 100644 --- a/Mage.Sets/src/mage/cards/b/BloodthornTaunter.java +++ b/Mage.Sets/src/mage/cards/b/BloodthornTaunter.java @@ -12,6 +12,7 @@ import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -37,7 +38,7 @@ public final class BloodthornTaunter extends CardImpl { SimpleActivatedAbility ability = new SimpleActivatedAbility( new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/BlueDragon.java b/Mage.Sets/src/mage/cards/b/BlueDragon.java index 670d550e1b3..3ba5018301b 100644 --- a/Mage.Sets/src/mage/cards/b/BlueDragon.java +++ b/Mage.Sets/src/mage/cards/b/BlueDragon.java @@ -1,24 +1,24 @@ package mage.cards.b; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.ContinuousEffectImpl; -import mage.constants.*; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.other.AnotherTargetPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.Target; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetOpponentsCreaturePermanent; +import java.util.UUID; + /** - * * @author weirddan455 */ public final class BlueDragon extends CardImpl { @@ -43,19 +43,9 @@ public final class BlueDragon extends CardImpl { // Lightning Breath — When Blue Dragon enters the battlefield, until your next turn, target creature an opponent controls gets -3/-0, up to one other target creature gets -2/-0, and up to one other target creature gets -1/-0. Ability ability = new EntersBattlefieldTriggeredAbility(new BlueDragonEffect()); - - Target target = new TargetOpponentsCreaturePermanent(); - target.setTargetTag(1); - ability.addTarget(target.withChooseHint("-3/-0")); - - target = new TargetCreaturePermanent(0, 1, filter2, false); - target.setTargetTag(2); - ability.addTarget(target.withChooseHint("-2/-0")); - - target = new TargetCreaturePermanent(0, 1, filter3, false); - target.setTargetTag(3); - ability.addTarget(target.withChooseHint("-1/-0")); - + ability.addTarget(new TargetOpponentsCreaturePermanent().setTargetTag(1).withChooseHint("-3/-0")); + ability.addTarget(new TargetPermanent(0, 1, filter2).setTargetTag(2).withChooseHint("-2/-0")); + ability.addTarget(new TargetPermanent(0, 1, filter3).setTargetTag(3).withChooseHint("-1/-0")); this.addAbility(ability.withFlavorWord("Lightning Breath")); } diff --git a/Mage.Sets/src/mage/cards/b/Blustersquall.java b/Mage.Sets/src/mage/cards/b/Blustersquall.java index 36edbe06932..0bfe1d44ba7 100644 --- a/Mage.Sets/src/mage/cards/b/Blustersquall.java +++ b/Mage.Sets/src/mage/cards/b/Blustersquall.java @@ -13,10 +13,13 @@ import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author LevelX2 */ @@ -26,7 +29,7 @@ public final class Blustersquall extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}"); // Tap target creature you don't control. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.getSpellAbility().addEffect(new TapTargetEffect()); // Overload {3}{U} (You may cast this spell for its overload cost. If you do, change its text by replacing all instances of "target" with "each.") diff --git a/Mage.Sets/src/mage/cards/b/BondersEnclave.java b/Mage.Sets/src/mage/cards/b/BondersEnclave.java index dee8f3a5d1f..e6a23309340 100644 --- a/Mage.Sets/src/mage/cards/b/BondersEnclave.java +++ b/Mage.Sets/src/mage/cards/b/BondersEnclave.java @@ -10,7 +10,6 @@ import mage.abilities.mana.ColorlessManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; import java.util.UUID; @@ -27,8 +26,7 @@ public final class BondersEnclave extends CardImpl { // {3}, {T}: Draw a card. Activate this ability only if you control a creature with power 4 or greater. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), - new GenericManaCost(3), FerociousCondition.instance + new DrawCardSourceControllerEffect(1), new GenericManaCost(3), FerociousCondition.instance ); ability.addCost(new TapSourceCost()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/b/BoneShredder.java b/Mage.Sets/src/mage/cards/b/BoneShredder.java index ddd06ccdaaa..e752b07ffa0 100644 --- a/Mage.Sets/src/mage/cards/b/BoneShredder.java +++ b/Mage.Sets/src/mage/cards/b/BoneShredder.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -43,7 +44,7 @@ public final class BoneShredder extends CardImpl { //When Bone Shredder enters the battlefield, destroy target nonartifact, nonblack creature. Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(false)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/BoobyTrap.java b/Mage.Sets/src/mage/cards/b/BoobyTrap.java index f8fd5f92907..e26b8ebf1af 100644 --- a/Mage.Sets/src/mage/cards/b/BoobyTrap.java +++ b/Mage.Sets/src/mage/cards/b/BoobyTrap.java @@ -91,7 +91,7 @@ class BoobyTrapTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "The chosen player reveals each card they draw.\n" + + return "The chosen player reveals each card they draw.
" + "When the chosen player draws the named card, sacrifice {this}. If you do, {this} deals 10 damage to that player."; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/b/BorealOutrider.java b/Mage.Sets/src/mage/cards/b/BorealOutrider.java index 94b9fd62674..d220f910a7d 100644 --- a/Mage.Sets/src/mage/cards/b/BorealOutrider.java +++ b/Mage.Sets/src/mage/cards/b/BorealOutrider.java @@ -61,7 +61,7 @@ enum BorealOutriderCondition implements Condition { @Override public String toString() { - return "{S} of any of that spell's color was spent to cast it"; + return "{S} of any of that spell's colors was spent to cast it"; } } @@ -69,6 +69,7 @@ class BorealOutriderEffect extends ReplacementEffectImpl { BorealOutriderEffect() { super(Duration.EndOfStep, Outcome.BoostCreature); + staticText = "that creature enters with an additional +1/+1 counter on it"; } private BorealOutriderEffect(BorealOutriderEffect effect) { diff --git a/Mage.Sets/src/mage/cards/b/BorosFuryShield.java b/Mage.Sets/src/mage/cards/b/BorosFuryShield.java index 80bc35cb960..2e90adce7d9 100644 --- a/Mage.Sets/src/mage/cards/b/BorosFuryShield.java +++ b/Mage.Sets/src/mage/cards/b/BorosFuryShield.java @@ -15,6 +15,7 @@ import mage.filter.common.FilterAttackingOrBlockingCreature; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -29,7 +30,7 @@ public final class BorosFuryShield extends CardImpl { // Prevent all combat damage that would be dealt by target attacking or blocking creature this turn. this.getSpellAbility().addEffect(new PreventDamageByTargetEffect(Duration.EndOfTurn, true)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // If {R} was spent to cast Boros Fury-Shield, it deals damage to that creature's controller equal to the creature's power. this.getSpellAbility().addEffect(new ConditionalOneShotEffect( diff --git a/Mage.Sets/src/mage/cards/b/BorrowedHostility.java b/Mage.Sets/src/mage/cards/b/BorrowedHostility.java index 780b8319a26..03cb05fcedb 100644 --- a/Mage.Sets/src/mage/cards/b/BorrowedHostility.java +++ b/Mage.Sets/src/mage/cards/b/BorrowedHostility.java @@ -12,6 +12,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -38,13 +39,13 @@ public final class BorrowedHostility extends CardImpl { Effect effect = new BoostTargetEffect(3, 0, Duration.EndOfTurn); effect.setText("Target creature gets +3/+0 until end of turn"); this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filterBoost).withChooseHint("gets +3/+0 until end of turn")); + this.getSpellAbility().addTarget(new TargetPermanent(filterBoost).withChooseHint("gets +3/+0 until end of turn")); // Target creature gains first strike until end of turn. effect = new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn); effect.setText("Target creature gains first strike until end of turn"); Mode mode = new Mode(effect); - mode.addTarget(new TargetCreaturePermanent(filterFirstStrike).withChooseHint("gains first strike until end of turn")); + mode.addTarget(new TargetPermanent(filterFirstStrike).withChooseHint("gains first strike until end of turn")); this.getSpellAbility().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/b/BorrowedMalevolence.java b/Mage.Sets/src/mage/cards/b/BorrowedMalevolence.java index f427b1c6db0..4b1d3d46e1d 100644 --- a/Mage.Sets/src/mage/cards/b/BorrowedMalevolence.java +++ b/Mage.Sets/src/mage/cards/b/BorrowedMalevolence.java @@ -10,6 +10,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -36,13 +37,13 @@ public final class BorrowedMalevolence extends CardImpl { Effect effect = new BoostTargetEffect(1, 1, Duration.EndOfTurn); effect.setText("Target creature gets +1/+1 until end of turn"); this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filterCreaturePlus).withChooseHint("gets +1/+1 until end of turn")); + this.getSpellAbility().addTarget(new TargetPermanent(filterCreaturePlus).withChooseHint("gets +1/+1 until end of turn")); // Target creature gets -1/-1 until end of turn. effect = new BoostTargetEffect(-1, -1, Duration.EndOfTurn); effect.setText("Target creature gets -1/-1 until end of turn"); Mode mode = new Mode(effect); - mode.addTarget(new TargetCreaturePermanent(filterCreatureMinus).withChooseHint("gets -1/-1 until end of turn")); + mode.addTarget(new TargetPermanent(filterCreatureMinus).withChooseHint("gets -1/-1 until end of turn")); this.getSpellAbility().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/b/BountyHunter.java b/Mage.Sets/src/mage/cards/b/BountyHunter.java index 365dc646545..09d3c48adec 100644 --- a/Mage.Sets/src/mage/cards/b/BountyHunter.java +++ b/Mage.Sets/src/mage/cards/b/BountyHunter.java @@ -14,10 +14,13 @@ import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author LoneFox @@ -38,11 +41,11 @@ public final class BountyHunter extends CardImpl { // {tap}: Put a bounty counter on target nonblack creature. Ability ability = new SimpleActivatedAbility(new AddCountersTargetEffect(CounterType.BOUNTY.createInstance()), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + ability.addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.addAbility(ability); // {tap}: Destroy target creature with a bounty counter on it. ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/BowOfNylea.java b/Mage.Sets/src/mage/cards/b/BowOfNylea.java index 2cccbf04f28..967859d2bb2 100644 --- a/Mage.Sets/src/mage/cards/b/BowOfNylea.java +++ b/Mage.Sets/src/mage/cards/b/BowOfNylea.java @@ -20,6 +20,7 @@ import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetCreaturePermanent; @@ -49,7 +50,7 @@ public final class BowOfNylea extends CardImpl { ability.addCost(new TapSourceCost()); // or Bow of Nylea deals 2 damage to target creature with flying; Mode mode = new Mode(new DamageTargetEffect(2)); - mode.addTarget(new TargetCreaturePermanent(filterFlying)); + mode.addTarget(new TargetPermanent(filterFlying)); ability.addMode(mode); // or you gain 3 life; mode = new Mode(new GainLifeEffect(3)); diff --git a/Mage.Sets/src/mage/cards/b/BoxingRing.java b/Mage.Sets/src/mage/cards/b/BoxingRing.java index 9c9fbb84a4a..cab3c136b8e 100644 --- a/Mage.Sets/src/mage/cards/b/BoxingRing.java +++ b/Mage.Sets/src/mage/cards/b/BoxingRing.java @@ -6,12 +6,15 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenEffect; 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.WatcherScope; import mage.filter.FilterPermanent; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; @@ -53,9 +56,8 @@ public final class BoxingRing extends CardImpl { this.addAbility(ability); // {T}: Create a Treasure token. Activate only if you control a creature that fought this turn. - this.addAbility(new ConditionalActivatedAbility( - Zone.BATTLEFIELD, new CreateTokenEffect(new TreasureToken()), - new TapSourceCost(), BoxingRingCondition.instance + this.addAbility(new ActivateIfConditionActivatedAbility( + new CreateTokenEffect(new TreasureToken()), new TapSourceCost(), BoxingRingCondition.instance ), new BoxingRingWatcher()); } diff --git a/Mage.Sets/src/mage/cards/b/BraceForImpact.java b/Mage.Sets/src/mage/cards/b/BraceForImpact.java index f98d54ec04a..68e94370dd2 100644 --- a/Mage.Sets/src/mage/cards/b/BraceForImpact.java +++ b/Mage.Sets/src/mage/cards/b/BraceForImpact.java @@ -15,6 +15,7 @@ import mage.game.events.GameEvent; import mage.game.events.PreventDamageEvent; import mage.game.events.PreventedDamageEvent; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -35,7 +36,7 @@ public final class BraceForImpact extends CardImpl { // Prevent all damage that would be dealt to target multicolored creature this turn. For each 1 damage prevented this way, put a +1/+1 counter on that creature. this.getSpellAbility().addEffect(new BraceForImpactPreventDamageTargetEffect(Duration.EndOfTurn)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private BraceForImpact(final BraceForImpact card) { diff --git a/Mage.Sets/src/mage/cards/b/Brainspoil.java b/Mage.Sets/src/mage/cards/b/Brainspoil.java index b0185041d08..5d016a67639 100644 --- a/Mage.Sets/src/mage/cards/b/Brainspoil.java +++ b/Mage.Sets/src/mage/cards/b/Brainspoil.java @@ -10,6 +10,7 @@ import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.EnchantedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -29,7 +30,7 @@ public final class Brainspoil extends CardImpl { // Destroy target creature that isn't enchanted. It can't be regenerated. this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // Transmute {1}{B}{B} this.addAbility(new TransmuteAbility("{1}{B}{B}")); diff --git a/Mage.Sets/src/mage/cards/b/BrainstealerDragon.java b/Mage.Sets/src/mage/cards/b/BrainstealerDragon.java index 51191b395c7..0fc11fb4d03 100644 --- a/Mage.Sets/src/mage/cards/b/BrainstealerDragon.java +++ b/Mage.Sets/src/mage/cards/b/BrainstealerDragon.java @@ -2,10 +2,10 @@ package mage.cards.b; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.FlyingAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.*; import mage.constants.*; import mage.filter.FilterPermanent; @@ -23,8 +23,7 @@ import java.util.UUID; */ public final class BrainstealerDragon extends CardImpl { - private static final FilterPermanent filter - = new FilterNonlandPermanent("a nonland permanent an opponent owns"); + private static final FilterPermanent filter = new FilterNonlandPermanent(); static { filter.add(TargetController.OPPONENT.getOwnerPredicate()); @@ -42,15 +41,12 @@ public final class BrainstealerDragon extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // At the beginning of your end step, exile the top card of each opponent's library. You may play those cards for as long as they remain exiled. If you cast a spell this way, you may spend mana as though it were mana of any color to cast it. - this.addAbility(new BeginningOfEndStepTriggeredAbility( - new BrainstealerDragonExileEffect() - )); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new BrainstealerDragonExileEffect())); // Whenever a nonland permanent an opponent owns you control enters, they lose life equal to its mana value. this.addAbility(new EntersBattlefieldControlledTriggeredAbility( - Zone.BATTLEFIELD, new BrainstealerDragonLifeEffect(), filter, - false, SetTargetPointer.PERMANENT - )); + Zone.BATTLEFIELD, new BrainstealerDragonLifeEffect(), filter, false, SetTargetPointer.PERMANENT + ).setTriggerPhrase("Whenever a nonland permanent an opponent owns enters the battlefield under your control, ")); } private BrainstealerDragon(final BrainstealerDragon card) { diff --git a/Mage.Sets/src/mage/cards/b/BramblefortFink.java b/Mage.Sets/src/mage/cards/b/BramblefortFink.java index dfb393b5f22..29d9f47e9ee 100644 --- a/Mage.Sets/src/mage/cards/b/BramblefortFink.java +++ b/Mage.Sets/src/mage/cards/b/BramblefortFink.java @@ -8,8 +8,9 @@ import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.continuous.SetBasePowerToughnessSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.filter.FilterPermanent; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; import mage.filter.common.FilterControlledPlaneswalkerPermanent; import java.util.UUID; @@ -19,9 +20,9 @@ import java.util.UUID; */ public final class BramblefortFink extends CardImpl { - private static final FilterPermanent filter - = new FilterControlledPlaneswalkerPermanent(SubType.OKO, "you control an Oko planeswalker"); - private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPlaneswalkerPermanent(SubType.OKO, "you control an Oko planeswalker") + ); public BramblefortFink(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); @@ -32,10 +33,10 @@ public final class BramblefortFink extends CardImpl { // {8}: Bramblefort Fink has base power and toughness 10/10 until end of turn. Activate this ability only if you control an Oko planeswalker. this.addAbility(new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, - new SetBasePowerToughnessSourceEffect(10, 10, Duration.EndOfTurn), - new GenericManaCost(8), - condition)); + new SetBasePowerToughnessSourceEffect( + 10, 10, Duration.EndOfTurn + ), new GenericManaCost(8), condition + )); } private BramblefortFink(final BramblefortFink card) { diff --git a/Mage.Sets/src/mage/cards/b/BranchingBolt.java b/Mage.Sets/src/mage/cards/b/BranchingBolt.java index b5fca894864..f9da1d99e24 100644 --- a/Mage.Sets/src/mage/cards/b/BranchingBolt.java +++ b/Mage.Sets/src/mage/cards/b/BranchingBolt.java @@ -14,6 +14,7 @@ import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -39,10 +40,10 @@ public final class BranchingBolt extends CardImpl { this.getSpellAbility().getModes().setMaxModes(2); // Branching Bolt deals 3 damage to target creature with flying; this.getSpellAbility().addEffect(new DamageTargetEffect(3)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filterFlying).withChooseHint("deals 3 damage, without flying")); + this.getSpellAbility().addTarget(new TargetPermanent(filterFlying).withChooseHint("deals 3 damage, without flying")); // or Branching Bolt deals 3 damage to target creature without flying. Mode mode = new Mode(new DamageTargetEffect(3)); - mode.addTarget(new TargetCreaturePermanent(filterNotFlying).withChooseHint("deals 3 damage, without flying")); + mode.addTarget(new TargetPermanent(filterNotFlying).withChooseHint("deals 3 damage, without flying")); this.getSpellAbility().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/b/BrassTalonChimera.java b/Mage.Sets/src/mage/cards/b/BrassTalonChimera.java index 232469aaf02..42ef018d9cf 100644 --- a/Mage.Sets/src/mage/cards/b/BrassTalonChimera.java +++ b/Mage.Sets/src/mage/cards/b/BrassTalonChimera.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -44,7 +45,7 @@ public final class BrassTalonChimera extends CardImpl { Ability ability = new SimpleActivatedAbility(new AddCountersTargetEffect(CounterType.P2P2.createInstance()), new SacrificeSourceCost()); ability.addEffect(new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.WhileOnBattlefield) .setText("It gains first strike. (This effect lasts indefinitely.)")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/BreachingHippocamp.java b/Mage.Sets/src/mage/cards/b/BreachingHippocamp.java index 69ec028f5f4..4cf6bc6a89e 100644 --- a/Mage.Sets/src/mage/cards/b/BreachingHippocamp.java +++ b/Mage.Sets/src/mage/cards/b/BreachingHippocamp.java @@ -1,6 +1,5 @@ package mage.cards.b; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -11,16 +10,17 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class BreachingHippocamp extends CardImpl { public BreachingHippocamp(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); this.subtype.add(SubType.HORSE, SubType.FISH); this.power = new MageInt(3); @@ -28,9 +28,10 @@ public final class BreachingHippocamp extends CardImpl { // Flash this.addAbility(FlashAbility.getInstance()); + // When Breaching Hippocamp enters the battlefield, untap another target creature you control. Ability ability = new EntersBattlefieldTriggeredAbility(new UntapTargetEffect(), false); - ability.addTarget(new TargetControlledCreaturePermanent(1,1, StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL, false)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/BreakOpen.java b/Mage.Sets/src/mage/cards/b/BreakOpen.java index ae00e8d7762..32b1d9317aa 100644 --- a/Mage.Sets/src/mage/cards/b/BreakOpen.java +++ b/Mage.Sets/src/mage/cards/b/BreakOpen.java @@ -9,6 +9,7 @@ import mage.constants.CardType; import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.card.FaceDownPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -29,7 +30,7 @@ public final class BreakOpen extends CardImpl { // Turn target face-down creature an opponent controls face up. this.getSpellAbility().addEffect(new TurnFaceUpTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private BreakOpen(final BreakOpen card) { diff --git a/Mage.Sets/src/mage/cards/b/BreakThroughTheLine.java b/Mage.Sets/src/mage/cards/b/BreakThroughTheLine.java index 197a4e6b965..a9d1dd390fa 100644 --- a/Mage.Sets/src/mage/cards/b/BreakThroughTheLine.java +++ b/Mage.Sets/src/mage/cards/b/BreakThroughTheLine.java @@ -17,6 +17,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -39,7 +40,7 @@ public final class BreakThroughTheLine extends CardImpl { Effect effect = new CantBeBlockedTargetEffect(Duration.EndOfTurn); effect.setText("and can't be blocked this turn"); ability.addEffect(effect); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/BreakingOfTheFellowship.java b/Mage.Sets/src/mage/cards/b/BreakingOfTheFellowship.java index 2a4438cf23c..6b1449b7d2e 100644 --- a/Mage.Sets/src/mage/cards/b/BreakingOfTheFellowship.java +++ b/Mage.Sets/src/mage/cards/b/BreakingOfTheFellowship.java @@ -16,6 +16,7 @@ import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -30,8 +31,8 @@ public final class BreakingOfTheFellowship extends CardImpl { // Target creature an opponent controls deals damage equal to its power to another target creature that player controls. this.getSpellAbility().addEffect(new BreakingOfTheFellowshipEffect()); - this.getSpellAbility().addTarget(new BreakingOfTheFellowshipFirstTarget(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("another target creature that player controls"))); + this.getSpellAbility().addTarget(new BreakingOfTheFellowshipFirstTarget()); + this.getSpellAbility().addTarget(new TargetPermanent(new FilterCreaturePermanent("another target creature that player controls"))); // The Ring tempts you. this.getSpellAbility().addEffect(new TheRingTemptsYouEffect()); @@ -78,10 +79,10 @@ class BreakingOfTheFellowshipEffect extends OneShotEffect { } -class BreakingOfTheFellowshipFirstTarget extends TargetCreaturePermanent { +class BreakingOfTheFellowshipFirstTarget extends TargetPermanent { - public BreakingOfTheFellowshipFirstTarget(FilterCreaturePermanent filter) { - super(1, 1, filter, false); + public BreakingOfTheFellowshipFirstTarget() { + super(1, 1, StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE, false); } private BreakingOfTheFellowshipFirstTarget(final BreakingOfTheFellowshipFirstTarget target) { diff --git a/Mage.Sets/src/mage/cards/b/BreathOfFury.java b/Mage.Sets/src/mage/cards/b/BreathOfFury.java index f1f676514f3..01a40680699 100644 --- a/Mage.Sets/src/mage/cards/b/BreathOfFury.java +++ b/Mage.Sets/src/mage/cards/b/BreathOfFury.java @@ -1,7 +1,6 @@ package mage.cards.b; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; @@ -23,6 +22,8 @@ import mage.target.Target; import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; +import java.util.UUID; + /** * @author duncant */ @@ -119,7 +120,7 @@ class BreathOfFuryEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature you control that could be enchanted by " + enchantment.getName()); filter.add(new CanBeEnchantedByPredicate(enchantment)); - Target target = new TargetControlledCreaturePermanent(filter); + Target target = new TargetPermanent(filter); target.withNotTarget(true); // It's important to check that the creature was successfully sacrificed here. Effects that prevent sacrifice will also prevent Breath of Fury's effect from working. // Commanders going to the command zone and Rest in Peace style replacement effects don't make Permanent.sacrifice return false. diff --git a/Mage.Sets/src/mage/cards/b/BridgeFromBelow.java b/Mage.Sets/src/mage/cards/b/BridgeFromBelow.java index 0be4df74c26..6fc26f76090 100644 --- a/Mage.Sets/src/mage/cards/b/BridgeFromBelow.java +++ b/Mage.Sets/src/mage/cards/b/BridgeFromBelow.java @@ -1,8 +1,7 @@ package mage.cards.b; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.DiesCreatureTriggeredAbility; import mage.abilities.condition.common.SourceInGraveyardCondition; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.ExileSourceEffect; import mage.cards.CardImpl; @@ -10,24 +9,20 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.TargetController; import mage.constants.Zone; +import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TokenPredicate; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; -import mage.game.permanent.Permanent; import mage.game.permanent.token.ZombieToken; import java.util.UUID; /** - * * @author Plopman */ public final class BridgeFromBelow extends CardImpl { - private static final FilterCreaturePermanent filter1 = new FilterCreaturePermanent("Whenever a nontoken creature is put into your graveyard from the battlefield, "); - private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("When a creature is put into an opponent's graveyard from the battlefield, "); + private static final FilterPermanent filter1 = new FilterCreaturePermanent(); + private static final FilterPermanent filter2 = new FilterCreaturePermanent(); static { filter1.add(TargetController.YOU.getOwnerPredicate()); @@ -39,11 +34,18 @@ public final class BridgeFromBelow extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{B}{B}{B}"); // Whenever a nontoken creature is put into your graveyard from the battlefield, if Bridge from Below is in your graveyard, create a 2/2 black Zombie creature token. - this.addAbility(new BridgeFromBelowAbility(new CreateTokenEffect(new ZombieToken()), filter1)); + this.addAbility(new DiesCreatureTriggeredAbility( + Zone.GRAVEYARD, new CreateTokenEffect(new ZombieToken()), + false, filter1, false + ).setTriggerPhrase("Whenever a nontoken creature is put into your graveyard from the battlefield, ") + .withInterveningIf(SourceInGraveyardCondition.instance)); // When a creature is put into an opponent's graveyard from the battlefield, if Bridge from Below is in your graveyard, exile Bridge from Below. - this.addAbility(new BridgeFromBelowAbility(new ExileSourceEffect(), filter2)); - + this.addAbility(new DiesCreatureTriggeredAbility( + Zone.GRAVEYARD, new ExileSourceEffect().setText("exile this card"), + false, filter2, false + ).setTriggerPhrase("When a creature is put into an opponent's graveyard from the battlefield, ") + .withInterveningIf(SourceInGraveyardCondition.instance)); } private BridgeFromBelow(final BridgeFromBelow card) { @@ -55,41 +57,3 @@ public final class BridgeFromBelow extends CardImpl { return new BridgeFromBelow(this); } } - -class BridgeFromBelowAbility extends TriggeredAbilityImpl { - - private final FilterCreaturePermanent filter; - - BridgeFromBelowAbility(Effect effect, FilterCreaturePermanent filter) { - super(Zone.GRAVEYARD, effect, false); - this.filter = filter; - this.withInterveningIf(SourceInGraveyardCondition.instance); - setTriggerPhrase(filter.getMessage()); - setLeavesTheBattlefieldTrigger(true); // it's not required for Bridge from Below, but better to keep same code style and verify pass - } - - private BridgeFromBelowAbility(final BridgeFromBelowAbility ability) { - super(ability); - this.filter = ability.filter; - } - - @Override - public BridgeFromBelowAbility copy() { - return new BridgeFromBelowAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ZONE_CHANGE; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); - if (permanent == null || !((ZoneChangeEvent) event).isDiesEvent()) { - return false; - } - return filter.match(permanent, controllerId, this, game); - } - -} diff --git a/Mage.Sets/src/mage/cards/b/BringLow.java b/Mage.Sets/src/mage/cards/b/BringLow.java index 70c9b810e44..e700d5f6f34 100644 --- a/Mage.Sets/src/mage/cards/b/BringLow.java +++ b/Mage.Sets/src/mage/cards/b/BringLow.java @@ -1,7 +1,6 @@ package mage.cards.b; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.condition.Condition; import mage.abilities.decorator.ConditionalOneShotEffect; @@ -14,6 +13,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * * @author LevelX2 @@ -29,7 +30,7 @@ public final class BringLow extends CardImpl { new DamageTargetEffect(5), new DamageTargetEffect(3), new TargetHasCounterCondition(CounterType.P1P1), - "{this} deals 3 damage to target creature. If that creature has a +1/+1 counter on it, Bring Low deals 5 damage to it instead")); + "{this} deals 3 damage to target creature. If that creature has a +1/+1 counter on it, {this} deals 5 damage to it instead")); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage.Sets/src/mage/cards/b/BringToTrial.java b/Mage.Sets/src/mage/cards/b/BringToTrial.java index c1bbac58820..a1d5b8a3d46 100644 --- a/Mage.Sets/src/mage/cards/b/BringToTrial.java +++ b/Mage.Sets/src/mage/cards/b/BringToTrial.java @@ -7,6 +7,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -28,7 +29,7 @@ public final class BringToTrial extends CardImpl { // Exile target creature with power 4 or greater. this.getSpellAbility().addEffect(new ExileTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private BringToTrial(final BringToTrial card) { diff --git a/Mage.Sets/src/mage/cards/b/BrokenDam.java b/Mage.Sets/src/mage/cards/b/BrokenDam.java index 46f0f144bff..f55a0bb78cc 100644 --- a/Mage.Sets/src/mage/cards/b/BrokenDam.java +++ b/Mage.Sets/src/mage/cards/b/BrokenDam.java @@ -1,7 +1,5 @@ - package mage.cards.b; -import java.util.UUID; import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.keyword.HorsemanshipAbility; import mage.cards.CardImpl; @@ -10,26 +8,27 @@ import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author LoneFox */ public final class BrokenDam extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures without horsemanship"); static { filter.add(Predicates.not(new AbilityPredicate(HorsemanshipAbility.class))); } - public BrokenDam(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{U}"); + public BrokenDam(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{U}"); // Tap one or two target creatures without horsemanship. this.getSpellAbility().addEffect(new TapTargetEffect("tap one or two target creatures without horsemanship")); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(1, 2, filter, false)); + this.getSpellAbility().addTarget(new TargetPermanent(1, 2, filter)); } private BrokenDam(final BrokenDam card) { diff --git a/Mage.Sets/src/mage/cards/b/BrokenVisage.java b/Mage.Sets/src/mage/cards/b/BrokenVisage.java index cee7109e816..923988b0ae5 100644 --- a/Mage.Sets/src/mage/cards/b/BrokenVisage.java +++ b/Mage.Sets/src/mage/cards/b/BrokenVisage.java @@ -18,6 +18,7 @@ import mage.filter.predicate.permanent.AttackingPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.BrokenVisageSpiritToken; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; @@ -38,7 +39,7 @@ public final class BrokenVisage extends CardImpl { // Destroy target nonartifact attacking creature. It can't be regenerated. Create a black Spirit creature token. Its power is equal to that creature's power and its toughness is equal to that creature's toughness. Sacrifice the token at the beginning of the next end step. this.getSpellAbility().addEffect(new BrokenVisageEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private BrokenVisage(final BrokenVisage card) { diff --git a/Mage.Sets/src/mage/cards/b/BrotherhoodRegalia.java b/Mage.Sets/src/mage/cards/b/BrotherhoodRegalia.java index 59b49b5e15c..e7dd7f1df12 100644 --- a/Mage.Sets/src/mage/cards/b/BrotherhoodRegalia.java +++ b/Mage.Sets/src/mage/cards/b/BrotherhoodRegalia.java @@ -12,7 +12,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.common.FilterControlledCreaturePermanent; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -23,6 +23,7 @@ public final class BrotherhoodRegalia extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("legendary creature"); + static { filter.add(SuperType.LEGENDARY.getPredicate()); } @@ -44,7 +45,7 @@ public final class BrotherhoodRegalia extends CardImpl { this.addAbility(ability); // Equip legendary creature {1} - this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(1), new TargetControlledCreaturePermanent(filter), false)); + this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(1), new TargetPermanent(filter), false)); // Equip {3} this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(3), true)); diff --git a/Mage.Sets/src/mage/cards/b/BrotherhoodScribe.java b/Mage.Sets/src/mage/cards/b/BrotherhoodScribe.java index af932033555..eebfc363f3c 100644 --- a/Mage.Sets/src/mage/cards/b/BrotherhoodScribe.java +++ b/Mage.Sets/src/mage/cards/b/BrotherhoodScribe.java @@ -7,7 +7,7 @@ import mage.MageInt; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect; import mage.abilities.hint.common.MetalcraftHint; @@ -32,7 +32,7 @@ public final class BrotherhoodScribe extends CardImpl { this.toughness = new MageInt(3); // Metalcraft -- {T}: You get {E}. Activate only if you control three or more artifacts. - this.addAbility(new ConditionalActivatedAbility( + this.addAbility(new ActivateIfConditionActivatedAbility( new GetEnergyCountersControllerEffect(1), new TapSourceCost(), MetalcraftCondition.instance) diff --git a/Mage.Sets/src/mage/cards/b/BruseTarlBoorishHerder.java b/Mage.Sets/src/mage/cards/b/BruseTarlBoorishHerder.java index 838c8c189ce..747fec5217c 100644 --- a/Mage.Sets/src/mage/cards/b/BruseTarlBoorishHerder.java +++ b/Mage.Sets/src/mage/cards/b/BruseTarlBoorishHerder.java @@ -1,11 +1,8 @@ - package mage.cards.b; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.DoubleStrikeAbility; import mage.abilities.keyword.LifelinkAbility; @@ -16,11 +13,11 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.constants.SuperType; -import mage.filter.common.FilterControlledCreaturePermanent; import mage.target.common.TargetControlledCreaturePermanent; +import java.util.UUID; + /** - * * @author spjspj */ public final class BruseTarlBoorishHerder extends CardImpl { @@ -34,14 +31,13 @@ public final class BruseTarlBoorishHerder extends CardImpl { this.toughness = new MageInt(3); // Whenever Bruse Tarl, Boorish Herder enters the battlefield or attacks, target creature you control gains double strike and lifelink until end of turn. - Effect effect = new GainAbilityTargetEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn); - effect.setText("target creature you control gains double strike"); - Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility(effect); - effect = new GainAbilityTargetEffect(LifelinkAbility.getInstance(), Duration.EndOfTurn); - effect.setText("and lifelink until end of turn"); - ability.addEffect(effect); - ability.addTarget(new TargetControlledCreaturePermanent(new FilterControlledCreaturePermanent("target creature you control"))); - + Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility(new GainAbilityTargetEffect( + DoubleStrikeAbility.getInstance(), Duration.EndOfTurn + ).setText("target creature you control gains double strike")); + ability.addEffect(new GainAbilityTargetEffect( + LifelinkAbility.getInstance(), Duration.EndOfTurn + ).setText("and lifelink until end of turn")); + ability.addTarget(new TargetControlledCreaturePermanent()); this.addAbility(ability); // Partner diff --git a/Mage.Sets/src/mage/cards/b/Bulwark.java b/Mage.Sets/src/mage/cards/b/Bulwark.java index 1d72f95d868..e2fac8bbb86 100644 --- a/Mage.Sets/src/mage/cards/b/Bulwark.java +++ b/Mage.Sets/src/mage/cards/b/Bulwark.java @@ -1,8 +1,8 @@ package mage.cards.b; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.effects.OneShotEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -43,7 +43,7 @@ class BulwarkDamageEffect extends OneShotEffect { BulwarkDamageEffect() { super(Outcome.Damage); - staticText = "Bulwark deals X damage to target opponent, where X is the number of cards in your hand minus the number of cards in that player's hand"; + staticText = "{this} deals X damage to target opponent, where X is the number of cards in your hand minus the number of cards in that player's hand"; } private BulwarkDamageEffect(final BulwarkDamageEffect effect) { diff --git a/Mage.Sets/src/mage/cards/b/BurningPalmEfreet.java b/Mage.Sets/src/mage/cards/b/BurningPalmEfreet.java index e0e1bd4963a..99f881cc6ac 100644 --- a/Mage.Sets/src/mage/cards/b/BurningPalmEfreet.java +++ b/Mage.Sets/src/mage/cards/b/BurningPalmEfreet.java @@ -16,6 +16,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -42,7 +43,7 @@ public final class BurningPalmEfreet extends CardImpl { ability.addEffect(new LoseAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn) .setText("and that creature loses flying until end of turn") ); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/b/ButchDeLoriaTunnelSnake.java b/Mage.Sets/src/mage/cards/b/ButchDeLoriaTunnelSnake.java index 8d6545ff0fa..9c660714aba 100644 --- a/Mage.Sets/src/mage/cards/b/ButchDeLoriaTunnelSnake.java +++ b/Mage.Sets/src/mage/cards/b/ButchDeLoriaTunnelSnake.java @@ -25,10 +25,13 @@ import mage.filter.StaticFilters; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * @author Susucr */ @@ -67,7 +70,7 @@ public final class ButchDeLoriaTunnelSnake extends CardImpl { new AddCountersTargetEffect(CounterType.MENACE.createInstance()), new ManaCostsImpl<>("{1}{B}") ); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); ability.addEffect(new BecomesCreatureTypeTargetEffect(Duration.EndOfGame, SubType.ROGUE, false) .setText("It becomes a Rogue in addition to its other types")); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/b/BuzzingWhackADoodle.java b/Mage.Sets/src/mage/cards/b/BuzzingWhackADoodle.java index 73fc5257431..07360cdcf3d 100644 --- a/Mage.Sets/src/mage/cards/b/BuzzingWhackADoodle.java +++ b/Mage.Sets/src/mage/cards/b/BuzzingWhackADoodle.java @@ -1,14 +1,11 @@ - package mage.cards.b; -import java.util.Set; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.IntCompareCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.GainLifeEffect; @@ -18,15 +15,16 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.Outcome; -import mage.constants.Zone; import mage.game.Game; import mage.players.Player; import mage.target.Target; import mage.target.TargetPlayer; import mage.target.common.TargetOpponent; +import java.util.Set; +import java.util.UUID; + /** - * * @author spjspj */ public final class BuzzingWhackADoodle extends CardImpl { @@ -38,16 +36,22 @@ public final class BuzzingWhackADoodle extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new BuzzingWhackADoodleEffect(), false)); // *Whack - T: Target player loses 2 life. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new LoseLifeTargetEffect(2), new TapSourceCost(), new WhackCondition()); + Ability ability = new ActivateIfConditionActivatedAbility( + new LoseLifeTargetEffect(2), new TapSourceCost(), new WhackCondition() + ); ability.addTarget(new TargetPlayer()); this.addAbility(ability); // *Doodle - T: You gain 3 life. - Ability ability2 = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new GainLifeEffect(3), new TapSourceCost(), new DoodleCondition()); + Ability ability2 = new ActivateIfConditionActivatedAbility( + new GainLifeEffect(3), new TapSourceCost(), new DoodleCondition() + ); this.addAbility(ability2); // *Buzz - 2, T: Draw a card. - Ability ability3 = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), new ManaCostsImpl<>("{2}"), new BuzzCondition()); + Ability ability3 = new ActivateIfConditionActivatedAbility( + new DrawCardSourceControllerEffect(1), new ManaCostsImpl<>("{2}"), new BuzzCondition() + ); ability3.addCost(new TapSourceCost()); this.addAbility(ability3); } @@ -144,7 +148,7 @@ class WhackCondition extends IntCompareCondition { @Override public String toString() { - return "if both players picked 'Whack'"; + return "both players picked 'Whack'"; } } @@ -165,7 +169,7 @@ class DoodleCondition extends IntCompareCondition { @Override public String toString() { - return "if both players picked 'Doodle'"; + return "both players picked 'Doodle'"; } } @@ -186,6 +190,6 @@ class BuzzCondition extends IntCompareCondition { @Override public String toString() { - return "if both players picked differently"; + return "both players picked differently"; } } diff --git a/Mage.Sets/src/mage/cards/c/CabalInquisitor.java b/Mage.Sets/src/mage/cards/c/CabalInquisitor.java index e6129522ac4..b6cb7292f82 100644 --- a/Mage.Sets/src/mage/cards/c/CabalInquisitor.java +++ b/Mage.Sets/src/mage/cards/c/CabalInquisitor.java @@ -6,7 +6,7 @@ import mage.abilities.condition.common.ThresholdCondition; import mage.abilities.costs.common.ExileFromGraveCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -34,7 +34,7 @@ public final class CabalInquisitor extends CardImpl { this.toughness = new MageInt(1); // Threshold - {1}{B}, {T}, Exile two cards from your graveyard: Target player discards a card. Activate this ability only any time you could cast a sorcery, and only if seven or more cards are in your graveyard. - Ability ability = new ConditionalActivatedAbility( + Ability ability = new ActivateIfConditionActivatedAbility( new DiscardTargetEffect(1), new ManaCostsImpl<>("{1}{B}"), ThresholdCondition.instance ).setTiming(TimingRule.SORCERY); ability.addTarget(new TargetPlayer()); diff --git a/Mage.Sets/src/mage/cards/c/CabalPit.java b/Mage.Sets/src/mage/cards/c/CabalPit.java index 3c322614a2d..8d9407713c4 100644 --- a/Mage.Sets/src/mage/cards/c/CabalPit.java +++ b/Mage.Sets/src/mage/cards/c/CabalPit.java @@ -5,7 +5,7 @@ import mage.abilities.condition.common.ThresholdCondition; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DamageControllerEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.mana.BlackManaAbility; @@ -32,7 +32,7 @@ public final class CabalPit extends CardImpl { this.addAbility(manaAbility); // Threshold - {B}, {T}, Sacrifice Cabal Pit: Target creature gets -2/-2 until end of turn. Activate this ability only if seven or more cards are in your graveyard. - Ability thresholdAbility = new ConditionalActivatedAbility( + Ability thresholdAbility = new ActivateIfConditionActivatedAbility( new BoostTargetEffect(-2, -2, Duration.EndOfTurn), new ManaCostsImpl<>("{B}"), ThresholdCondition.instance ); diff --git a/Mage.Sets/src/mage/cards/c/CabalTorturer.java b/Mage.Sets/src/mage/cards/c/CabalTorturer.java index b7116721839..19d118a3e7e 100644 --- a/Mage.Sets/src/mage/cards/c/CabalTorturer.java +++ b/Mage.Sets/src/mage/cards/c/CabalTorturer.java @@ -6,7 +6,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.ThresholdCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -37,7 +37,7 @@ public final class CabalTorturer extends CardImpl { this.addAbility(ability); // Threshold - {3}{B}{B}, {tap}: Target creature gets -2/-2 until end of turn. Activate this ability only if seven or more cards are in your graveyard. - ability = new ConditionalActivatedAbility( + ability = new ActivateIfConditionActivatedAbility( new BoostTargetEffect(-2, -2, Duration.EndOfTurn), new ManaCostsImpl<>("{3}{B}{B}"), ThresholdCondition.instance ); diff --git a/Mage.Sets/src/mage/cards/c/CagedZombie.java b/Mage.Sets/src/mage/cards/c/CagedZombie.java index 2625767f96d..573152e12d2 100644 --- a/Mage.Sets/src/mage/cards/c/CagedZombie.java +++ b/Mage.Sets/src/mage/cards/c/CagedZombie.java @@ -12,7 +12,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import java.util.UUID; @@ -30,8 +29,7 @@ public final class CagedZombie extends CardImpl { // {1}{B}, {T}: Each opponent loses 2 life. Activate this ability only if a creature died this turn. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new LoseLifeOpponentsEffect(2), - new ManaCostsImpl<>("{1}{B}"), MorbidCondition.instance + new LoseLifeOpponentsEffect(2), new ManaCostsImpl<>("{1}{B}"), MorbidCondition.instance ); ability.addCost(new TapSourceCost()); this.addAbility(ability.addHint(MorbidHint.instance)); diff --git a/Mage.Sets/src/mage/cards/c/CaitCageBrawler.java b/Mage.Sets/src/mage/cards/c/CaitCageBrawler.java index b92d83818f9..12aa315f45a 100644 --- a/Mage.Sets/src/mage/cards/c/CaitCageBrawler.java +++ b/Mage.Sets/src/mage/cards/c/CaitCageBrawler.java @@ -57,10 +57,10 @@ public final class CaitCageBrawler extends CardImpl { class CaitCageBrawlerEffect extends OneShotEffect { - public CaitCageBrawlerEffect() { + CaitCageBrawlerEffect() { super(Outcome.Benefit); this.staticText = "you and defending player each draw a card, then discard a card. Put two +1/+1 counters on " + - "{this} if you discarded the card with the highest mana value among those cards or tied for highest."; + "{this} if you discarded the card with the greatest mana value among those cards or tied for greatest"; } protected CaitCageBrawlerEffect(final CaitCageBrawlerEffect effect) { @@ -120,4 +120,4 @@ class CaitCageBrawlerEffect extends OneShotEffect { } return true; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/c/CallToServe.java b/Mage.Sets/src/mage/cards/c/CallToServe.java index 79343503e67..686b14ec6c4 100644 --- a/Mage.Sets/src/mage/cards/c/CallToServe.java +++ b/Mage.Sets/src/mage/cards/c/CallToServe.java @@ -17,6 +17,8 @@ import mage.filter.StaticFilters; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author Loki @@ -28,7 +30,7 @@ public final class CallToServe extends CardImpl { this.subtype.add(SubType.AURA); // Enchant nonblack creature - TargetPermanent auraTarget = new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK); + TargetPermanent auraTarget = new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); Ability ability = new EnchantAbility(auraTarget); diff --git a/Mage.Sets/src/mage/cards/c/CallToTheKindred.java b/Mage.Sets/src/mage/cards/c/CallToTheKindred.java index 4b2ff37cf46..57419f3606a 100644 --- a/Mage.Sets/src/mage/cards/c/CallToTheKindred.java +++ b/Mage.Sets/src/mage/cards/c/CallToTheKindred.java @@ -1,10 +1,10 @@ package mage.cards.c; import mage.abilities.Ability; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; import mage.abilities.keyword.EnchantAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.*; import mage.constants.CardType; import mage.constants.Outcome; @@ -13,7 +13,6 @@ import mage.constants.Zone; import mage.filter.common.FilterCreatureCard; import mage.filter.predicate.mageobject.SharesCreatureTypePredicate; import mage.game.Game; -import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetCard; @@ -41,7 +40,7 @@ public final class CallToTheKindred extends CardImpl { // At the beginning of your upkeep, you may look at the top five cards of your library. // If you do, you may put a creature card that shares a creature type with enchanted creature from among them onto the battlefield, // then you put the rest of those cards on the bottom of your library in any order. - this.addAbility(new OnEventTriggeredAbility(GameEvent.EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", new CallToTheKindredEffect(), true)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new CallToTheKindredEffect(), true)); } private CallToTheKindred(final CallToTheKindred card) { diff --git a/Mage.Sets/src/mage/cards/c/CallousOppressor.java b/Mage.Sets/src/mage/cards/c/CallousOppressor.java index 4b762b2cca9..15f3237b97c 100644 --- a/Mage.Sets/src/mage/cards/c/CallousOppressor.java +++ b/Mage.Sets/src/mage/cards/c/CallousOppressor.java @@ -21,6 +21,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetOpponent; import mage.util.CardUtil; @@ -50,7 +51,7 @@ public final class CallousOppressor extends CardImpl { SourceTappedCondition.TAPPED, "Gain control of target creature that isn't of the chosen type for as long as {this} remains tapped"); Ability ability = new SimpleActivatedAbility(effect, new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(new CallousOppressorFilter())); + ability.addTarget(new TargetPermanent(new CallousOppressorFilter())); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CallousSellSword.java b/Mage.Sets/src/mage/cards/c/CallousSellSword.java index a727344100e..43cffe99073 100644 --- a/Mage.Sets/src/mage/cards/c/CallousSellSword.java +++ b/Mage.Sets/src/mage/cards/c/CallousSellSword.java @@ -16,10 +16,11 @@ import mage.constants.Outcome; import mage.constants.SubType; import mage.counters.CounterType; import mage.filter.common.FilterAnyTarget; +import mage.filter.common.FilterPermanentOrPlayer; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.target.common.TargetAnyTarget; import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetPermanentOrPlayer; import java.util.UUID; @@ -28,7 +29,7 @@ import java.util.UUID; */ public final class CallousSellSword extends AdventureCard { - private static final FilterAnyTarget filterSecondTarget = new FilterAnyTarget("any other target"); + private static final FilterPermanentOrPlayer filterSecondTarget = new FilterAnyTarget("any other target"); private static final Hint hint = new ValueHint( "Creatures that died under your control this turn", CreaturesYouControlDiedCount.instance @@ -54,7 +55,7 @@ public final class CallousSellSword extends AdventureCard { // Target creature you control deals damage equal to its power to any other target. Then sacrifice it. this.getSpellCard().getSpellAbility().addEffect(new DamageWithPowerFromOneToAnotherTargetEffect()); this.getSpellCard().getSpellAbility().addTarget(new TargetControlledCreaturePermanent().setTargetTag(1)); - this.getSpellCard().getSpellAbility().addTarget(new TargetAnyTarget(1, 1, filterSecondTarget).setTargetTag(2)); + this.getSpellCard().getSpellAbility().addTarget(new TargetPermanentOrPlayer(filterSecondTarget).setTargetTag(2)); this.getSpellCard().getSpellAbility().addEffect(new CallousSellSwordSacrificeFirstTargetEffect().concatBy("Then")); this.finalizeAdventure(); diff --git a/Mage.Sets/src/mage/cards/c/Camouflage.java b/Mage.Sets/src/mage/cards/c/Camouflage.java index d192d4edc66..1e86a48d31e 100644 --- a/Mage.Sets/src/mage/cards/c/Camouflage.java +++ b/Mage.Sets/src/mage/cards/c/Camouflage.java @@ -1,12 +1,5 @@ package mage.cards.c; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility; import mage.abilities.condition.common.MyTurnCondition; @@ -17,9 +10,9 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.PhaseStep; -import mage.filter.predicate.Predicates; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.PermanentReferenceInCollectionPredicate; import mage.game.Game; import mage.game.combat.CombatGroup; @@ -28,11 +21,12 @@ 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.TargetPermanent; import mage.util.RandomUtil; +import java.util.*; + /** - * * @author L_J */ public final class Camouflage extends CardImpl { @@ -121,7 +115,7 @@ class CamouflageEffect extends ContinuousRuleModifyingEffectImpl { filter.add(Predicates.not(new PermanentReferenceInCollectionPredicate(spentBlockers, game))); } if (defender.chooseUse(Outcome.Neutral, "Make a new blocker pile? If not, all remaining piles stay empty. (remaining piles: " + (attackerCount - masterList.size()) + ')', source, game)) { - Target target = new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, filter, true); + Target target = new TargetPermanent(0, Integer.MAX_VALUE, filter, true); if (target.canChoose(defenderId, source, game)) { if (defender.chooseTarget(Outcome.Neutral, target, source, game)) { for (UUID creatureId : target.getTargets()) { @@ -171,7 +165,7 @@ class CamouflageEffect extends ContinuousRuleModifyingEffectImpl { } } } - + List> allPiles = masterMap.get(playerId); Set blockerIds = new HashSet<>(); for (List pile : allPiles) { diff --git a/Mage.Sets/src/mage/cards/c/CanalDredger.java b/Mage.Sets/src/mage/cards/c/CanalDredger.java index a17cda24833..e51ece4951a 100644 --- a/Mage.Sets/src/mage/cards/c/CanalDredger.java +++ b/Mage.Sets/src/mage/cards/c/CanalDredger.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -16,6 +15,8 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.target.common.TargetCardInYourGraveyard; +import java.util.UUID; + /** * * @author L_J @@ -31,7 +32,7 @@ public final class CanalDredger extends CardImpl { // TODO: Draft specific abilities not implemented // Draft Canal Dredger face up. - this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Draft Canal Dredger face up - not implemented."))); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Draft {this} face up - not implemented."))); // Each player passes the last card from each booster pack to a player who drafted a card named Canal Dredger. this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Each player passes the last card from each booster pack to a player who drafted a card named Canal Dredger - not implemented."))); diff --git a/Mage.Sets/src/mage/cards/c/Candletrap.java b/Mage.Sets/src/mage/cards/c/Candletrap.java index 4c580dceb43..b08de188b95 100644 --- a/Mage.Sets/src/mage/cards/c/Candletrap.java +++ b/Mage.Sets/src/mage/cards/c/Candletrap.java @@ -1,28 +1,27 @@ package mage.cards.c; -import java.util.UUID; - +import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.CovenCondition; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.ExileAttachedEffect; import mage.abilities.effects.common.PreventAllDamageByAttachedEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.hint.common.CovenHint; import mage.abilities.keyword.DefenderAbility; -import mage.constants.*; -import mage.target.common.TargetCreaturePermanent; -import mage.abilities.Ability; -import mage.abilities.effects.common.AttachEffect; -import mage.target.TargetPermanent; import mage.abilities.keyword.EnchantAbility; 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 weirddan455 */ public final class Candletrap extends CardImpl { @@ -36,21 +35,22 @@ public final class Candletrap extends CardImpl { TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // Enchanted creature has defender. this.addAbility(new SimpleStaticAbility(new GainAbilityAttachedEffect(DefenderAbility.getInstance(), AttachmentType.AURA))); // Prevent all combat damage that would be dealt by enchanted creature. - this.addAbility(new SimpleStaticAbility(new PreventAllDamageByAttachedEffect(Duration.WhileOnBattlefield, "enchanted creature", true))); + this.addAbility(new SimpleStaticAbility(new PreventAllDamageByAttachedEffect( + Duration.WhileOnBattlefield, "enchanted creature", true + ))); // Coven — {2}{W}, Sacrifice Candletrap: Exile enchanted creature. Activate only if you control three or more creatures with different powers. - ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new ExileAttachedEffect(), new ManaCostsImpl<>("{2}{W}"), CovenCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new ExileAttachedEffect(), new ManaCostsImpl<>("{2}{W}"), CovenCondition.instance + ); ability.addCost(new SacrificeSourceCost()); - ability.setAbilityWord(AbilityWord.COVEN); - ability.addHint(CovenHint.instance); - this.addAbility(ability); + this.addAbility(ability.setAbilityWord(AbilityWord.COVEN).addHint(CovenHint.instance)); } private Candletrap(final Candletrap card) { diff --git a/Mage.Sets/src/mage/cards/c/CankerousThirst.java b/Mage.Sets/src/mage/cards/c/CankerousThirst.java index dc1ecd5327c..9762cc3e68f 100644 --- a/Mage.Sets/src/mage/cards/c/CankerousThirst.java +++ b/Mage.Sets/src/mage/cards/c/CankerousThirst.java @@ -19,6 +19,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; @@ -34,8 +35,8 @@ public final class CankerousThirst extends CardImpl { // If {B} was spent to cast Cankerous Thirst, you may have target creature get -3/-3 until end of turn. If {G} was spent to cast Cankerous Thirst, you may have target creature get +3/+3 until end of turn. this.getSpellAbility().addEffect(new CankerousThirstEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (1th effect -3/-3)"))); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (2nd effect +3/+3)"))); + this.getSpellAbility().addTarget(new TargetPermanent(new FilterCreaturePermanent("creature (1th effect -3/-3)"))); + this.getSpellAbility().addTarget(new TargetPermanent(new FilterCreaturePermanent("creature (2nd effect +3/+3)"))); this.getSpellAbility().addEffect(new InfoEffect("(Do both if {B}{G} was spent.)")); } diff --git a/Mage.Sets/src/mage/cards/c/CantinaBand.java b/Mage.Sets/src/mage/cards/c/CantinaBand.java index 36d2de81d0a..71088199aa6 100644 --- a/Mage.Sets/src/mage/cards/c/CantinaBand.java +++ b/Mage.Sets/src/mage/cards/c/CantinaBand.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,7 +39,7 @@ public final class CantinaBand extends CardImpl { // {T}, {1}: Tap target nonartifact creature. Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new GenericManaCost(1)); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CaoCaoLordOfWei.java b/Mage.Sets/src/mage/cards/c/CaoCaoLordOfWei.java index 095a835be06..f199fe1523d 100644 --- a/Mage.Sets/src/mage/cards/c/CaoCaoLordOfWei.java +++ b/Mage.Sets/src/mage/cards/c/CaoCaoLordOfWei.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; @@ -13,17 +11,17 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; -import mage.constants.Zone; import mage.target.common.TargetOpponent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class CaoCaoLordOfWei extends CardImpl { public CaoCaoLordOfWei(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.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.SOLDIER); @@ -32,9 +30,11 @@ public final class CaoCaoLordOfWei extends CardImpl { this.toughness = new MageInt(3); // {tap}: Target opponent discards two cards. Activate this ability only during your turn, before attackers are declared. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new DiscardTargetEffect(2), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new DiscardTargetEffect(2), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance + ); ability.addTarget(new TargetOpponent()); - this.addAbility(ability); + this.addAbility(ability); } private CaoCaoLordOfWei(final CaoCaoLordOfWei card) { diff --git a/Mage.Sets/src/mage/cards/c/CapriciousSorcerer.java b/Mage.Sets/src/mage/cards/c/CapriciousSorcerer.java index f2fed9e7586..3577a8dfbad 100644 --- a/Mage.Sets/src/mage/cards/c/CapriciousSorcerer.java +++ b/Mage.Sets/src/mage/cards/c/CapriciousSorcerer.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; @@ -12,25 +10,27 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** - * * @author fireshoes */ public final class CapriciousSorcerer extends CardImpl { public CapriciousSorcerer(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.subtype.add(SubType.WIZARD); this.power = new MageInt(1); this.toughness = new MageInt(1); // {tap}: Capricious Sorcerer deals 1 damage to any target. Activate this ability only during your turn, before attackers are declared. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new DamageTargetEffect(1), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new DamageTargetEffect(1), new TapSourceCost(), + MyTurnBeforeAttackersDeclaredCondition.instance + ); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CaptivatingCrew.java b/Mage.Sets/src/mage/cards/c/CaptivatingCrew.java index ec304038f23..6c4450048d7 100644 --- a/Mage.Sets/src/mage/cards/c/CaptivatingCrew.java +++ b/Mage.Sets/src/mage/cards/c/CaptivatingCrew.java @@ -18,8 +18,11 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author TheElk801 @@ -42,7 +45,7 @@ public final class CaptivatingCrew extends CardImpl { effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn); effect.setText("It gains haste until end of turn"); ability.addEffect(effect); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CapturedByTheConsulate.java b/Mage.Sets/src/mage/cards/c/CapturedByTheConsulate.java index 7e4ed9447fe..7754c03bd08 100644 --- a/Mage.Sets/src/mage/cards/c/CapturedByTheConsulate.java +++ b/Mage.Sets/src/mage/cards/c/CapturedByTheConsulate.java @@ -26,6 +26,8 @@ import mage.target.targetpointer.FixedTarget; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author LevelX2 */ @@ -36,7 +38,7 @@ public final class CapturedByTheConsulate extends CardImpl { this.subtype.add(SubType.AURA); // Enchant creature you don't control - TargetPermanent auraTarget = new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL); + TargetPermanent auraTarget = new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.UnboostCreature)); Ability ability = new EnchantAbility(auraTarget); diff --git a/Mage.Sets/src/mage/cards/c/Carom.java b/Mage.Sets/src/mage/cards/c/Carom.java index 42724fb9131..9cebd978664 100644 --- a/Mage.Sets/src/mage/cards/c/Carom.java +++ b/Mage.Sets/src/mage/cards/c/Carom.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.effects.RedirectionEffect; @@ -10,14 +8,15 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.other.AnotherTargetPredicate; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author Skyler Sell */ public final class Carom extends CardImpl { @@ -28,16 +27,8 @@ public final class Carom extends CardImpl { // The next 1 damage that would be dealt to target creature this turn is dealt to another target creature instead. // Draw a card. this.getSpellAbility().addEffect(new CaromEffect(Duration.EndOfTurn, 1)); - - TargetCreaturePermanent target = new TargetCreaturePermanent(); - target.setTargetTag(1); - this.getSpellAbility().addTarget(target); - - FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature (damage is redirected to)"); - filter.add(new AnotherTargetPredicate(2)); - TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter); - target2.setTargetTag(2); - this.getSpellAbility().addTarget(target2); + this.getSpellAbility().addTarget(new TargetCreaturePermanent().withChooseHint("to redirect from").setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2).withChooseHint("to redirect to").setTargetTag(2)); this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("
")); } diff --git a/Mage.Sets/src/mage/cards/c/CaseOfTheBurningMasks.java b/Mage.Sets/src/mage/cards/c/CaseOfTheBurningMasks.java index 7c6fad69706..2a25533c19b 100644 --- a/Mage.Sets/src/mage/cards/c/CaseOfTheBurningMasks.java +++ b/Mage.Sets/src/mage/cards/c/CaseOfTheBurningMasks.java @@ -7,7 +7,7 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.SolvedSourceCondition; import mage.abilities.costs.common.SacrificeSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.ExileTopXMayPlayUntilEffect; import mage.abilities.hint.common.CaseSolvedHint; @@ -45,7 +45,7 @@ public final class CaseOfTheBurningMasks extends CardImpl { initialAbility.addTarget(new TargetOpponentsCreaturePermanent()); // To solve -- Three or more sources you controlled dealt damage this turn. // Solved -- Sacrifice this Case: Exile the top three cards of your library. Choose one of them. You may play that card this turn. - Ability solvedAbility = new ConditionalActivatedAbility( + Ability solvedAbility = new ActivateIfConditionActivatedAbility( new ExileTopXMayPlayUntilEffect(3, true, Duration.EndOfTurn), new SacrificeSourceCost().setText("sacrifice this Case"), SolvedSourceCondition.SOLVED ); diff --git a/Mage.Sets/src/mage/cards/c/CaseOfTheFilchedFalcon.java b/Mage.Sets/src/mage/cards/c/CaseOfTheFilchedFalcon.java index 2acca20cc61..e3785e4bc2b 100644 --- a/Mage.Sets/src/mage/cards/c/CaseOfTheFilchedFalcon.java +++ b/Mage.Sets/src/mage/cards/c/CaseOfTheFilchedFalcon.java @@ -11,7 +11,7 @@ import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.condition.common.SolvedSourceCondition; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.continuous.BecomesCreatureTargetEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.effects.keyword.InvestigateEffect; @@ -50,7 +50,7 @@ public final class CaseOfTheFilchedFalcon extends CardImpl { Condition toSolveCondition = new PermanentsOnTheBattlefieldCondition( filter, ComparisonType.MORE_THAN, 2, true); // Solved -- {2}{U}, Sacrifice this Case: Put four +1/+1 counters on target noncreature artifact. It becomes a 0/0 Bird creature with flying in addition to its other types. - Ability solvedAbility = new ConditionalActivatedAbility( + Ability solvedAbility = new ActivateIfConditionActivatedAbility( new AddCountersTargetEffect(CounterType.P1P1.createInstance(4)), new ManaCostsImpl<>("{2}{U}"), SolvedSourceCondition.SOLVED); solvedAbility.addEffect(new BecomesCreatureTargetEffect(new CaseOfTheFilchedFalconToken(), diff --git a/Mage.Sets/src/mage/cards/c/CaseOfTheStashedSkeleton.java b/Mage.Sets/src/mage/cards/c/CaseOfTheStashedSkeleton.java index 0759772440d..3f9293be0de 100644 --- a/Mage.Sets/src/mage/cards/c/CaseOfTheStashedSkeleton.java +++ b/Mage.Sets/src/mage/cards/c/CaseOfTheStashedSkeleton.java @@ -10,7 +10,7 @@ import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.condition.common.SolvedSourceCondition; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; import mage.abilities.hint.common.CaseSolvedHint; @@ -52,7 +52,7 @@ public final class CaseOfTheStashedSkeleton extends CardImpl { Condition toSolveCondition = new PermanentsOnTheBattlefieldCondition( filter, ComparisonType.EQUAL_TO, 0, true); // Solved -- {1}{B}, Sacrifice this Case: Search your library for a card, put it into your hand, then shuffle. Activate only as a sorcery. - Ability solvedAbility = new ConditionalActivatedAbility( + Ability solvedAbility = new ActivateIfConditionActivatedAbility( new SearchLibraryPutInHandEffect(new TargetCardInLibrary(), false) .setText("Search your library for a card, put it into your hand, then shuffle. Activate only as a sorcery."), new ManaCostsImpl<>("{1}{B}"), diff --git a/Mage.Sets/src/mage/cards/c/CaseOfTheUneatenFeast.java b/Mage.Sets/src/mage/cards/c/CaseOfTheUneatenFeast.java index 395749437da..252bb31b6c4 100644 --- a/Mage.Sets/src/mage/cards/c/CaseOfTheUneatenFeast.java +++ b/Mage.Sets/src/mage/cards/c/CaseOfTheUneatenFeast.java @@ -9,7 +9,7 @@ import mage.abilities.condition.Condition; import mage.abilities.condition.common.SolvedSourceCondition; import mage.abilities.condition.common.YouGainedLifeCondition; import mage.abilities.costs.common.SacrificeSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.hint.common.CaseSolvedHint; @@ -47,7 +47,7 @@ public final class CaseOfTheUneatenFeast extends CardImpl { new GainLifeEffect(1), StaticFilters.FILTER_PERMANENT_CREATURE); // To solve -- You've gained 5 or more life this turn. // Solved -- Sacrifice this Case: Creature cards in your graveyard gain "You may cast this card from your graveyard" until end of turn. - Ability solvedAbility = new ConditionalActivatedAbility( + Ability solvedAbility = new ActivateIfConditionActivatedAbility( new CaseOfTheUneatenFeastEffect(), new SacrificeSourceCost().setText("sacrifice this Case"), SolvedSourceCondition.SOLVED); diff --git a/Mage.Sets/src/mage/cards/c/CastDown.java b/Mage.Sets/src/mage/cards/c/CastDown.java index ce9bb242d86..a9b95cf29fd 100644 --- a/Mage.Sets/src/mage/cards/c/CastDown.java +++ b/Mage.Sets/src/mage/cards/c/CastDown.java @@ -7,6 +7,7 @@ import mage.constants.CardType; import mage.constants.SuperType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -23,7 +24,7 @@ public final class CastDown extends CardImpl { // Destroy target nonlegendary creature. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private CastDown(final CastDown card){ @@ -33,4 +34,4 @@ public final class CastDown extends CardImpl { public CastDown copy(){ return new CastDown(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/c/CatapultSquad.java b/Mage.Sets/src/mage/cards/c/CatapultSquad.java index ab28ba6efdd..b9cb309fed3 100644 --- a/Mage.Sets/src/mage/cards/c/CatapultSquad.java +++ b/Mage.Sets/src/mage/cards/c/CatapultSquad.java @@ -15,6 +15,7 @@ import mage.constants.Zone; import mage.filter.common.FilterAttackingOrBlockingCreature; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; @@ -40,7 +41,7 @@ public final class CatapultSquad extends CardImpl { // Tap two untapped Soldiers you control: Catapult Squad deals 2 damage to target attacking or blocking creature. Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(2), new TapTargetCost(new TargetControlledPermanent(2, 2, filter, false))); - ability.addTarget(new TargetCreaturePermanent(new FilterAttackingOrBlockingCreature())); + ability.addTarget(new TargetPermanent(new FilterAttackingOrBlockingCreature())); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CathedralAcolyte.java b/Mage.Sets/src/mage/cards/c/CathedralAcolyte.java index 47182f4df5d..21d77466332 100644 --- a/Mage.Sets/src/mage/cards/c/CathedralAcolyte.java +++ b/Mage.Sets/src/mage/cards/c/CathedralAcolyte.java @@ -27,7 +27,7 @@ import java.util.UUID; */ public final class CathedralAcolyte extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); - private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("creature that entered the battlefield this turn"); + private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("creature that entered this turn"); static { filter.add(CounterAnyPredicate.instance); diff --git a/Mage.Sets/src/mage/cards/c/CathedralMembrane.java b/Mage.Sets/src/mage/cards/c/CathedralMembrane.java index 923776d1012..9514da271f7 100644 --- a/Mage.Sets/src/mage/cards/c/CathedralMembrane.java +++ b/Mage.Sets/src/mage/cards/c/CathedralMembrane.java @@ -1,21 +1,22 @@ - package mage.cards.c; import mage.MageInt; +import mage.MageObjectReference; import mage.abilities.Ability; -import mage.abilities.common.ZoneChangeTriggeredAbility; +import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.DefenderAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.TurnPhase; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; -import mage.watchers.Watcher; +import mage.watchers.common.BlockedAttackerWatcher; -import java.util.HashSet; -import java.util.Set; import java.util.UUID; /** @@ -35,8 +36,7 @@ public final class CathedralMembrane extends CardImpl { this.addAbility(DefenderAbility.getInstance()); // When Cathedral Membrane dies during combat, it deals 6 damage to each creature it blocked this combat. - this.addAbility(new CathedralMembraneAbility(), new CathedralMembraneWatcher()); - + this.addAbility(new CathedralMembraneAbility()); } private CathedralMembrane(final CathedralMembrane card) { @@ -49,10 +49,11 @@ public final class CathedralMembrane extends CardImpl { } } -class CathedralMembraneAbility extends ZoneChangeTriggeredAbility { +class CathedralMembraneAbility extends DiesSourceTriggeredAbility { CathedralMembraneAbility() { - super(Zone.BATTLEFIELD, Zone.GRAVEYARD, new CathedralMembraneEffect(), "When {this} dies during combat, ", false); + super(new CathedralMembraneEffect()); + setTriggerPhrase("When {this} dies during combat, "); } private CathedralMembraneAbility(CathedralMembraneAbility ability) { @@ -66,12 +67,7 @@ class CathedralMembraneAbility extends ZoneChangeTriggeredAbility { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (super.checkTrigger(event, game)) { - if (game.getTurnPhaseType() == TurnPhase.COMBAT) { - return true; - } - } - return false; + return game.getTurnPhaseType() == TurnPhase.COMBAT && super.checkTrigger(event, game); } } @@ -94,41 +90,13 @@ class CathedralMembraneEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - CathedralMembraneWatcher watcher = game.getState().getWatcher(CathedralMembraneWatcher.class, source.getSourceId()); - if (watcher != null) { - for (UUID uuid : watcher.getBlockedCreatures()) { - Permanent permanent = game.getPermanent(uuid); - if (permanent != null) { - permanent.damage(6, source.getSourceId(), source, game, false, true); - } + Permanent permanent = source.getSourcePermanentOrLKI(game); + BlockedAttackerWatcher watcher = game.getState().getWatcher(BlockedAttackerWatcher.class); + if (watcher != null && permanent != null) { + for (Permanent p : watcher.getBlockedCreatures(new MageObjectReference(permanent, game), game)) { + p.damage(6, source.getSourceId(), source, game, false, true); } } return true; } } - -class CathedralMembraneWatcher extends Watcher { - - private final Set blockedCreatures = new HashSet<>(); - - CathedralMembraneWatcher() { - super(WatcherScope.CARD); - } - - @Override - public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.BLOCKER_DECLARED && event.getSourceId().equals(sourceId)) { - blockedCreatures.add(event.getTargetId()); - } - } - - @Override - public void reset() { - super.reset(); - blockedCreatures.clear(); - } - - Set getBlockedCreatures() { - return blockedCreatures; - } -} diff --git a/Mage.Sets/src/mage/cards/c/CattiBrieOfMithralHall.java b/Mage.Sets/src/mage/cards/c/CattiBrieOfMithralHall.java index f0fe906e2ba..dc8c128822f 100644 --- a/Mage.Sets/src/mage/cards/c/CattiBrieOfMithralHall.java +++ b/Mage.Sets/src/mage/cards/c/CattiBrieOfMithralHall.java @@ -20,6 +20,7 @@ import mage.constants.*; import mage.counters.CounterType; import mage.filter.common.FilterAttackingOrBlockingCreature; import mage.game.Game; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -59,7 +60,7 @@ public final class CattiBrieOfMithralHall extends CardImpl { // {1}, Remove all +1/+1 counters from Catti-brie: It deals X damage to target attacking or blocking creature an opponent controls, where X is the number of counters removed this way. Ability damageAbility = new SimpleActivatedAbility( new DamageTargetEffect(CattiBrieRemovedCounterValue.instance).setText("it deals X damage to target attacking or blocking creature an opponent controls, where X is the number of counters removed this way"), new ManaCostsImpl<>("{1}")); - damageAbility.addTarget(new TargetCreaturePermanent(filter)); + damageAbility.addTarget(new TargetPermanent(filter)); damageAbility.addCost(new RemoveAllCountersSourceCost(CounterType.P1P1)); this.addAbility(damageAbility); diff --git a/Mage.Sets/src/mage/cards/c/CauldronOfSouls.java b/Mage.Sets/src/mage/cards/c/CauldronOfSouls.java index 49d6eac6183..7c7add9d41f 100644 --- a/Mage.Sets/src/mage/cards/c/CauldronOfSouls.java +++ b/Mage.Sets/src/mage/cards/c/CauldronOfSouls.java @@ -1,23 +1,19 @@ - package mage.cards.c; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.PersistAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Zone; -import mage.filter.StaticFilters; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class CauldronOfSouls extends CardImpl { @@ -26,12 +22,13 @@ public final class CauldronOfSouls extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}"); // {tap}: Choose any number of target creatures. Each of those creatures gains persist until end of turn. - Effect effect = new GainAbilityTargetEffect(new PersistAbility(), Duration.EndOfTurn); - effect.setText("choose any number of target creatures. Each of those creatures gains persist until end of turn"); - Ability ability = new SimpleActivatedAbility(effect, new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(0, Integer.MAX_VALUE, StaticFilters.FILTER_PERMANENT_CREATURE, false)); + Ability ability = new SimpleActivatedAbility( + new GainAbilityTargetEffect(new PersistAbility(), Duration.EndOfTurn) + .setText("choose any number of target creatures. Each of those creatures gains persist until end of turn"), + new TapSourceCost() + ); + ability.addTarget(new TargetCreaturePermanent(0, Integer.MAX_VALUE)); this.addAbility(ability); - } private CauldronOfSouls(final CauldronOfSouls card) { diff --git a/Mage.Sets/src/mage/cards/c/CavernousMaw.java b/Mage.Sets/src/mage/cards/c/CavernousMaw.java index 32379092ed1..adb526ed19f 100644 --- a/Mage.Sets/src/mage/cards/c/CavernousMaw.java +++ b/Mage.Sets/src/mage/cards/c/CavernousMaw.java @@ -3,7 +3,7 @@ package mage.cards.c; import mage.abilities.Ability; import mage.abilities.condition.IntCompareCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.dynamicvalue.AdditiveDynamicValue; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; @@ -41,7 +41,7 @@ public final class CavernousMaw extends CardImpl { this.addAbility(new ColorlessManaAbility()); // {2}: Cavernous Maw becomes a 3/3 Elemental creature until end of turn. It's still a Cave land. Activate only if the number of other Caves you control plus the number of Cave cards in your graveyard is three or greater. - this.addAbility(new ConditionalActivatedAbility( + this.addAbility(new ActivateIfConditionActivatedAbility( new BecomesCreatureSourceEffect( new CreatureToken(3, 3, "3/3 Elemental creature") .withSubType(SubType.ELEMENTAL), diff --git a/Mage.Sets/src/mage/cards/c/CelestialEnforcer.java b/Mage.Sets/src/mage/cards/c/CelestialEnforcer.java index ef5772bcd21..03dc253156f 100644 --- a/Mage.Sets/src/mage/cards/c/CelestialEnforcer.java +++ b/Mage.Sets/src/mage/cards/c/CelestialEnforcer.java @@ -13,7 +13,6 @@ 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; @@ -45,7 +44,7 @@ public final class CelestialEnforcer extends CardImpl { // {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 + new TapTargetEffect(), new ManaCostsImpl<>("{1}{W}"), condition ); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent()); diff --git a/Mage.Sets/src/mage/cards/c/CelestialRegulator.java b/Mage.Sets/src/mage/cards/c/CelestialRegulator.java index f499ded4111..305d2c93a43 100644 --- a/Mage.Sets/src/mage/cards/c/CelestialRegulator.java +++ b/Mage.Sets/src/mage/cards/c/CelestialRegulator.java @@ -17,8 +17,11 @@ import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.permanent.CounterAnyPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * * @author weirddan455 @@ -39,7 +42,7 @@ public final class CelestialRegulator extends CardImpl { // When Celestial Regulator enters the battlefield, choose target creature you don't control and tap it. // If you control a creature with a counter on it, the chosen creature doesn't untap during its controller's next untap step. Ability ability = new EntersBattlefieldTriggeredAbility(new CelestialRegulatorEffect()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + ability.addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CennsTactician.java b/Mage.Sets/src/mage/cards/c/CennsTactician.java index 2bc13f43866..5b9596af83c 100644 --- a/Mage.Sets/src/mage/cards/c/CennsTactician.java +++ b/Mage.Sets/src/mage/cards/c/CennsTactician.java @@ -16,6 +16,7 @@ import mage.constants.*; import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -39,7 +40,7 @@ public final class CennsTactician extends CardImpl { // {W}, {tap}: Put a +1/+1 counter on target Soldier creature. Ability ability = new SimpleActivatedAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), new ColoredManaCost(ColoredManaSymbol.W)); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filterSoldier)); + ability.addTarget(new TargetPermanent(filterSoldier)); this.addAbility(ability); // Each creature you control with a +1/+1 counter on it can block an additional creature each combat. diff --git a/Mage.Sets/src/mage/cards/c/CentaurArcher.java b/Mage.Sets/src/mage/cards/c/CentaurArcher.java index b848646cc85..5eda6670a21 100644 --- a/Mage.Sets/src/mage/cards/c/CentaurArcher.java +++ b/Mage.Sets/src/mage/cards/c/CentaurArcher.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -39,7 +40,7 @@ public final class CentaurArcher extends CardImpl { // {tap}: Centaur Archer deals 1 damage to target creature with flying. Ability activatedAbility = new SimpleActivatedAbility(new DamageTargetEffect(1), new TapSourceCost()); - activatedAbility.addTarget(new TargetCreaturePermanent(filter)); + activatedAbility.addTarget(new TargetPermanent(filter)); this.addAbility(activatedAbility); } diff --git a/Mage.Sets/src/mage/cards/c/CentaurGarden.java b/Mage.Sets/src/mage/cards/c/CentaurGarden.java index 1bf1fa1b913..4b21c3b0742 100644 --- a/Mage.Sets/src/mage/cards/c/CentaurGarden.java +++ b/Mage.Sets/src/mage/cards/c/CentaurGarden.java @@ -5,7 +5,7 @@ import mage.abilities.condition.common.ThresholdCondition; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DamageControllerEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.mana.GreenManaAbility; @@ -32,7 +32,7 @@ public final class CentaurGarden extends CardImpl { this.addAbility(manaAbility); // Threshold - {G}, {tap}, Sacrifice Centaur Garden: Target creature gets +3/+3 until end of turn. Activate this ability only if seven or more cards are in your graveyard. - Ability thresholdAbility = new ConditionalActivatedAbility( + Ability thresholdAbility = new ActivateIfConditionActivatedAbility( new BoostTargetEffect(3, 3, Duration.EndOfTurn), new ManaCostsImpl<>("{G}"), ThresholdCondition.instance ); diff --git a/Mage.Sets/src/mage/cards/c/CentaurPeacemaker.java b/Mage.Sets/src/mage/cards/c/CentaurPeacemaker.java index 45e10757f0b..d14039c1307 100644 --- a/Mage.Sets/src/mage/cards/c/CentaurPeacemaker.java +++ b/Mage.Sets/src/mage/cards/c/CentaurPeacemaker.java @@ -1,20 +1,16 @@ package mage.cards.c; -import java.util.Objects; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.effects.OneShotEffect; -import mage.constants.SubType; +import mage.abilities.effects.common.GainLifeAllEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.game.Game; +import mage.constants.SubType; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class CentaurPeacemaker extends CardImpl { @@ -28,9 +24,7 @@ public final class CentaurPeacemaker extends CardImpl { this.toughness = new MageInt(3); // When Centaur Mediator enters the battlefield, each player gains 4 life. - this.addAbility(new EntersBattlefieldTriggeredAbility( - new CentaurMediatorEffect() - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeAllEffect(4))); } private CentaurPeacemaker(final CentaurPeacemaker card) { @@ -42,32 +36,3 @@ public final class CentaurPeacemaker extends CardImpl { return new CentaurPeacemaker(this); } } - -class CentaurMediatorEffect extends OneShotEffect { - - CentaurMediatorEffect() { - super(Outcome.GainLife); - staticText = "each player gains 4 life."; - } - - private CentaurMediatorEffect(final CentaurMediatorEffect effect) { - super(effect); - } - - @Override - public CentaurMediatorEffect copy() { - return new CentaurMediatorEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - game.getState().getPlayersInRange( - source.getControllerId(), game) - .stream() - .map(game::getPlayer) - .filter(Objects::nonNull) - .forEachOrdered(player -> player.gainLife(4, game, source)); - return true; - } - -} diff --git a/Mage.Sets/src/mage/cards/c/CephalidColiseum.java b/Mage.Sets/src/mage/cards/c/CephalidColiseum.java index 7f8d92d1ecd..4710981fd81 100644 --- a/Mage.Sets/src/mage/cards/c/CephalidColiseum.java +++ b/Mage.Sets/src/mage/cards/c/CephalidColiseum.java @@ -5,7 +5,7 @@ import mage.abilities.condition.common.ThresholdCondition; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DamageControllerEffect; import mage.abilities.effects.common.DrawDiscardTargetEffect; import mage.abilities.mana.BlueManaAbility; @@ -31,7 +31,7 @@ public final class CephalidColiseum extends CardImpl { this.addAbility(manaAbility); // Threshold - {U}, {tap}, Sacrifice Cephalid Coliseum: Target player draws three cards, then discards three cards. Activate this ability only if seven or more cards are in your graveyard. - Ability thresholdAbility = new ConditionalActivatedAbility( + Ability thresholdAbility = new ActivateIfConditionActivatedAbility( new DrawDiscardTargetEffect(3, 3), new ManaCostsImpl<>("{U}"), ThresholdCondition.instance ); diff --git a/Mage.Sets/src/mage/cards/c/CephalidRetainer.java b/Mage.Sets/src/mage/cards/c/CephalidRetainer.java index 03935c83147..04e5316d61b 100644 --- a/Mage.Sets/src/mage/cards/c/CephalidRetainer.java +++ b/Mage.Sets/src/mage/cards/c/CephalidRetainer.java @@ -16,6 +16,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -39,7 +40,7 @@ public final class CephalidRetainer extends CardImpl { // {U}{U}: Tap target creature without flying. Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new ManaCostsImpl<>("{U}{U}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CerebralVortex.java b/Mage.Sets/src/mage/cards/c/CerebralVortex.java index 0b12819ff69..920382b2bd7 100644 --- a/Mage.Sets/src/mage/cards/c/CerebralVortex.java +++ b/Mage.Sets/src/mage/cards/c/CerebralVortex.java @@ -10,7 +10,6 @@ import mage.constants.Outcome; import mage.constants.WatcherScope; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.players.Player; import mage.target.TargetPlayer; import mage.watchers.Watcher; @@ -48,7 +47,7 @@ class CerebralVortexEffect extends OneShotEffect { CerebralVortexEffect() { super(Outcome.Damage); - this.staticText = ", then Cerebral Vortex deals damage to that player equal to the number of cards they've drawn this turn"; + this.staticText = ", then {this} deals damage to that player equal to the number of cards they've drawn this turn"; } private CerebralVortexEffect(final CerebralVortexEffect effect) { diff --git a/Mage.Sets/src/mage/cards/c/CetaSanctuary.java b/Mage.Sets/src/mage/cards/c/CetaSanctuary.java index d995234fe7f..a5f2d20753e 100644 --- a/Mage.Sets/src/mage/cards/c/CetaSanctuary.java +++ b/Mage.Sets/src/mage/cards/c/CetaSanctuary.java @@ -1,17 +1,16 @@ package mage.cards.c; -import java.util.UUID; import mage.ObjectColor; -import mage.abilities.Ability; -import mage.abilities.common.SanctuaryInterveningIfTriggeredAbility; +import mage.abilities.common.SanctuaryTriggeredAbility; import mage.abilities.effects.common.DrawDiscardControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class CetaSanctuary extends CardImpl { @@ -20,12 +19,12 @@ public final class CetaSanctuary extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); // At the beginning of your upkeep, if you control a red or green permanent, draw a card, then discard a card. If you control a red permanent and a green permanent, instead draw two cards, then discard a card. - Ability ability = new SanctuaryInterveningIfTriggeredAbility( - new DrawDiscardControllerEffect(1, 1), new DrawDiscardControllerEffect(2, 1), ObjectColor.GREEN, ObjectColor.RED, - "At the beginning of your upkeep, if you control a red or green permanent, draw a card, then discard a card. " - + "If you control a red permanent and a green permanent, instead draw two cards, then discard a card." - ); - this.addAbility(ability); + this.addAbility(new SanctuaryTriggeredAbility( + new DrawDiscardControllerEffect(1, 1), + new DrawDiscardControllerEffect(2, 1), + ObjectColor.GREEN, ObjectColor.RED, "draw a card, then discard a card. " + + "If you control a red permanent and a green permanent, instead draw two cards, then discard a card." + )); } private CetaSanctuary(final CetaSanctuary card) { diff --git a/Mage.Sets/src/mage/cards/c/Cetavolver.java b/Mage.Sets/src/mage/cards/c/Cetavolver.java index a5da484d969..de202943a46 100644 --- a/Mage.Sets/src/mage/cards/c/Cetavolver.java +++ b/Mage.Sets/src/mage/cards/c/Cetavolver.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.condition.common.KickedCostCondition; @@ -14,10 +13,12 @@ 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.counters.CounterType; +import java.util.UUID; + /** * * @author Loki @@ -39,7 +40,7 @@ public final class Cetavolver extends CardImpl { // If Cetavolver was kicked with its {1}{R} kicker, it enters with two +1/+1 counters on it and with first strike. EntersBattlefieldAbility ability1 = new EntersBattlefieldAbility( new AddCountersSourceEffect(CounterType.P1P1.createInstance(2),false), - new KickedCostCondition("{1}{R}"), "If Cetavolver was kicked with its {1}{R} kicker, it enters with two +1/+1 counters on it and with first strike.", + new KickedCostCondition("{1}{R}"), "If {this} was kicked with its {1}{R} kicker, it enters with two +1/+1 counters on it and with first strike.", "{this} enters with two +1/+1 counters on it and with first strike"); ((EntersBattlefieldEffect)ability1.getEffects().get(0)).addEffect(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.WhileOnBattlefield)); this.addAbility(ability1); @@ -47,7 +48,7 @@ public final class Cetavolver extends CardImpl { // If Cetavolver was kicked with its {G} kicker, it enters with a +1/+1 counter on it and with trample. EntersBattlefieldAbility ability2 = new EntersBattlefieldAbility( new AddCountersSourceEffect(CounterType.P1P1.createInstance(1),false), new KickedCostCondition("{G}"), - "If Cetavolver was kicked with its {G} kicker, it enters with a +1/+1 counter on it and with trample.", + "If {this} was kicked with its {G} kicker, it enters with a +1/+1 counter on it and with trample.", "{this} enters with a +1/+1 counter on it and with trample"); ((EntersBattlefieldEffect)ability2.getEffects().get(0)).addEffect(new GainAbilitySourceEffect(TrampleAbility.getInstance(), Duration.WhileOnBattlefield)); this.addAbility(ability2); diff --git a/Mage.Sets/src/mage/cards/c/ChainedBrute.java b/Mage.Sets/src/mage/cards/c/ChainedBrute.java index dd39e3422ba..dc5aa46ba61 100644 --- a/Mage.Sets/src/mage/cards/c/ChainedBrute.java +++ b/Mage.Sets/src/mage/cards/c/ChainedBrute.java @@ -13,9 +13,7 @@ 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; @@ -36,8 +34,7 @@ public final class ChainedBrute extends CardImpl { // {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 + new UntapSourceEffect(), new GenericManaCost(1), MyTurnCondition.instance ); ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/c/Chainflinger.java b/Mage.Sets/src/mage/cards/c/Chainflinger.java index df3b4314f7f..5f11b2d40f3 100644 --- a/Mage.Sets/src/mage/cards/c/Chainflinger.java +++ b/Mage.Sets/src/mage/cards/c/Chainflinger.java @@ -6,7 +6,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.ThresholdCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -36,7 +36,7 @@ public final class Chainflinger extends CardImpl { this.addAbility(ability); // Threshold - {2}{R}, {tap}: Chainflinger deals 2 damage to any target. Activate this ability only if seven or more cards are in your graveyard. - Ability thresholdAbility = new ConditionalActivatedAbility( + Ability thresholdAbility = new ActivateIfConditionActivatedAbility( new DamageTargetEffect(2), new ManaCostsImpl<>("{2}{R}"), ThresholdCondition.instance ); thresholdAbility.addCost(new TapSourceCost()); diff --git a/Mage.Sets/src/mage/cards/c/Chandler.java b/Mage.Sets/src/mage/cards/c/Chandler.java index 9a87640b874..8da8844cfe1 100644 --- a/Mage.Sets/src/mage/cards/c/Chandler.java +++ b/Mage.Sets/src/mage/cards/c/Chandler.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.SuperType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class Chandler extends CardImpl { // {R}{R}{R}, {tap}: Destroy target artifact creature. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new ManaCostsImpl<>("{R}{R}{R}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/ChandrasIncinerator.java b/Mage.Sets/src/mage/cards/c/ChandrasIncinerator.java index 5fd71a51efb..9c439931724 100644 --- a/Mage.Sets/src/mage/cards/c/ChandrasIncinerator.java +++ b/Mage.Sets/src/mage/cards/c/ChandrasIncinerator.java @@ -3,21 +3,21 @@ 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.common.SourceDealsNoncombatDamageToOpponentTriggeredAbility; +import mage.abilities.dynamicvalue.common.SavedDamageValue; 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.target.targetadjustment.ThatPlayerControlsTargetAdjuster; import mage.util.CardUtil; import mage.watchers.Watcher; @@ -46,7 +46,10 @@ public final class ChandrasIncinerator extends CardImpl { 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()); + Ability ability = new SourceDealsNoncombatDamageToOpponentTriggeredAbility(new DamageTargetEffect(SavedDamageValue.MUCH), SetTargetPointer.PLAYER); + ability.addTarget(new TargetPermanent(new FilterCreatureOrPlaneswalkerPermanent("creature or planeswalker that player controls"))); + ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster()); + this.addAbility(ability); } private ChandrasIncinerator(final ChandrasIncinerator card) { @@ -123,47 +126,3 @@ class ChandrasIncineratorWatcher extends Watcher { 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/ChandrasPyreling.java b/Mage.Sets/src/mage/cards/c/ChandrasPyreling.java index 380ba8a5b91..8eaf21d8798 100644 --- a/Mage.Sets/src/mage/cards/c/ChandrasPyreling.java +++ b/Mage.Sets/src/mage/cards/c/ChandrasPyreling.java @@ -1,7 +1,8 @@ package mage.cards.c; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; +import mage.abilities.common.SourceDealsNoncombatDamageToOpponentTriggeredAbility; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.DoubleStrikeAbility; @@ -10,13 +11,7 @@ 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; /** @@ -33,7 +28,9 @@ public final class ChandrasPyreling extends CardImpl { 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()); + Ability ability = new SourceDealsNoncombatDamageToOpponentTriggeredAbility(new BoostSourceEffect(1, 0, Duration.EndOfTurn).setText("this creature gets +1/+0")); + ability.addEffect(new GainAbilitySourceEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn).setText("and gains double strike until end of turn")); + this.addAbility(ability); } private ChandrasPyreling(final ChandrasPyreling card) { @@ -45,38 +42,3 @@ public final class ChandrasPyreling extends CardImpl { 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() == GameEvent.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, {this} 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/ChangeOfPlans.java b/Mage.Sets/src/mage/cards/c/ChangeOfPlans.java index 6288c217a69..0d0b27b6f5b 100644 --- a/Mage.Sets/src/mage/cards/c/ChangeOfPlans.java +++ b/Mage.Sets/src/mage/cards/c/ChangeOfPlans.java @@ -1,6 +1,5 @@ package mage.cards.c; -import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.keyword.ConniveSourceEffect; @@ -9,8 +8,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; import mage.filter.FilterPermanent; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.permanent.PermanentIdPredicate; +import mage.filter.predicate.permanent.PermanentReferenceInCollectionPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -83,13 +81,7 @@ class ChangeOfPlansEffect extends OneShotEffect { return true; } FilterPermanent filter = new FilterPermanent("creatures"); - filter.add(Predicates.or( - permanents - .stream() - .map(MageItem::getId) - .map(PermanentIdPredicate::new) - .collect(Collectors.toSet()) - )); + filter.add(new PermanentReferenceInCollectionPredicate(permanents, game)); TargetPermanent target = new TargetPermanent(0, Integer.MAX_VALUE, filter, true); player.choose(outcome, target.withChooseHint("to phase out"), source, game); for (UUID targetId : target.getTargets()) { diff --git a/Mage.Sets/src/mage/cards/c/ChemistersTrick.java b/Mage.Sets/src/mage/cards/c/ChemistersTrick.java index 7aeeb029592..0b350b5185a 100644 --- a/Mage.Sets/src/mage/cards/c/ChemistersTrick.java +++ b/Mage.Sets/src/mage/cards/c/ChemistersTrick.java @@ -15,11 +15,14 @@ import mage.constants.Outcome; import mage.filter.StaticFilters; 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; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author LevelX2 @@ -30,7 +33,7 @@ public final class ChemistersTrick extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}{R}"); // Target creature you don't control gets -2/-0 until end of turn and attacks this turn if able. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.getSpellAbility().addEffect(new BoostTargetEffect(-2, 0, Duration.EndOfTurn)); this.getSpellAbility().addEffect(new AttacksIfAbleTargetEffect(Duration.EndOfTurn).setText("and attacks this turn if able")); diff --git a/Mage.Sets/src/mage/cards/c/CherishedHatchling.java b/Mage.Sets/src/mage/cards/c/CherishedHatchling.java index aa93168f1b2..c346568cdc8 100644 --- a/Mage.Sets/src/mage/cards/c/CherishedHatchling.java +++ b/Mage.Sets/src/mage/cards/c/CherishedHatchling.java @@ -20,11 +20,14 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.stack.Spell; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * @author LevelX2 */ @@ -68,7 +71,7 @@ class CherishedHatchlingTriggeredAbility extends DelayedTriggeredAbility { private static Effect getEffectToAdd() { Ability abilityToAdd = new EntersBattlefieldTriggeredAbility(new FightTargetSourceEffect().setText("you may have it fight another target creature"), true); - abilityToAdd.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + abilityToAdd.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); return new GainAbilityTargetEffect(abilityToAdd, Duration.EndOfTurn, "it gains \"When this creature enters, you may have it fight another target creature.\"", true); } diff --git a/Mage.Sets/src/mage/cards/c/Chewbacca.java b/Mage.Sets/src/mage/cards/c/Chewbacca.java index 964513320ee..c740c9ea95b 100644 --- a/Mage.Sets/src/mage/cards/c/Chewbacca.java +++ b/Mage.Sets/src/mage/cards/c/Chewbacca.java @@ -1,6 +1,5 @@ package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksOrBlocksTriggeredAbility; @@ -9,20 +8,21 @@ import mage.abilities.keyword.VigilanceAbility; 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.StaticFilters; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author Styxo */ public final class Chewbacca extends CardImpl { public Chewbacca(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}{G}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{G}{W}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.WOOKIEE); this.subtype.add(SubType.WARRIOR); @@ -34,7 +34,7 @@ public final class Chewbacca extends CardImpl { // Whenever Chewbacca attacks or blocks, another target creature you control gets +3/+3 until end of turn. Ability ability = new AttacksOrBlocksTriggeredAbility(new BoostTargetEffect(3, 3, Duration.EndOfTurn), false); - ability.addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/ChewbaccaTheBeast.java b/Mage.Sets/src/mage/cards/c/ChewbaccaTheBeast.java index 905238824fc..2f3a8aeb15c 100644 --- a/Mage.Sets/src/mage/cards/c/ChewbaccaTheBeast.java +++ b/Mage.Sets/src/mage/cards/c/ChewbaccaTheBeast.java @@ -13,6 +13,7 @@ import mage.cards.CardSetInfo; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.permanent.AttackingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -43,7 +44,7 @@ public final class ChewbaccaTheBeast extends CardImpl { // Whenever Chewbacca, the Beast attacks, another target attacking creature you control gains indestructible until end of turn. Ability ability = new AttacksTriggeredAbility(new GainAbilityTargetEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn), false); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/ChiefChirpa.java b/Mage.Sets/src/mage/cards/c/ChiefChirpa.java index 2866aa9ba93..ac3d8d8d8f5 100644 --- a/Mage.Sets/src/mage/cards/c/ChiefChirpa.java +++ b/Mage.Sets/src/mage/cards/c/ChiefChirpa.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; import mage.abilities.Ability; @@ -19,13 +17,14 @@ import mage.constants.TargetController; import mage.counters.CounterType; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.predicate.mageobject.ColorPredicate; import mage.game.permanent.token.EwokToken; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author Styxo */ public final class ChiefChirpa extends CardImpl { @@ -42,7 +41,7 @@ public final class ChiefChirpa extends CardImpl { } public ChiefChirpa(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{R}{G}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}{G}{W}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.EWOK); this.subtype.add(SubType.WARRIOR); @@ -54,7 +53,7 @@ public final class ChiefChirpa extends CardImpl { // Whenever a green creature you control dies, you may put a +1/+1 counter on another target Ewok creature you control. Ability ability = new DiesCreatureTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), true, diedFilter); - ability.addTarget(new TargetControlledCreaturePermanent(ewokFilter)); + ability.addTarget(new TargetPermanent(ewokFilter)); this.addAbility(ability); // When Chief Chirpa become monstrous, create three 1/1 green Ewok creature tokens. diff --git a/Mage.Sets/src/mage/cards/c/ChillToTheBone.java b/Mage.Sets/src/mage/cards/c/ChillToTheBone.java index a0ee9f882e8..576d903ecb3 100644 --- a/Mage.Sets/src/mage/cards/c/ChillToTheBone.java +++ b/Mage.Sets/src/mage/cards/c/ChillToTheBone.java @@ -9,6 +9,7 @@ import mage.constants.CardType; import mage.constants.SuperType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -28,7 +29,7 @@ public final class ChillToTheBone extends CardImpl { // Destroy target nonsnow creature. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private ChillToTheBone(final ChillToTheBone card) { diff --git a/Mage.Sets/src/mage/cards/c/ChokingVines.java b/Mage.Sets/src/mage/cards/c/ChokingVines.java index d07731b13f5..adf075894df 100644 --- a/Mage.Sets/src/mage/cards/c/ChokingVines.java +++ b/Mage.Sets/src/mage/cards/c/ChokingVines.java @@ -8,11 +8,14 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.PhaseStep; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetadjustment.XTargetsCountAdjuster; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_ATTACKING_CREATURES; + /** * @author arcox */ @@ -30,7 +33,7 @@ public final class ChokingVines extends CardImpl { .setText("X target attacking creatures become blocked.")); this.getSpellAbility().addEffect(new DamageTargetEffect(1) .setText("{this} deals 1 damage to each of those creatures")); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ATTACKING_CREATURES)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_ATTACKING_CREATURES)); this.getSpellAbility().setTargetAdjuster(new XTargetsCountAdjuster()); } diff --git a/Mage.Sets/src/mage/cards/c/ChromeshellCrab.java b/Mage.Sets/src/mage/cards/c/ChromeshellCrab.java index 582981243d5..48b4574519e 100644 --- a/Mage.Sets/src/mage/cards/c/ChromeshellCrab.java +++ b/Mage.Sets/src/mage/cards/c/ChromeshellCrab.java @@ -15,9 +15,12 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Duration; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author fireshoes @@ -41,7 +44,7 @@ public final class ChromeshellCrab extends CardImpl { effect.setText("exchange control of target creature you control and target creature an opponent controls"); Ability ability = new TurnedFaceUpSourceTriggeredAbility(effect, false, true); ability.addTarget(new TargetControlledCreaturePermanent()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/ChurningReservoir.java b/Mage.Sets/src/mage/cards/c/ChurningReservoir.java index 1a0b02282db..196ec45d80f 100644 --- a/Mage.Sets/src/mage/cards/c/ChurningReservoir.java +++ b/Mage.Sets/src/mage/cards/c/ChurningReservoir.java @@ -2,17 +2,16 @@ package mage.cards.c; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.WatcherScope; -import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledPermanent; @@ -59,7 +58,7 @@ public final class ChurningReservoir extends CardImpl { // {2}, {T}: Create a 1/1 red Phyrexian Goblin creature token. Activate only if an oil counter was removed from a permanent you controlled this turn or a permanent with an oil counter on it was put into a graveyard this turn. ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new CreateTokenEffect(new PhyrexianGoblinToken()), + new CreateTokenEffect(new PhyrexianGoblinToken()), new GenericManaCost(2), ChurningReservoirCondition.instance ); ability.addCost(new TapSourceCost()); diff --git a/Mage.Sets/src/mage/cards/c/CinderCrawler.java b/Mage.Sets/src/mage/cards/c/CinderCrawler.java index 4862ecc686e..72646557b11 100644 --- a/Mage.Sets/src/mage/cards/c/CinderCrawler.java +++ b/Mage.Sets/src/mage/cards/c/CinderCrawler.java @@ -1,20 +1,19 @@ package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.condition.common.SourceBlockedCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; 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.Zone; +import mage.constants.SubType; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class CinderCrawler extends CardImpl { @@ -27,11 +26,9 @@ public final class CinderCrawler extends CardImpl { this.toughness = new MageInt(2); // {R}: Cinder Crawler gets +1/+0 until end of turn. Activate this ability only if Cinder Crawler is blocked. - this.addAbility(new ConditionalActivatedAbility( - Zone.BATTLEFIELD, + this.addAbility(new ActivateIfConditionActivatedAbility( new BoostSourceEffect(1, 0, Duration.EndOfTurn), - new ManaCostsImpl<>("{R}"), - SourceBlockedCondition.instance + new ManaCostsImpl<>("{R}"), SourceBlockedCondition.instance )); } diff --git a/Mage.Sets/src/mage/cards/c/CinderhazeWretch.java b/Mage.Sets/src/mage/cards/c/CinderhazeWretch.java index a7cf0dbcf05..a41e6be57cb 100644 --- a/Mage.Sets/src/mage/cards/c/CinderhazeWretch.java +++ b/Mage.Sets/src/mage/cards/c/CinderhazeWretch.java @@ -14,7 +14,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.counters.CounterType; import mage.target.TargetPlayer; @@ -34,14 +33,16 @@ public final class CinderhazeWretch extends CardImpl { this.toughness = new MageInt(2); // {T}: Target player discards a card. Activate this ability only during your turn. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new DiscardTargetEffect(1), new TapSourceCost(), MyTurnCondition.instance); - ability.addHint(MyTurnHint.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new DiscardTargetEffect(1), new TapSourceCost(), MyTurnCondition.instance + ); ability.addTarget(new TargetPlayer()); - this.addAbility(ability); + this.addAbility(ability.addHint(MyTurnHint.instance)); // Put a -1/-1 counter on Cinderhaze Wretch: Untap Cinderhaze Wretch. - this.addAbility(new SimpleActivatedAbility(new UntapSourceEffect(), new PutCountersSourceCost(CounterType.M1M1.createInstance(1)))); - + this.addAbility(new SimpleActivatedAbility( + new UntapSourceEffect(), new PutCountersSourceCost(CounterType.M1M1.createInstance(1)) + )); } private CinderhazeWretch(final CinderhazeWretch card) { diff --git a/Mage.Sets/src/mage/cards/c/CitadelOfPain.java b/Mage.Sets/src/mage/cards/c/CitadelOfPain.java index 5597a0f0d7f..a0e2826a3be 100644 --- a/Mage.Sets/src/mage/cards/c/CitadelOfPain.java +++ b/Mage.Sets/src/mage/cards/c/CitadelOfPain.java @@ -1,20 +1,17 @@ package mage.cards.c; import mage.abilities.Ability; -import mage.abilities.Mode; -import mage.abilities.TriggeredAbility; -import mage.abilities.common.OnEventTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; +import mage.constants.TargetController; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledLandPermanent; import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; -import mage.game.events.GameEvent; import mage.players.Player; import java.util.UUID; @@ -28,10 +25,9 @@ public final class CitadelOfPain extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); // At the beginning of each player's end step, Citadel of Pain deals X damage to that player, where X is the number of untapped lands they control. - TriggeredAbility triggered = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, - "beginning of the end step", true, - new CitadelOfPainEffect()); - this.addAbility(triggered); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.EACH_PLAYER, new CitadelOfPainEffect(), false + )); } private CitadelOfPain(final CitadelOfPain card) { @@ -64,16 +60,15 @@ class CitadelOfPainEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(game.getActivePlayerId()); - if (player != null) { - int damage = game.getBattlefield().countAll(filter, game.getActivePlayerId(), game); - player.damage(damage, source.getSourceId(), source, game); - return true; + if (player == null) { + return false; } - return false; + int damage = game.getBattlefield().count(filter, game.getActivePlayerId(), source, game); + return damage > 0 && player.damage(damage, source.getSourceId(), source, game) > 0; } @Override public CitadelOfPainEffect copy() { return new CitadelOfPainEffect(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/c/CitadelSiege.java b/Mage.Sets/src/mage/cards/c/CitadelSiege.java index edbafe2556e..4399e931bc8 100644 --- a/Mage.Sets/src/mage/cards/c/CitadelSiege.java +++ b/Mage.Sets/src/mage/cards/c/CitadelSiege.java @@ -15,6 +15,7 @@ import mage.constants.ModeChoice; import mage.constants.TargetController; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; @@ -46,7 +47,7 @@ public final class CitadelSiege extends CardImpl { ability = new BeginningOfCombatTriggeredAbility( TargetController.OPPONENT, new TapTargetEffect("tap target creature that player controls"), false ); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect(ability, ModeChoice.DRAGONS))); } diff --git a/Mage.Sets/src/mage/cards/c/CityOfShadows.java b/Mage.Sets/src/mage/cards/c/CityOfShadows.java index f67dc011964..ae9a711c8ba 100644 --- a/Mage.Sets/src/mage/cards/c/CityOfShadows.java +++ b/Mage.Sets/src/mage/cards/c/CityOfShadows.java @@ -1,6 +1,5 @@ package mage.cards.c; -import java.util.UUID; import mage.Mana; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -12,13 +11,13 @@ import mage.abilities.mana.DynamicManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.StaticFilters; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; + +import java.util.UUID; /** - * * @author Luna Skyrise */ public final class CityOfShadows extends CardImpl { @@ -28,7 +27,7 @@ public final class CityOfShadows extends CardImpl { // {T}, Exile a creature you control: Put a storage counter on City of Shadows. Ability ability = new SimpleActivatedAbility(new AddCountersSourceEffect(CounterType.STORAGE.createInstance()), new TapSourceCost()); - ability.addCost(new ExileTargetCost(new TargetControlledCreaturePermanent(StaticFilters.FILTER_CONTROLLED_A_CREATURE))); + ability.addCost(new ExileTargetCost(new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_A_CREATURE))); this.addAbility(ability); // {T}: Add {C} for each storage counter on City of Shadows. diff --git a/Mage.Sets/src/mage/cards/c/ClanDefiance.java b/Mage.Sets/src/mage/cards/c/ClanDefiance.java index 14e388c5e43..a3d04ea8ba7 100644 --- a/Mage.Sets/src/mage/cards/c/ClanDefiance.java +++ b/Mage.Sets/src/mage/cards/c/ClanDefiance.java @@ -10,6 +10,7 @@ import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetPlayerOrPlaneswalker; @@ -36,10 +37,10 @@ public final class ClanDefiance extends CardImpl { this.getSpellAbility().getModes().setMaxModes(3); // Clan Defiance deals X damage to target creature with flying; this.getSpellAbility().addEffect(new DamageTargetEffect(GetXValue.instance)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filterFlying).withChooseHint("deals X damage, with flying")); + this.getSpellAbility().addTarget(new TargetPermanent(filterFlying).withChooseHint("deals X damage, with flying")); // Clan Defiance deals X damage to target creature without flying; Mode mode1 = new Mode(new DamageTargetEffect(GetXValue.instance)); - mode1.addTarget(new TargetCreaturePermanent(filterWithoutFlying).withChooseHint("deals X damage, without flying")); + mode1.addTarget(new TargetPermanent(filterWithoutFlying).withChooseHint("deals X damage, without flying")); this.getSpellAbility().addMode(mode1); // and/or Clan Defiance deals X damage to target player. Mode mode2 = new Mode(new DamageTargetEffect(GetXValue.instance)); diff --git a/Mage.Sets/src/mage/cards/c/ClashOfRealities.java b/Mage.Sets/src/mage/cards/c/ClashOfRealities.java index 6d8f13d6c8e..3f732d9af3a 100644 --- a/Mage.Sets/src/mage/cards/c/ClashOfRealities.java +++ b/Mage.Sets/src/mage/cards/c/ClashOfRealities.java @@ -16,6 +16,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,12 +39,12 @@ public final class ClashOfRealities extends CardImpl { // All Spirits have "When this permanent enters the battlefield, you may have it deal 3 damage to target non-Spirit creature." Ability ability1 = new ClashOfRealitiesTriggeredAbility(new DamageTargetEffect(3), "When this permanent enters, "); - ability1.addTarget(new TargetCreaturePermanent(filterNotSpirit)); + ability1.addTarget(new TargetPermanent(filterNotSpirit)); this.addAbility(new SimpleStaticAbility(new GainAbilityAllEffect(ability1, Duration.WhileOnBattlefield, filterSpirit, "All Spirits have \"When this permanent enters the battlefield, you may have it deal 3 damage to target non-Spirit creature.\""))); // Non-Spirit creatures have "When this creature enters the battlefield, you may have it deal 3 damage to target Spirit creature." Ability ability2 = new ClashOfRealitiesTriggeredAbility(new DamageTargetEffect(3), "When this creature enters, "); - ability2.addTarget(new TargetCreaturePermanent(filterSpirit)); + ability2.addTarget(new TargetPermanent(filterSpirit)); this.addAbility(new SimpleStaticAbility(new GainAbilityAllEffect(ability2, Duration.WhileOnBattlefield, filterNotSpirit, "Non-Spirit creatures have \"When this creature enters the battlefield, you may have it deal 3 damage to target Spirit creature.\""))); } diff --git a/Mage.Sets/src/mage/cards/c/ClashOfTitans.java b/Mage.Sets/src/mage/cards/c/ClashOfTitans.java index c9405028f82..561f6abc70d 100644 --- a/Mage.Sets/src/mage/cards/c/ClashOfTitans.java +++ b/Mage.Sets/src/mage/cards/c/ClashOfTitans.java @@ -6,10 +6,13 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2; + /** * @author TheElk801 */ @@ -24,7 +27,7 @@ public final class ClashOfTitans extends CardImpl { target.setTargetTag(1); this.getSpellAbility().addTarget(target); - target = new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2); + target = new TargetPermanent(FILTER_ANOTHER_CREATURE_TARGET_2); target.setTargetTag(2); this.getSpellAbility().addTarget(target); } diff --git a/Mage.Sets/src/mage/cards/c/ClearAPath.java b/Mage.Sets/src/mage/cards/c/ClearAPath.java index db45f3a0420..fda21aea8eb 100644 --- a/Mage.Sets/src/mage/cards/c/ClearAPath.java +++ b/Mage.Sets/src/mage/cards/c/ClearAPath.java @@ -11,6 +11,7 @@ import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -32,7 +33,7 @@ public final class ClearAPath extends CardImpl { // Destroy target creature with defender. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - Target target = new TargetCreaturePermanent(filter); + Target target = new TargetPermanent(filter); this.getSpellAbility().addTarget(target); } diff --git a/Mage.Sets/src/mage/cards/c/ClearShot.java b/Mage.Sets/src/mage/cards/c/ClearShot.java index 3cd13c1c01a..d3ee7cadc1f 100644 --- a/Mage.Sets/src/mage/cards/c/ClearShot.java +++ b/Mage.Sets/src/mage/cards/c/ClearShot.java @@ -8,11 +8,14 @@ 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 mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author LevelX2 */ @@ -28,7 +31,7 @@ public final class ClearShot extends CardImpl { // It deals damage equal to its power to target creature you don't control. this.getSpellAbility().addEffect(new DamageWithPowerFromOneToAnotherTargetEffect("It")); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); // second target + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); // second target } diff --git a/Mage.Sets/src/mage/cards/c/CleavingSkyrider.java b/Mage.Sets/src/mage/cards/c/CleavingSkyrider.java index 7641522e7d1..5ae8dcd5ad5 100644 --- a/Mage.Sets/src/mage/cards/c/CleavingSkyrider.java +++ b/Mage.Sets/src/mage/cards/c/CleavingSkyrider.java @@ -44,7 +44,7 @@ public final class CleavingSkyrider extends CardImpl { // When Cleaving Skyrider enters the battlefield, if it was kicked, it deals X damage to any target, where X is the number of attacking creatures. Ability ability = new EntersBattlefieldTriggeredAbility( - new DamageTargetEffect(xValue, "it") + new DamageTargetEffect(xValue, "it").setText("it deals X damage to any target, where X is the number of attacking creatures") ).withInterveningIf(KickedCondition.ONCE); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/c/ClockworkAvian.java b/Mage.Sets/src/mage/cards/c/ClockworkAvian.java index fbe109ce863..0baa24bc0f3 100644 --- a/Mage.Sets/src/mage/cards/c/ClockworkAvian.java +++ b/Mage.Sets/src/mage/cards/c/ClockworkAvian.java @@ -8,14 +8,16 @@ import mage.abilities.condition.common.AttackedOrBlockedThisCombatSourceConditio import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +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; @@ -51,9 +53,8 @@ public final class ClockworkAvian extends CardImpl { ).withInterveningIf(AttackedOrBlockedThisCombatSourceCondition.instance), new AttackedOrBlockedThisCombatWatcher()); // {X}, {tap}: Put up to X +1/+0 counters on Clockwork Avian. This ability can't cause the total number of +1/+0 counters on Clockwork Avian to be greater than four. Activate this ability only during your upkeep. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, new ClockworkAvianEffect(), - new ManaCostsImpl<>("{X}"), new IsStepCondition(PhaseStep.UPKEEP) + Ability ability = new ActivateIfConditionActivatedAbility( + new ClockworkAvianEffect(), new ManaCostsImpl<>("{X}"), IsStepCondition.getMyUpkeep() ); ability.addCost(new TapSourceCost()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/c/ClockworkBeast.java b/Mage.Sets/src/mage/cards/c/ClockworkBeast.java index 85647d084f9..aaef5b5002b 100644 --- a/Mage.Sets/src/mage/cards/c/ClockworkBeast.java +++ b/Mage.Sets/src/mage/cards/c/ClockworkBeast.java @@ -9,13 +9,15 @@ import mage.abilities.condition.common.AttackedOrBlockedThisCombatSourceConditio import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +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; @@ -48,9 +50,8 @@ public final class ClockworkBeast extends CardImpl { ).withInterveningIf(AttackedOrBlockedThisCombatSourceCondition.instance), new AttackedOrBlockedThisCombatWatcher()); // {X}, {tap}: Put up to X +1/+0 counters on Clockwork Beast. This ability can't cause the total number of +1/+0 counters on Clockwork Beast to be greater than seven. Activate this ability only during your upkeep. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, new ClockworkBeastEffect(), - new ManaCostsImpl<>("{X}"), new IsStepCondition(PhaseStep.UPKEEP) + Ability ability = new ActivateIfConditionActivatedAbility( + new ClockworkBeastEffect(), new ManaCostsImpl<>("{X}"), IsStepCondition.getMyUpkeep() ); ability.addCost(new TapSourceCost()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/c/ClockworkGnomes.java b/Mage.Sets/src/mage/cards/c/ClockworkGnomes.java index 810b2d41523..8587ac39d4d 100644 --- a/Mage.Sets/src/mage/cards/c/ClockworkGnomes.java +++ b/Mage.Sets/src/mage/cards/c/ClockworkGnomes.java @@ -14,6 +14,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -37,7 +38,7 @@ public final class ClockworkGnomes extends CardImpl { // {3}, {tap}: Regenerate target artifact creature. Ability ability = new SimpleActivatedAbility(new RegenerateTargetEffect(), new ManaCostsImpl<>("{3}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/ClockworkSteed.java b/Mage.Sets/src/mage/cards/c/ClockworkSteed.java index 4aa2284535a..45aa3ebb66f 100644 --- a/Mage.Sets/src/mage/cards/c/ClockworkSteed.java +++ b/Mage.Sets/src/mage/cards/c/ClockworkSteed.java @@ -9,14 +9,17 @@ import mage.abilities.condition.common.AttackedOrBlockedThisCombatSourceConditio import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; 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.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; @@ -56,9 +59,8 @@ public final class ClockworkSteed extends CardImpl { ).withInterveningIf(AttackedOrBlockedThisCombatSourceCondition.instance), new AttackedOrBlockedThisCombatWatcher()); // {X}, {tap}: Put up to X +1/+0 counters on Clockwork Steed. This ability can't cause the total number of +1/+0 counters on Clockwork Steed to be greater than four. Activate this ability only during your upkeep. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, new ClockworkSteedEffect(), - new ManaCostsImpl<>("{X}"), new IsStepCondition(PhaseStep.UPKEEP) + Ability ability = new ActivateIfConditionActivatedAbility( + new ClockworkSteedEffect(), new ManaCostsImpl<>("{X}"), IsStepCondition.getMyUpkeep() ); ability.addCost(new TapSourceCost()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/c/ClockworkSwarm.java b/Mage.Sets/src/mage/cards/c/ClockworkSwarm.java index 311315bc130..25f9e70081f 100644 --- a/Mage.Sets/src/mage/cards/c/ClockworkSwarm.java +++ b/Mage.Sets/src/mage/cards/c/ClockworkSwarm.java @@ -9,14 +9,17 @@ import mage.abilities.condition.common.AttackedOrBlockedThisCombatSourceConditio import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; 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.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; @@ -60,9 +63,8 @@ public final class ClockworkSwarm extends CardImpl { ).withInterveningIf(AttackedOrBlockedThisCombatSourceCondition.instance), new AttackedOrBlockedThisCombatWatcher()); // {X}, {tap}: Put up to X +1/+0 counters on Clockwork Swarm. This ability can't cause the total number of +1/+0 counters on Clockwork Swarm to be greater than four. Activate this ability only during your upkeep. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, new ClockworkSwarmEffect(), - new ManaCostsImpl<>("{X}"), new IsStepCondition(PhaseStep.UPKEEP) + Ability ability = new ActivateIfConditionActivatedAbility( + new ClockworkSwarmEffect(), new ManaCostsImpl<>("{X}"), IsStepCondition.getMyUpkeep() ); ability.addCost(new TapSourceCost()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/c/ClosingStatement.java b/Mage.Sets/src/mage/cards/c/ClosingStatement.java index 12444cbfcb2..aabb7a99b3a 100644 --- a/Mage.Sets/src/mage/cards/c/ClosingStatement.java +++ b/Mage.Sets/src/mage/cards/c/ClosingStatement.java @@ -16,13 +16,12 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetCreatureOrPlaneswalker; import java.util.UUID; /** - * * @author htrajan */ public final class ClosingStatement extends CardImpl { @@ -44,11 +43,9 @@ public final class ClosingStatement extends CardImpl { this.addAbility(ability); // Destroy target creature or planeswalker you don't control. Put a +1/+1 counter on up to one target creature you control. - this.getSpellAbility().addTarget(new TargetCreatureOrPlaneswalker(1, 1, filter, false) - .setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPermanent(filter).setTargetTag(1)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, 1) - .setTargetTag(2)); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, 1).setTargetTag(2)); this.getSpellAbility().addEffect(new ClosingStatementEffect()); } @@ -85,9 +82,9 @@ class ClosingStatementEffect extends OneShotEffect { return false; } Target target = source.getTargets().stream() - .filter(t -> t.getTargetTag() == 2) - .findFirst() - .orElseThrow(() -> new IllegalStateException("Expected to find target with tag 2 but none exists")); + .filter(t -> t.getTargetTag() == 2) + .findFirst() + .orElseThrow(() -> new IllegalStateException("Expected to find target with tag 2 but none exists")); Permanent permanent = game.getPermanent(target.getFirstTarget()); if (permanent != null) { return permanent.addCounters(CounterType.P1P1.createInstance(), source.getControllerId(), source, game); diff --git a/Mage.Sets/src/mage/cards/c/CloudsLimitBreak.java b/Mage.Sets/src/mage/cards/c/CloudsLimitBreak.java index 25b96002dce..91b5eea84fd 100644 --- a/Mage.Sets/src/mage/cards/c/CloudsLimitBreak.java +++ b/Mage.Sets/src/mage/cards/c/CloudsLimitBreak.java @@ -16,7 +16,6 @@ import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; -import mage.target.common.TargetCreaturePermanent; import java.util.Objects; import java.util.UUID; @@ -67,9 +66,9 @@ public final class CloudsLimitBreak extends CardImpl { } } -class CloudsLimitBreakTarget extends TargetCreaturePermanent { +class CloudsLimitBreakTarget extends TargetPermanent { - private static final FilterCreaturePermanent filter + private static final FilterPermanent filter = new FilterCreaturePermanent("tapped creatures with different controllers"); CloudsLimitBreakTarget() { diff --git a/Mage.Sets/src/mage/cards/c/CoalitionRelic.java b/Mage.Sets/src/mage/cards/c/CoalitionRelic.java index 4ae44f6e614..69538a7d364 100644 --- a/Mage.Sets/src/mage/cards/c/CoalitionRelic.java +++ b/Mage.Sets/src/mage/cards/c/CoalitionRelic.java @@ -3,18 +3,17 @@ package mage.cards.c; import mage.Mana; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfFirstMainTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.mana.AnyColorManaAbility; +import mage.abilities.triggers.BeginningOfFirstMainTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.choices.ChoiceColor; import mage.constants.CardType; import mage.constants.Outcome; -import mage.constants.Zone; import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; @@ -52,7 +51,7 @@ class CoalitionRelicEffect extends OneShotEffect { CoalitionRelicEffect() { super(Outcome.PutManaInPool); - this.staticText = "remove all charge counters from Coalition Relic. Add one mana of any color for each charge counter removed this way"; + this.staticText = "remove all charge counters from {this}. Add one mana of any color for each charge counter removed this way"; } private CoalitionRelicEffect(final CoalitionRelicEffect effect) { diff --git a/Mage.Sets/src/mage/cards/c/CoastalDrake.java b/Mage.Sets/src/mage/cards/c/CoastalDrake.java index 2e37b3766fc..d679c6aa728 100644 --- a/Mage.Sets/src/mage/cards/c/CoastalDrake.java +++ b/Mage.Sets/src/mage/cards/c/CoastalDrake.java @@ -15,8 +15,11 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.constants.SubType.KAVU; + /** * * @author Loki @@ -35,7 +38,7 @@ public final class CoastalDrake extends CardImpl { // {1}{U}, {T} : Return target Kavu to its owner's hand. Ability ability = new SimpleActivatedAbility(new ReturnToHandTargetEffect(), new ManaCostsImpl<>("{1}{U}")); - ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent(SubType.KAVU, "Kavu"))); + ability.addTarget(new TargetPermanent(new FilterCreaturePermanent(KAVU, "Kavu"))); ability.addCost(new TapSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CoastalWizard.java b/Mage.Sets/src/mage/cards/c/CoastalWizard.java index b476e1b3b5d..5a718460040 100644 --- a/Mage.Sets/src/mage/cards/c/CoastalWizard.java +++ b/Mage.Sets/src/mage/cards/c/CoastalWizard.java @@ -1,51 +1,40 @@ - package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.common.MyTurnBeforeAttackersDeclaredCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.ReturnToHandSourceEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.AnotherPredicate; -import mage.target.common.TargetCreaturePermanent; +import mage.filter.StaticFilters; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author fireshoes */ public final class CoastalWizard extends CardImpl { - - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); - static { - filter.add(AnotherPredicate.instance); - } public CoastalWizard(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.HUMAN); this.subtype.add(SubType.WIZARD); this.power = new MageInt(1); this.toughness = new MageInt(1); // {tap}: Return Coastal Wizard and another target creature to their owners' hands. Activate this ability only during your turn, before attackers are declared. - Effect effect = new ReturnToHandSourceEffect(true); - effect.setText("Return Coastal Wizard"); - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - effect, new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); - effect = new ReturnToHandTargetEffect(); - effect.setText("and another target creature to their owners' hands"); - ability.addTarget(new TargetCreaturePermanent(filter)); - ability.addEffect(effect); + Ability ability = new ActivateIfConditionActivatedAbility( + new ReturnToHandSourceEffect(true).setText("return {this}"), + new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance + ); + ability.addEffect(new ReturnToHandTargetEffect().setText("and another target creature to their owners' hands")); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CoffinPuppets.java b/Mage.Sets/src/mage/cards/c/CoffinPuppets.java index 7ca089511df..4e8fa10b7e7 100644 --- a/Mage.Sets/src/mage/cards/c/CoffinPuppets.java +++ b/Mage.Sets/src/mage/cards/c/CoffinPuppets.java @@ -1,4 +1,3 @@ - package mage.cards.c; import mage.MageInt; @@ -12,12 +11,10 @@ import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffec import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.PhaseStep; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterControlledLandPermanent; import mage.filter.common.FilterControlledPermanent; -import mage.target.common.TargetControlledPermanent; import java.util.UUID; @@ -38,7 +35,7 @@ public final class CoffinPuppets extends CardImpl { private static final Condition condition = new CompoundCondition( "during your upkeep and only if you control a Swamp", new PermanentsOnTheBattlefieldCondition(filter), - new IsStepCondition(PhaseStep.UPKEEP) + IsStepCondition.getMyUpkeep() ); public CoffinPuppets(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/c/CogworkLibrarian.java b/Mage.Sets/src/mage/cards/c/CogworkLibrarian.java index 0460290b3a9..c3ad17b06bf 100644 --- a/Mage.Sets/src/mage/cards/c/CogworkLibrarian.java +++ b/Mage.Sets/src/mage/cards/c/CogworkLibrarian.java @@ -1,15 +1,16 @@ package mage.cards.c; -import java.util.UUID; import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.InfoEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; -import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.common.InfoEffect; + +import java.util.UUID; /** * @@ -27,12 +28,12 @@ public final class CogworkLibrarian extends CardImpl { // TODO: Draft specific abilities not implemented // Draft Cogwork Librarian face up. - this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Draft Cogwork Librarian face up - not implemented."))); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Draft {this} face up - not implemented."))); // As you draft a card, you may draft an additional card from that booster pack. If you do, put Cogwork Librarian into that booster pack. this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("As you draft a card, " + "you may draft an additional card from that booster pack. If you do, " - + "put Cogwork Librarian into that booster pack - not implemented."))); + + "put {this} into that booster pack - not implemented."))); } private CogworkLibrarian(final CogworkLibrarian card) { diff --git a/Mage.Sets/src/mage/cards/c/CogworkSpy.java b/Mage.Sets/src/mage/cards/c/CogworkSpy.java index f8ee109d1db..bb02a3c810c 100644 --- a/Mage.Sets/src/mage/cards/c/CogworkSpy.java +++ b/Mage.Sets/src/mage/cards/c/CogworkSpy.java @@ -28,7 +28,7 @@ public final class CogworkSpy extends CardImpl { // TODO: Draft specific abilities not implemented // Reveal Cogwork Spy as you draft it. You may look at the next card drafted from this booster pack. - this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Reveal Cogwork Spy as you draft it. " + this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Reveal {this} as you draft it. " + "You may look at the next card drafted from this booster pack - not implemented."))); // Flying diff --git a/Mage.Sets/src/mage/cards/c/CoilingStalker.java b/Mage.Sets/src/mage/cards/c/CoilingStalker.java index 4990d4c8845..701ad3b8e89 100644 --- a/Mage.Sets/src/mage/cards/c/CoilingStalker.java +++ b/Mage.Sets/src/mage/cards/c/CoilingStalker.java @@ -1,24 +1,24 @@ package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersTargetEffect; -import mage.constants.SubType; import mage.abilities.keyword.NinjutsuAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SubType; import mage.counters.CounterType; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.Predicate; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author weirddan455 */ public final class CoilingStalker extends CardImpl { @@ -43,7 +43,7 @@ public final class CoilingStalker extends CardImpl { // Whenever Coiling Stalker deals combat damage to a player, put a +1/+1 counter on target creature you control that doesn't have a +1/+1 counter on it. Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), false); - ability.addTarget(new TargetControlledCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/ColfenorTheLastYew.java b/Mage.Sets/src/mage/cards/c/ColfenorTheLastYew.java index 7c4f5018f3e..93109b0530b 100644 --- a/Mage.Sets/src/mage/cards/c/ColfenorTheLastYew.java +++ b/Mage.Sets/src/mage/cards/c/ColfenorTheLastYew.java @@ -2,13 +2,17 @@ package mage.cards.c; import mage.MageInt; import mage.MageObjectReference; +import mage.abilities.Ability; import mage.abilities.common.DiesThisOrAnotherTriggeredAbility; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; import mage.abilities.keyword.ReachAbility; import mage.abilities.keyword.VigilanceAbility; 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.constants.SuperType; import mage.filter.FilterCard; import mage.filter.StaticFilters; import mage.filter.common.FilterCreatureCard; @@ -16,10 +20,10 @@ import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.MageObjectReferencePredicate; import mage.filter.predicate.mageobject.ToughnessPredicate; import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; +import mage.target.Target; import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetadjustment.GenericTargetAdjuster; import java.util.UUID; @@ -44,7 +48,10 @@ public final class ColfenorTheLastYew extends CardImpl { this.addAbility(ReachAbility.getInstance()); // Whenever Colfenor, the Last Yew or another creature you control dies, return up to one other target creature card with lesser toughness from your graveyard to your hand. - this.addAbility(new ColfenorTheLastYewTriggeredAbility()); + Ability ability = new DiesThisOrAnotherTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect(), false, StaticFilters.FILTER_CONTROLLED_CREATURE); + ability.addTarget(new TargetCardInYourGraveyard(0, 1, new FilterCreatureCard("other target creature card with lesser toughness"))); + ability.setTargetAdjuster(new ColfenorTheLastYewTargetAdjuster()); + this.addAbility(ability); } private ColfenorTheLastYew(final ColfenorTheLastYew card) { @@ -56,43 +63,15 @@ public final class ColfenorTheLastYew extends CardImpl { return new ColfenorTheLastYew(this); } } - -class ColfenorTheLastYewTriggeredAbility extends DiesThisOrAnotherTriggeredAbility { - - ColfenorTheLastYewTriggeredAbility() { - super(new ReturnFromGraveyardToHandTargetEffect(), false, StaticFilters.FILTER_CONTROLLED_CREATURE); - } - - private ColfenorTheLastYewTriggeredAbility(final ColfenorTheLastYewTriggeredAbility ability) { - super(ability); - } - +class ColfenorTheLastYewTargetAdjuster extends GenericTargetAdjuster { @Override - public DiesThisOrAnotherTriggeredAbility copy() { - return new ColfenorTheLastYewTriggeredAbility(this); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (!super.checkTrigger(event, game)) { - return false; - } - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - Permanent permanent = zEvent.getTarget(); - if (permanent == null) { - return false; - } + public void adjustTargets(Ability ability, Game game) { + Permanent permanent = (Permanent)ability.getEffects().get(0).getValue("creatureDied"); + ability.getTargets().clear(); + Target newTarget = blueprintTarget.copy(); FilterCard filterCard = new FilterCreatureCard("creature card with toughness less than " + permanent.getToughness().getValue()); filterCard.add(new ToughnessPredicate(ComparisonType.FEWER_THAN, permanent.getToughness().getValue())); filterCard.add(Predicates.not(new MageObjectReferencePredicate(new MageObjectReference(permanent, game)))); - this.getTargets().clear(); - this.addTarget(new TargetCardInYourGraveyard(0, 1, filterCard)); - return true; - } - - @Override - public String getRule() { - return "Whenever {this} or another creature you control dies, return up to one other target creature card " + - "with lesser toughness from your graveyard to your hand."; + ability.addTarget(newTarget); } } diff --git a/Mage.Sets/src/mage/cards/c/CollarTheCulprit.java b/Mage.Sets/src/mage/cards/c/CollarTheCulprit.java index a5a1e96eea0..ca360a0db11 100644 --- a/Mage.Sets/src/mage/cards/c/CollarTheCulprit.java +++ b/Mage.Sets/src/mage/cards/c/CollarTheCulprit.java @@ -9,6 +9,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ToughnessPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -28,7 +29,7 @@ public final class CollarTheCulprit extends CardImpl { // Destroy target creature with toughness 4 or greater. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private CollarTheCulprit(final CollarTheCulprit card) { @@ -39,4 +40,4 @@ public final class CollarTheCulprit extends CardImpl { public CollarTheCulprit copy() { return new CollarTheCulprit(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/c/CollectiveDefiance.java b/Mage.Sets/src/mage/cards/c/CollectiveDefiance.java index b38e425645d..e9b252575d2 100644 --- a/Mage.Sets/src/mage/cards/c/CollectiveDefiance.java +++ b/Mage.Sets/src/mage/cards/c/CollectiveDefiance.java @@ -15,6 +15,7 @@ import mage.filter.FilterPlayer; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.TargetPlayer; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetOpponentOrPlaneswalker; @@ -47,7 +48,7 @@ public final class CollectiveDefiance extends CardImpl { Effect effect = new DamageTargetEffect(4); effect.setText("{this} deals 4 damage to target creature"); Mode mode = new Mode(effect); - mode.addTarget(new TargetCreaturePermanent(filterCreature).withChooseHint("deals 4 damage to")); + mode.addTarget(new TargetPermanent(filterCreature).withChooseHint("deals 4 damage to")); this.getSpellAbility().addMode(mode); // Collective Defiance deals 3 damage to target opponent or planeswalker. diff --git a/Mage.Sets/src/mage/cards/c/CollectiveEffort.java b/Mage.Sets/src/mage/cards/c/CollectiveEffort.java index ccff1b45ca4..9ba56cd19d1 100644 --- a/Mage.Sets/src/mage/cards/c/CollectiveEffort.java +++ b/Mage.Sets/src/mage/cards/c/CollectiveEffort.java @@ -20,8 +20,8 @@ import mage.filter.predicate.mageobject.PowerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.TargetPlayer; -import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetEnchantmentPermanent; @@ -43,7 +43,7 @@ public final class CollectiveEffort extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{W}{W}"); // Escalate — Tap an untapped creature you control. - this.addAbility(new EscalateAbility(new TapTargetCost(new TargetControlledCreaturePermanent(StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURE)))); + this.addAbility(new EscalateAbility(new TapTargetCost(StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURE))); // Choose one or more — this.getSpellAbility().getModes().setMinModes(1); @@ -51,7 +51,7 @@ public final class CollectiveEffort extends CardImpl { // Destroy target creature with power 4 or greater.; this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filterDestroyCreature).withChooseHint("destroy")); + this.getSpellAbility().addTarget(new TargetPermanent(filterDestroyCreature).withChooseHint("destroy")); // Destroy target enchantment.; Effect effect = new DestroyTargetEffect(); diff --git a/Mage.Sets/src/mage/cards/c/ColossusOfSardia.java b/Mage.Sets/src/mage/cards/c/ColossusOfSardia.java index 52a44993f62..e413df1c79c 100644 --- a/Mage.Sets/src/mage/cards/c/ColossusOfSardia.java +++ b/Mage.Sets/src/mage/cards/c/ColossusOfSardia.java @@ -1,12 +1,10 @@ - package mage.cards.c; -import java.util.UUID; import mage.MageInt; 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.costs.mana.GenericManaCost; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DontUntapInControllersUntapStepSourceEffect; import mage.abilities.effects.common.UntapSourceEffect; import mage.abilities.keyword.TrampleAbility; @@ -14,17 +12,16 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.PhaseStep; -import mage.constants.Zone; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class ColossusOfSardia extends CardImpl { public ColossusOfSardia(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{9}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{9}"); this.subtype.add(SubType.GOLEM); this.power = new MageInt(9); @@ -37,8 +34,9 @@ public final class ColossusOfSardia extends CardImpl { this.addAbility(new SimpleStaticAbility(new DontUntapInControllersUntapStepSourceEffect())); // {9}: Untap Colossus of Sardia. Activate this ability only during your upkeep. - this.addAbility(new ConditionalActivatedAbility(Zone.BATTLEFIELD, - new UntapSourceEffect(), new ManaCostsImpl<>("{9}"), new IsStepCondition(PhaseStep.UPKEEP), null)); + this.addAbility(new ActivateIfConditionActivatedAbility( + new UntapSourceEffect(), new GenericManaCost(9), IsStepCondition.getMyUpkeep() + )); } private ColossusOfSardia(final ColossusOfSardia card) { diff --git a/Mage.Sets/src/mage/cards/c/ComboAttack.java b/Mage.Sets/src/mage/cards/c/ComboAttack.java index 2b17b496161..8acc59d0cf4 100644 --- a/Mage.Sets/src/mage/cards/c/ComboAttack.java +++ b/Mage.Sets/src/mage/cards/c/ComboAttack.java @@ -1,30 +1,34 @@ 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.filter.FilterPermanent; import mage.filter.common.FilterTeamCreaturePermanent; 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 ComboAttack extends CardImpl { + private static final FilterPermanent filter = new FilterTeamCreaturePermanent("creatures your team controls"); + public ComboAttack(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}"); // Two target creatures your team controls each deal damage equal to their power to target creature. this.getSpellAbility().addEffect(new ComboAttackEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(2, 2, new FilterTeamCreaturePermanent(), false)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(1)); + this.getSpellAbility().addTarget(new TargetPermanent(2, filter)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } private ComboAttack(final ComboAttack card) { diff --git a/Mage.Sets/src/mage/cards/c/Combust.java b/Mage.Sets/src/mage/cards/c/Combust.java index b625cd51b69..7e0703f4087 100644 --- a/Mage.Sets/src/mage/cards/c/Combust.java +++ b/Mage.Sets/src/mage/cards/c/Combust.java @@ -15,6 +15,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -36,7 +37,7 @@ public final class Combust extends CardImpl { // Combust deals 5 damage to target white or blue creature. The damage can't be prevented. this.getSpellAbility().addEffect(new DamageTargetEffect(5, false)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // Combust can't be countered. Ability ability = new SimpleStaticAbility(Zone.STACK, new CantBeCounteredSourceEffect()); @@ -53,4 +54,4 @@ public final class Combust extends CardImpl { return new Combust(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/c/CometStellarPup.java b/Mage.Sets/src/mage/cards/c/CometStellarPup.java index a971fb75333..e534188ebb4 100644 --- a/Mage.Sets/src/mage/cards/c/CometStellarPup.java +++ b/Mage.Sets/src/mage/cards/c/CometStellarPup.java @@ -76,7 +76,7 @@ class CometStellarPupAbility extends OneShotEffect { + "1 or 2 — [+2], then create two 1/1 green Squirrel creature tokens. They gain haste until end of turn.
" + "3 — [-1], then return a card with mana value 2 or less from your graveyard to your hand.
" + "4 or 5 — {this} deals damage equal to the number of loyalty counters on him to a creature or player, then [-2].
" - + "6 — [+1], and you may activate Comet, Stellar Pup's loyalty ability two more times this turn."; + + "6 — [+1], and you may activate {this}'s loyalty ability two more times this turn."; } private CometStellarPupAbility(final CometStellarPupAbility effect) { diff --git a/Mage.Sets/src/mage/cards/c/CompanionOfTheTrials.java b/Mage.Sets/src/mage/cards/c/CompanionOfTheTrials.java index fdd89ef531f..41d068b8245 100644 --- a/Mage.Sets/src/mage/cards/c/CompanionOfTheTrials.java +++ b/Mage.Sets/src/mage/cards/c/CompanionOfTheTrials.java @@ -1,9 +1,9 @@ - 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.mana.ManaCostsImpl; import mage.abilities.effects.common.UntapTargetEffect; @@ -12,22 +12,19 @@ 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.TargetCreaturePermanent; import java.util.UUID; /** - * * @author fireshoes */ public final class CompanionOfTheTrials extends CardImpl { - private static final FilterPlaneswalkerPermanent filter = new FilterPlaneswalkerPermanent("you control a Gideon planeswalker"); - static { - filter.add(SubType.GIDEON.getPredicate()); - } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPlaneswalkerPermanent(SubType.GIDEON, "you control a Gideon planeswalker") + ); public CompanionOfTheTrials(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); @@ -41,10 +38,9 @@ public final class CompanionOfTheTrials extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // {1}{W}: Untap target creature. Activate this ability only if you control a Gideon planeswalker. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new UntapTargetEffect(), - new ManaCostsImpl<>("{1}{W}"), - new PermanentsOnTheBattlefieldCondition(filter)); + Ability ability = new ActivateIfConditionActivatedAbility( + new UntapTargetEffect(), new ManaCostsImpl<>("{1}{W}"), condition + ); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CompleteDisregard.java b/Mage.Sets/src/mage/cards/c/CompleteDisregard.java index f6569b7c01c..fa48129824d 100644 --- a/Mage.Sets/src/mage/cards/c/CompleteDisregard.java +++ b/Mage.Sets/src/mage/cards/c/CompleteDisregard.java @@ -10,6 +10,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -32,7 +33,7 @@ public final class CompleteDisregard extends CardImpl { // Exile target creature with power 3 or less. this.getSpellAbility().addEffect(new ExileTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private CompleteDisregard(final CompleteDisregard card) { diff --git a/Mage.Sets/src/mage/cards/c/ConniveConcoct.java b/Mage.Sets/src/mage/cards/c/ConniveConcoct.java index c28f608578e..9e4ce30d66c 100644 --- a/Mage.Sets/src/mage/cards/c/ConniveConcoct.java +++ b/Mage.Sets/src/mage/cards/c/ConniveConcoct.java @@ -20,6 +20,7 @@ import mage.filter.predicate.mageobject.PowerPredicate; import mage.game.Game; import mage.players.Player; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; @@ -46,7 +47,7 @@ public final class ConniveConcoct extends SplitCard { new GainControlTargetEffect(Duration.Custom) ); this.getLeftHalfCard().getSpellAbility().addTarget( - new TargetCreaturePermanent(filter) + new TargetPermanent(filter) ); // Concoct diff --git a/Mage.Sets/src/mage/cards/c/ConqueringManticore.java b/Mage.Sets/src/mage/cards/c/ConqueringManticore.java index 439e6048dcb..e1819ed50ef 100644 --- a/Mage.Sets/src/mage/cards/c/ConqueringManticore.java +++ b/Mage.Sets/src/mage/cards/c/ConqueringManticore.java @@ -16,8 +16,11 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Duration; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author North @@ -36,7 +39,7 @@ public final class ConqueringManticore extends CardImpl { Ability ability = new EntersBattlefieldTriggeredAbility(new GainControlTargetEffect(Duration.EndOfTurn), false); ability.addEffect(new UntapTargetEffect().setText("Untap that creature")); ability.addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn).setText("It gains haste until end of turn.")); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/Conscription.java b/Mage.Sets/src/mage/cards/c/Conscription.java index a54564c5d5c..656068c2d62 100644 --- a/Mage.Sets/src/mage/cards/c/Conscription.java +++ b/Mage.Sets/src/mage/cards/c/Conscription.java @@ -12,6 +12,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -34,7 +35,7 @@ public final class Conscription extends CardImpl { this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.EndOfGame)); this.getSpellAbility().addEffect(new BecomesCreatureTypeTargetEffect(Duration.EndOfGame, SubType.TROOPER, false) .setText("It becomes a Trooper in addition to its other types")); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private Conscription(final Conscription card) { diff --git a/Mage.Sets/src/mage/cards/c/ConsulsLieutenant.java b/Mage.Sets/src/mage/cards/c/ConsulsLieutenant.java index d204a246592..5035bafc11d 100644 --- a/Mage.Sets/src/mage/cards/c/ConsulsLieutenant.java +++ b/Mage.Sets/src/mage/cards/c/ConsulsLieutenant.java @@ -37,7 +37,7 @@ public final class ConsulsLieutenant extends CardImpl { // Whenever Consul's Lieutenant attacks, if it's renowned, other attacking creatures you control get +1/+1 until end of turn. this.addAbility(new AttacksTriggeredAbility(new BoostControlledEffect( 1, 1, Duration.EndOfTurn, StaticFilters.FILTER_ATTACKING_CREATURES, true - )).withInterveningIf(RenownedSourceCondition.instance)); + )).withInterveningIf(RenownedSourceCondition.ITS)); } private ConsulsLieutenant(final ConsulsLieutenant card) { diff --git a/Mage.Sets/src/mage/cards/c/ConsulsShieldguard.java b/Mage.Sets/src/mage/cards/c/ConsulsShieldguard.java index 2efb58dae72..dfbe4a9d47d 100644 --- a/Mage.Sets/src/mage/cards/c/ConsulsShieldguard.java +++ b/Mage.Sets/src/mage/cards/c/ConsulsShieldguard.java @@ -16,6 +16,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.filter.common.FilterAttackingCreature; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -43,7 +44,7 @@ public final class ConsulsShieldguard extends CardImpl { // Whenever Consul's Shieldguard attacks, you may pay {E}. If you do, another target attacking creature gains indestructible until end of turn. Ability ability = new AttacksTriggeredAbility(new DoIfCostPaid(new GainAbilityTargetEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn), new PayEnergyCost(1))); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/ConsumeStrength.java b/Mage.Sets/src/mage/cards/c/ConsumeStrength.java index 4c2ad90b846..1cb173ebf76 100644 --- a/Mage.Sets/src/mage/cards/c/ConsumeStrength.java +++ b/Mage.Sets/src/mage/cards/c/ConsumeStrength.java @@ -1,23 +1,17 @@ - package mage.cards.c; -import java.util.UUID; -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.*; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.other.AnotherTargetPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.constants.CardType; +import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; -import mage.target.targetpointer.FixedTarget; +import mage.target.targetpointer.SecondTargetPointer; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class ConsumeStrength extends CardImpl { @@ -26,18 +20,11 @@ public final class ConsumeStrength extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}{G}"); // Target creature gets +2/+2 until end of turn. Another target creature gets -2/-2 until end of turn. - this.getSpellAbility().addEffect(new ConsumeStrengthEffect()); - - FilterCreaturePermanent filter1 = new FilterCreaturePermanent("creature to get +2/+2"); - TargetCreaturePermanent target1 = new TargetCreaturePermanent(filter1); - target1.setTargetTag(1); - this.getSpellAbility().addTarget(target1); - - FilterCreaturePermanent filter2 = new FilterCreaturePermanent("another creature to get -2/-2"); - filter2.add(new AnotherTargetPredicate(2)); - TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter2); - target2.setTargetTag(2); - this.getSpellAbility().addTarget(target2); + this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2)); + this.getSpellAbility().addEffect(new BoostTargetEffect(-2, -2) + .setText("another target creature gets -2/-2 until end of turn").setTargetPointer(new SecondTargetPointer())); + this.getSpellAbility().addTarget(new TargetCreaturePermanent().withChooseHint("+2/+2").setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2).withChooseHint("-2/-2").setTargetTag(2)); } private ConsumeStrength(final ConsumeStrength card) { @@ -49,37 +36,3 @@ public final class ConsumeStrength extends CardImpl { return new ConsumeStrength(this); } } - -class ConsumeStrengthEffect extends OneShotEffect { - - ConsumeStrengthEffect() { - super(Outcome.BoostCreature); - this.staticText = "Target creature gets +2/+2 until end of turn. Another target creature gets -2/-2 until end of turn"; - } - - private ConsumeStrengthEffect(final ConsumeStrengthEffect effect) { - super(effect); - } - - @Override - public ConsumeStrengthEffect copy() { - return new ConsumeStrengthEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getFirstTarget()); - if (permanent != null) { - ContinuousEffect effect = new BoostTargetEffect(2, 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, -2, Duration.EndOfTurn); - effect.setTargetPointer(new FixedTarget(permanent, game)); - game.addEffect(effect, source); - } - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/c/ConsumingSinkhole.java b/Mage.Sets/src/mage/cards/c/ConsumingSinkhole.java index 5b1c94faafc..c91f9e2ebf6 100644 --- a/Mage.Sets/src/mage/cards/c/ConsumingSinkhole.java +++ b/Mage.Sets/src/mage/cards/c/ConsumingSinkhole.java @@ -11,6 +11,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetPlayerOrPlaneswalker; @@ -36,7 +37,7 @@ public final class ConsumingSinkhole extends CardImpl { Effect effect = new ExileTargetEffect(); effect.setText("Exile target land creature"); this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // Consuming Sinkhole deals 4 damage to target player. Mode mode = new Mode(new DamageTargetEffect(4)); diff --git a/Mage.Sets/src/mage/cards/c/ContestOfClaws.java b/Mage.Sets/src/mage/cards/c/ContestOfClaws.java index 71ddea06b8c..530b4a9847e 100644 --- a/Mage.Sets/src/mage/cards/c/ContestOfClaws.java +++ b/Mage.Sets/src/mage/cards/c/ContestOfClaws.java @@ -14,9 +14,12 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2; + /** * * @author jimga150 @@ -32,7 +35,7 @@ public final class ContestOfClaws extends CardImpl { Target target = new TargetControlledCreaturePermanent().setTargetTag(1); this.getSpellAbility().addTarget(target); - Target target2 = new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2).setTargetTag(2); + Target target2 = new TargetPermanent(FILTER_ANOTHER_CREATURE_TARGET_2).setTargetTag(2); this.getSpellAbility().addTarget(target2); } diff --git a/Mage.Sets/src/mage/cards/c/ContestedCliffs.java b/Mage.Sets/src/mage/cards/c/ContestedCliffs.java index eece6e5d555..32d59b7b26f 100644 --- a/Mage.Sets/src/mage/cards/c/ContestedCliffs.java +++ b/Mage.Sets/src/mage/cards/c/ContestedCliffs.java @@ -18,8 +18,11 @@ import mage.constants.Zone; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -42,9 +45,9 @@ public final class ContestedCliffs extends CardImpl { Effect effect = new FightTargetsEffect(); Ability ability = new SimpleActivatedAbility(effect, new ManaCostsImpl<>("{R}{G}")); ability.addCost(new TapSourceCost()); - Target target1 = new TargetCreaturePermanent(filter1); + Target target1 = new TargetPermanent(filter1); ability.addTarget(target1); - Target target2 = new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE); + Target target2 = new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE); ability.addTarget(target2); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/ControlledInstincts.java b/Mage.Sets/src/mage/cards/c/ControlledInstincts.java index cd8e447f483..80801916ad4 100644 --- a/Mage.Sets/src/mage/cards/c/ControlledInstincts.java +++ b/Mage.Sets/src/mage/cards/c/ControlledInstincts.java @@ -39,7 +39,7 @@ public final class ControlledInstincts extends CardImpl { // Enchant red or green creature - TargetPermanent auraTarget = new TargetCreaturePermanent(filter); + TargetPermanent auraTarget = new TargetPermanent(filter); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); this.addAbility(new EnchantAbility(auraTarget)); diff --git a/Mage.Sets/src/mage/cards/c/CoralNet.java b/Mage.Sets/src/mage/cards/c/CoralNet.java index 2fccfb646fd..8526fadae55 100644 --- a/Mage.Sets/src/mage/cards/c/CoralNet.java +++ b/Mage.Sets/src/mage/cards/c/CoralNet.java @@ -41,7 +41,7 @@ public final class CoralNet extends CardImpl { this.subtype.add(SubType.AURA); // Enchant green or white creature - TargetPermanent auraTarget = new TargetCreaturePermanent(filter); + TargetPermanent auraTarget = new TargetPermanent(filter); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); this.addAbility(new EnchantAbility(auraTarget)); diff --git a/Mage.Sets/src/mage/cards/c/CoralReef.java b/Mage.Sets/src/mage/cards/c/CoralReef.java index 46bd9d0d43e..a8935d15e9b 100644 --- a/Mage.Sets/src/mage/cards/c/CoralReef.java +++ b/Mage.Sets/src/mage/cards/c/CoralReef.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; @@ -17,25 +16,23 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class CoralReef extends CardImpl { - + private static final FilterControlledPermanent islandFilter = new FilterControlledPermanent("an Island"); private static final FilterControlledCreaturePermanent untappedBlueCreatureFilter = new FilterControlledCreaturePermanent("an untapped blue creature you control"); - + static { islandFilter.add(SubType.ISLAND.getPredicate()); untappedBlueCreatureFilter.add(TappedPredicate.UNTAPPED); @@ -43,22 +40,22 @@ public final class CoralReef extends CardImpl { } public CoralReef(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}{U}"); // Coral Reef enters the battlefield with four polyp counters on it. Effect effect = new AddCountersSourceEffect(CounterType.POLYP.createInstance(4)); effect.setText("with four polyp counters on it"); this.addAbility(new EntersBattlefieldAbility(effect)); - + // Sacrifice an Island: Put two polyp counters on Coral Reef. effect = new AddCountersSourceEffect(CounterType.POLYP.createInstance(2), true); effect.setText("Put two polyp counters on {this}"); this.addAbility(new SimpleActivatedAbility(effect, new SacrificeTargetCost(islandFilter))); - + // {U}, Tap an untapped blue creature you control, Remove a polyp counter from Coral Reef: Put a +0/+1 counter on target creature. Ability ability = new SimpleActivatedAbility(new AddCountersTargetEffect(CounterType.P0P1.createInstance()), new ManaCostsImpl<>("{U}")); - ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(untappedBlueCreatureFilter))); + ability.addCost(new TapTargetCost(untappedBlueCreatureFilter)); ability.addCost(new RemoveCountersSourceCost(CounterType.POLYP.createInstance())); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/c/Corpsehatch.java b/Mage.Sets/src/mage/cards/c/Corpsehatch.java index 254bb590334..2a039f0f94c 100644 --- a/Mage.Sets/src/mage/cards/c/Corpsehatch.java +++ b/Mage.Sets/src/mage/cards/c/Corpsehatch.java @@ -8,8 +8,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; import mage.game.permanent.token.EldraziSpawnToken; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author North @@ -19,7 +22,7 @@ public final class Corpsehatch extends CardImpl { public Corpsehatch(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{B}{B}"); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); this.getSpellAbility().addEffect(new CreateTokenEffect(new EldraziSpawnToken(), 2).withTextOptions(true)); } diff --git a/Mage.Sets/src/mage/cards/c/CosmicHorror.java b/Mage.Sets/src/mage/cards/c/CosmicHorror.java index 4d01d7a3a47..5bc52c79bc8 100644 --- a/Mage.Sets/src/mage/cards/c/CosmicHorror.java +++ b/Mage.Sets/src/mage/cards/c/CosmicHorror.java @@ -16,7 +16,6 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import java.util.Locale; import java.util.UUID; /** @@ -34,7 +33,7 @@ public final class CosmicHorror extends CardImpl { this.addAbility(FirstStrikeAbility.getInstance()); // At the beginning of your upkeep, destroy Cosmic Horror unless you pay {3}{B}{B}{B}. If Cosmic Horror is destroyed this way, it deals 7 damage to you. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new CosmicHorrorEffect(new ManaCostsImpl<>("{3}{B}{B}{B}")))); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new CosmicHorrorEffect())); } private CosmicHorror(final CosmicHorror card) { @@ -49,30 +48,22 @@ public final class CosmicHorror extends CardImpl { class CosmicHorrorEffect extends OneShotEffect { - protected Cost cost; - - public CosmicHorrorEffect(Cost cost) { + CosmicHorrorEffect() { super(Outcome.DestroyPermanent); - this.cost = cost; - staticText = "destroy {this} unless you pay {3}{B}{B}{B}. If {this} is destroyed this way it deals 7 damage to you"; + staticText = "destroy {this} unless you pay {3}{B}{B}{B}. If {this} is destroyed this way, it deals 7 damage to you"; } private CosmicHorrorEffect(final CosmicHorrorEffect effect) { super(effect); - this.cost = effect.cost.copy(); } @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - Permanent cosmicHorror = game.getPermanentOrLKIBattlefield(source.getSourceId()); + Permanent cosmicHorror = source.getSourcePermanentIfItStillExists(game); if (controller != null && cosmicHorror != null) { - StringBuilder sb = new StringBuilder(cost.getText()).append('?'); - if (!sb.toString().toLowerCase(Locale.ENGLISH).startsWith("exile ") && !sb.toString().toLowerCase(Locale.ENGLISH).startsWith("return ")) { - sb.insert(0, "Pay "); - } - if (controller.chooseUse(Outcome.Benefit, sb.toString(), source, game)) { - cost.clearPaid(); + if (controller.chooseUse(Outcome.Benefit, "Pay {3}{B}{B}{B} to prevent destroy effect?", source, game)) { + Cost cost = new ManaCostsImpl<>("{3}{B}{B}{B}"); if (cost.pay(source, game, source, source.getControllerId(), false, null)) { return true; } diff --git a/Mage.Sets/src/mage/cards/c/CourtStreetDenizen.java b/Mage.Sets/src/mage/cards/c/CourtStreetDenizen.java index d2d133e22f1..14846759d64 100644 --- a/Mage.Sets/src/mage/cards/c/CourtStreetDenizen.java +++ b/Mage.Sets/src/mage/cards/c/CourtStreetDenizen.java @@ -15,8 +15,11 @@ import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -38,7 +41,7 @@ public final class CourtStreetDenizen extends CardImpl { // Whenever another white creature you control enters, tap target creature an opponent controls. Ability ability = new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new TapTargetEffect(), filter, false); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CrackInTime.java b/Mage.Sets/src/mage/cards/c/CrackInTime.java index 3213303b327..afe8a24b114 100644 --- a/Mage.Sets/src/mage/cards/c/CrackInTime.java +++ b/Mage.Sets/src/mage/cards/c/CrackInTime.java @@ -11,10 +11,13 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * @author Susucr */ @@ -32,7 +35,7 @@ public final class CrackInTime extends CardImpl { new EntersBattlefieldTriggeredAbility(null), new BeginningOfFirstMainTriggeredAbility(null) ); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/Crackleburr.java b/Mage.Sets/src/mage/cards/c/Crackleburr.java index 861aecc1944..9674500e9a2 100644 --- a/Mage.Sets/src/mage/cards/c/Crackleburr.java +++ b/Mage.Sets/src/mage/cards/c/Crackleburr.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; import mage.abilities.Ability; @@ -17,34 +15,34 @@ 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.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetAnyTarget; +import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; -/** - * - * @author jeffwadsworth +import java.util.UUID; +/** + * @author jeffwadsworth */ public final class Crackleburr extends CardImpl { - - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped red creatures you control"); - private static final FilterControlledCreaturePermanent filter2 = new FilterControlledCreaturePermanent("tapped blue creature you control"); - + + private static final FilterControlledPermanent filter = new FilterControlledCreaturePermanent("untapped red creatures you control"); + private static final FilterControlledPermanent filter2 = new FilterControlledCreaturePermanent("tapped blue creature you control"); + static { filter.add(new ColorPredicate(ObjectColor.RED)); filter.add(TappedPredicate.UNTAPPED); - + filter2.add(new ColorPredicate(ObjectColor.BLUE)); filter2.add(TappedPredicate.TAPPED); } public Crackleburr(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U/R}{U/R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U/R}{U/R}"); this.subtype.add(SubType.ELEMENTAL); this.power = new MageInt(2); @@ -53,17 +51,16 @@ public final class Crackleburr extends CardImpl { // {UR}{UR}, {tap}, Tap two untapped red creatures you control: Crackleburr deals 3 damage to any target. Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(3), new ManaCostsImpl<>("{U/R}{U/R}")); ability.addCost(new TapSourceCost()); - ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(2, 2, filter, true))); + ability.addCost(new TapTargetCost(new TargetControlledPermanent(2, filter))); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); - + // {UR}{UR}, {untap}, Untap two tapped blue creatures you control: Return target creature to its owner's hand. Ability ability2 = new SimpleActivatedAbility(new ReturnToHandTargetEffect(), new ManaCostsImpl<>("{U/R}{U/R}")); ability2.addCost(new UntapSourceCost()); - ability2.addCost(new UntapTargetCost(new TargetControlledCreaturePermanent(2, 2, filter2, true))); + ability2.addCost(new UntapTargetCost(new TargetControlledPermanent(2, filter2))); ability2.addTarget(new TargetCreaturePermanent()); this.addAbility(ability2); - } private Crackleburr(final Crackleburr card) { diff --git a/Mage.Sets/src/mage/cards/c/CracklingDoom.java b/Mage.Sets/src/mage/cards/c/CracklingDoom.java index 107510d19af..5b00be3738d 100644 --- a/Mage.Sets/src/mage/cards/c/CracklingDoom.java +++ b/Mage.Sets/src/mage/cards/c/CracklingDoom.java @@ -15,14 +15,13 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.ArrayList; import java.util.List; import java.util.UUID; /** - * * @author LevelX2 */ public final class CracklingDoom extends CardImpl { @@ -49,9 +48,11 @@ public final class CracklingDoom extends CardImpl { class CracklingDoomEffect extends OneShotEffect { static FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature with the greatest power among creatures you control"); + static { filter.add(GreatestPowerControlledPredicate.instance); } + public CracklingDoomEffect() { super(Outcome.Sacrifice); this.staticText = "Each opponent sacrifices a creature with the greatest power among creatures that player controls"; @@ -75,7 +76,7 @@ class CracklingDoomEffect extends OneShotEffect { if (controller.hasOpponent(playerId, game)) { Player opponent = game.getPlayer(playerId); if (opponent != null) { - Target target = new TargetControlledCreaturePermanent(filter); + Target target = new TargetPermanent(filter); target.withNotTarget(true); if (opponent.choose(outcome, target, source, game)) { Permanent permanent = game.getPermanent(target.getFirstTarget()); diff --git a/Mage.Sets/src/mage/cards/c/CradleToGrave.java b/Mage.Sets/src/mage/cards/c/CradleToGrave.java index 891f2598985..54195e27d7e 100644 --- a/Mage.Sets/src/mage/cards/c/CradleToGrave.java +++ b/Mage.Sets/src/mage/cards/c/CradleToGrave.java @@ -11,6 +11,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.permanent.EnteredThisTurnPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -30,7 +31,7 @@ public final class CradleToGrave extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{B}"); // Destroy target nonblack creature that entered the battlefield this turn. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); } diff --git a/Mage.Sets/src/mage/cards/c/CraftyPathmage.java b/Mage.Sets/src/mage/cards/c/CraftyPathmage.java index 0da1201b615..85a23d16eea 100644 --- a/Mage.Sets/src/mage/cards/c/CraftyPathmage.java +++ b/Mage.Sets/src/mage/cards/c/CraftyPathmage.java @@ -15,6 +15,7 @@ import mage.constants.ComparisonType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -39,7 +40,7 @@ public final class CraftyPathmage extends CardImpl { // {tap}: Target creature with power 2 or less can't be blocked this turn. Ability ability = new SimpleActivatedAbility(new CantBeBlockedTargetEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CrashLanding.java b/Mage.Sets/src/mage/cards/c/CrashLanding.java index bd667657fd5..c075f6df546 100644 --- a/Mage.Sets/src/mage/cards/c/CrashLanding.java +++ b/Mage.Sets/src/mage/cards/c/CrashLanding.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -39,7 +40,7 @@ public final class CrashLanding extends CardImpl { this.getSpellAbility().addEffect(new LoseAbilityTargetEffect( FlyingAbility.getInstance(), Duration.EndOfTurn)); this.getSpellAbility().addEffect(new DamageTargetEffect(amount).setText("{this} deals damage to that creature equal to the number of Forests you control")); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter2)); + this.getSpellAbility().addTarget(new TargetPermanent(filter2)); } private CrashLanding(final CrashLanding card) { diff --git a/Mage.Sets/src/mage/cards/c/CrashingBoars.java b/Mage.Sets/src/mage/cards/c/CrashingBoars.java index 87806c9607b..375dc6f7763 100644 --- a/Mage.Sets/src/mage/cards/c/CrashingBoars.java +++ b/Mage.Sets/src/mage/cards/c/CrashingBoars.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; @@ -11,25 +9,28 @@ import mage.abilities.effects.common.combat.MustBeBlockedByTargetSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; import mage.constants.SetTargetPointer; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; import mage.players.Player; import mage.target.Target; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author emerald000 */ public final class CrashingBoars extends CardImpl { public CrashingBoars(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}"); this.subtype.add(SubType.BOAR); this.power = new MageInt(4); this.toughness = new MageInt(4); @@ -49,38 +50,42 @@ public final class CrashingBoars extends CardImpl { } class CrashingBoarsEffect extends OneShotEffect { - - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); + + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); + static { filter.add(TappedPredicate.UNTAPPED); } - + CrashingBoarsEffect() { super(Outcome.Benefit); this.staticText = "defending player chooses an untapped creature they control. That creature blocks {this} this turn if able"; } - + private CrashingBoarsEffect(final CrashingBoarsEffect effect) { super(effect); } - + @Override public CrashingBoarsEffect copy() { return new CrashingBoarsEffect(this); } - + @Override public boolean apply(Game game, Ability source) { Player defendingPlayer = game.getPlayer(this.getTargetPointer().getFirst(game, source)); - if (defendingPlayer != null) { - Target target = new TargetControlledCreaturePermanent(1, 1, filter, true); - if (target.choose(Outcome.Neutral, defendingPlayer.getId(), source.getSourceId(), source, game)) { - RequirementEffect effect = new MustBeBlockedByTargetSourceEffect(); - effect.setTargetPointer(new FixedTarget(target.getFirstTarget(), game)); - game.addEffect(effect, source); - } - return true; + if (defendingPlayer == null || !game.getBattlefield().contains( + StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURE, + defendingPlayer.getId(), source, game, 1 + )) { + return false; } - return false; + Target target = new TargetPermanent(StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURE); + target.withNotTarget(true); + defendingPlayer.choose(Outcome.Neutral, target, source, game); + RequirementEffect effect = new MustBeBlockedByTargetSourceEffect(); + effect.setTargetPointer(new FixedTarget(target.getFirstTarget(), game)); + game.addEffect(effect, source); + return true; } } diff --git a/Mage.Sets/src/mage/cards/c/CraterElemental.java b/Mage.Sets/src/mage/cards/c/CraterElemental.java index aa0bea29657..b9377dc293d 100644 --- a/Mage.Sets/src/mage/cards/c/CraterElemental.java +++ b/Mage.Sets/src/mage/cards/c/CraterElemental.java @@ -12,7 +12,10 @@ import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.continuous.SetBasePowerSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.AbilityWord; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -38,14 +41,10 @@ public final class CraterElemental extends CardImpl { this.addAbility(ability); // Formidable — {2}{R}: Crater Elemental has base power 8 until end of turn. Activate this ability only if creatures you control have total power 8 or greater. - ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, + this.addAbility(new ActivateIfConditionActivatedAbility( new SetBasePowerSourceEffect(8, Duration.EndOfTurn), - new ManaCostsImpl<>("{2}{R}"), - FormidableCondition.instance - ); - ability.setAbilityWord(AbilityWord.FORMIDABLE); - this.addAbility(ability); + new ManaCostsImpl<>("{2}{R}"), FormidableCondition.instance + ).setAbilityWord(AbilityWord.FORMIDABLE)); } private CraterElemental(final CraterElemental card) { diff --git a/Mage.Sets/src/mage/cards/c/CrawlingSensation.java b/Mage.Sets/src/mage/cards/c/CrawlingSensation.java index b5e844cb915..b6688f2adf3 100644 --- a/Mage.Sets/src/mage/cards/c/CrawlingSensation.java +++ b/Mage.Sets/src/mage/cards/c/CrawlingSensation.java @@ -1,10 +1,9 @@ package mage.cards.c; -import java.util.UUID; import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.MillCardsControllerEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -15,8 +14,9 @@ import mage.game.events.GameEvent; import mage.game.events.ZoneChangeGroupEvent; import mage.game.permanent.token.InsectToken; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class CrawlingSensation extends CardImpl { @@ -25,7 +25,7 @@ public final class CrawlingSensation extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); // At the beginning of your upkeep, you may put the top two cards of your library into your graveyard. - this.addAbility(new OnEventTriggeredAbility(GameEvent.EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", new MillCardsControllerEffect(2), true)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new MillCardsControllerEffect(2), true)); // Whenever one or more land cards are put into your graveyard from anywhere for the first time each turn, create a 1/1 green Insect creature token. this.addAbility(new CrawlingSensationTriggeredAbility()); diff --git a/Mage.Sets/src/mage/cards/c/CreepingInn.java b/Mage.Sets/src/mage/cards/c/CreepingInn.java index 22cdd1d9244..106c64a1076 100644 --- a/Mage.Sets/src/mage/cards/c/CreepingInn.java +++ b/Mage.Sets/src/mage/cards/c/CreepingInn.java @@ -13,7 +13,6 @@ 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.ExileZone; import mage.game.Game; @@ -64,7 +63,7 @@ class CreepingInnEffect extends OneShotEffect { super(Outcome.Exile); this.staticText = "you may exile a creature card from your graveyard. " + "If you do, each opponent loses X life and you gain X life, " + - "where X is the number of creature cards exiled with Creeping Inn."; + "where X is the number of creature cards exiled with {this}."; } private CreepingInnEffect(final CreepingInnEffect effect) { diff --git a/Mage.Sets/src/mage/cards/c/CroakingCounterpart.java b/Mage.Sets/src/mage/cards/c/CroakingCounterpart.java index a7172e58211..419dc393dde 100644 --- a/Mage.Sets/src/mage/cards/c/CroakingCounterpart.java +++ b/Mage.Sets/src/mage/cards/c/CroakingCounterpart.java @@ -13,6 +13,7 @@ import mage.constants.SubType; import mage.constants.TimingRule; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -39,7 +40,7 @@ public final class CroakingCounterpart extends CardImpl { effect.setOnlySubType(SubType.FROG); effect.setText("Create a token that's a copy of target non-Frog creature, except it's a 1/1 green Frog"); this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // Flashback {3}{G}{U} this.addAbility(new FlashbackAbility(this, new ManaCostsImpl<>("{3}{G}{U}"))); diff --git a/Mage.Sets/src/mage/cards/c/CropSigil.java b/Mage.Sets/src/mage/cards/c/CropSigil.java index e5e3284ebe9..e96d2e1a4b9 100644 --- a/Mage.Sets/src/mage/cards/c/CropSigil.java +++ b/Mage.Sets/src/mage/cards/c/CropSigil.java @@ -1,25 +1,24 @@ package mage.cards.c; -import java.util.UUID; - import mage.abilities.Ability; -import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.DeliriumCondition; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; +import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.effects.common.MillCardsControllerEffect; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AbilityWord; import mage.constants.CardType; -import mage.constants.Zone; import mage.filter.StaticFilters; import mage.target.common.TargetCardInYourGraveyard; import mage.target.targetpointer.EachTargetPointer; +import java.util.UUID; + /** * @author fireshoes */ @@ -33,17 +32,14 @@ public final class CropSigil extends CardImpl { // Delirium — {2}{G}, Sacrifice Crop Sigil: Return up to one target creature card and up to one target land card from your graveyard to your hand. // Activate this ability only if there are four or more card types among cards in your graveyard. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, + Ability ability = new ActivateIfConditionActivatedAbility( new ReturnFromGraveyardToHandTargetEffect().setTargetPointer(new EachTargetPointer()), - new ManaCostsImpl<>("{2}{G}"), - DeliriumCondition.instance); + new ManaCostsImpl<>("{2}{G}"), DeliriumCondition.instance + ); ability.addCost(new SacrificeSourceCost()); ability.addTarget(new TargetCardInYourGraveyard(0, 1, StaticFilters.FILTER_CARD_CREATURE)); ability.addTarget(new TargetCardInYourGraveyard(0, 1, StaticFilters.FILTER_CARD_LAND)); - ability.setAbilityWord(AbilityWord.DELIRIUM); - ability.addHint(CardTypesInGraveyardCount.YOU.getHint()); - this.addAbility(ability); + this.addAbility(ability.setAbilityWord(AbilityWord.DELIRIUM).addHint(CardTypesInGraveyardCount.YOU.getHint())); } private CropSigil(final CropSigil card) { diff --git a/Mage.Sets/src/mage/cards/c/CrosissCharm.java b/Mage.Sets/src/mage/cards/c/CrosissCharm.java index 6b1f220a260..96a79f17cc4 100644 --- a/Mage.Sets/src/mage/cards/c/CrosissCharm.java +++ b/Mage.Sets/src/mage/cards/c/CrosissCharm.java @@ -13,6 +13,8 @@ import mage.target.TargetPermanent; import mage.target.common.TargetArtifactPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author LevelX2 @@ -27,7 +29,7 @@ public final class CrosissCharm extends CardImpl { this.getSpellAbility().addTarget(new TargetPermanent()); // or destroy target nonblack creature, and it can't be regenerated; Mode mode = new Mode(new DestroyTargetEffect(true)); - mode.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + mode.addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.getSpellAbility().addMode(mode); // or destroy target artifact. mode = new Mode(new DestroyTargetEffect()); diff --git a/Mage.Sets/src/mage/cards/c/CrownOfDoom.java b/Mage.Sets/src/mage/cards/c/CrownOfDoom.java index 3f88e155142..c9ea284b93a 100644 --- a/Mage.Sets/src/mage/cards/c/CrownOfDoom.java +++ b/Mage.Sets/src/mage/cards/c/CrownOfDoom.java @@ -4,16 +4,18 @@ import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.common.AttacksAllTriggeredAbility; import mage.abilities.condition.common.MyTurnCondition; -import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.ContinuousEffect; -import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.abilities.hint.common.MyTurnHint; 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.SetTargetPointer; import mage.filter.FilterPlayer; import mage.filter.StaticFilters; import mage.filter.predicate.ObjectSourcePlayer; @@ -42,22 +44,18 @@ public final class CrownOfDoom extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); // Whenever a creature attacks you or a planeswalker you control, it gets +2/+0 until end of turn. - Effect effect = new BoostTargetEffect(2, 0, Duration.EndOfTurn); - effect.setText("it gets +2/+0 until end of turn"); this.addAbility(new AttacksAllTriggeredAbility( - effect, - false, - StaticFilters.FILTER_PERMANENT_CREATURE, - SetTargetPointer.PERMANENT, - true)); + new BoostTargetEffect(2, 0, Duration.EndOfTurn) + .setText("it gets +2/+0 until end of turn"), + false, StaticFilters.FILTER_PERMANENT_CREATURE, + SetTargetPointer.PERMANENT, true + )); // {2}: Target player other than Crown of Doom's owner gains control of it. Activate this ability only during your turn. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, - new CrownOfDoomEffect(), - new ManaCostsImpl<>("{2}"), - MyTurnCondition.instance); - ability.addTarget(new TargetPlayer(1, 1, false, filter)); + new CrownOfDoomEffect(), new GenericManaCost(2), MyTurnCondition.instance + ); + ability.addTarget(new TargetPlayer(filter)); ability.addHint(MyTurnHint.instance); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CruelCut.java b/Mage.Sets/src/mage/cards/c/CruelCut.java index 075e67261a9..e22e130756b 100644 --- a/Mage.Sets/src/mage/cards/c/CruelCut.java +++ b/Mage.Sets/src/mage/cards/c/CruelCut.java @@ -7,6 +7,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -28,7 +29,7 @@ public final class CruelCut extends CardImpl { // Destroy target creature with power 2 or less. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private CruelCut(final CruelCut card) { diff --git a/Mage.Sets/src/mage/cards/c/CruelDeceiver.java b/Mage.Sets/src/mage/cards/c/CruelDeceiver.java index db1d48f65c4..0e923f3ee06 100644 --- a/Mage.Sets/src/mage/cards/c/CruelDeceiver.java +++ b/Mage.Sets/src/mage/cards/c/CruelDeceiver.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; @@ -15,14 +14,12 @@ import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.LookLibraryControllerEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.cards.*; -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.players.Player; +import java.util.UUID; + /** * * @author LevelX2 @@ -57,7 +54,7 @@ class CruelDeceiverEffect extends OneShotEffect { CruelDeceiverEffect() { super(Outcome.AddAbility); - this.staticText = "Reveal the top card of your library. If it's a land card, {this} gains \"Whenever Cruel Deceiver deals damage to a creature, destroy that creature\" until end of turn"; + this.staticText = "Reveal the top card of your library. If it's a land card, {this} gains \"Whenever {this} deals damage to a creature, destroy that creature\" until end of turn"; } private CruelDeceiverEffect(final CruelDeceiverEffect effect) { diff --git a/Mage.Sets/src/mage/cards/c/CrumblingAshes.java b/Mage.Sets/src/mage/cards/c/CrumblingAshes.java index eba3857a9a1..907864f6625 100644 --- a/Mage.Sets/src/mage/cards/c/CrumblingAshes.java +++ b/Mage.Sets/src/mage/cards/c/CrumblingAshes.java @@ -11,6 +11,7 @@ import mage.constants.CardType; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -31,7 +32,7 @@ public final class CrumblingAshes extends CardImpl { // At the beginning of your upkeep, destroy target creature with a -1/-1 counter on it. Ability ability = new BeginningOfUpkeepTriggeredAbility(new DestroyTargetEffect()); - Target target = new TargetCreaturePermanent(filter); + Target target = new TargetPermanent(filter); ability.addTarget(target); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/c/CrushUnderfoot.java b/Mage.Sets/src/mage/cards/c/CrushUnderfoot.java index 1df8a71620c..f802c195bf0 100644 --- a/Mage.Sets/src/mage/cards/c/CrushUnderfoot.java +++ b/Mage.Sets/src/mage/cards/c/CrushUnderfoot.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; @@ -9,30 +7,29 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class CrushUnderfoot extends CardImpl { public CrushUnderfoot(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.KINDRED,CardType.INSTANT},"{1}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.KINDRED, CardType.INSTANT}, "{1}{R}"); this.subtype.add(SubType.GIANT); - // Choose a Giant creature you control. It deals damage equal to its power to target creature. this.getSpellAbility().addEffect(new CrushUnderfootEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature damage is dealt to"))); - + this.getSpellAbility().addTarget(new TargetCreaturePermanent().withChooseHint("to deal damage to")); } private CrushUnderfoot(final CrushUnderfoot card) { @@ -47,10 +44,7 @@ public final class CrushUnderfoot extends CardImpl { class CrushUnderfootEffect extends OneShotEffect { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Giant creature you control"); - static { - filter.add(SubType.GIANT.getPredicate()); - } + private static final FilterPermanent filter = new FilterControlledCreaturePermanent(SubType.GIANT, "Giant creature you control"); public CrushUnderfootEffect() { super(Outcome.Damage); @@ -69,22 +63,24 @@ class CrushUnderfootEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - // Choose a Giant creature you control (not targeted, happens during effect resolving ) - Target target = new TargetControlledCreaturePermanent(1,1, filter,false); - if (target.canChoose(controller.getId(), source, game) - && controller.chooseTarget(outcome, target, source, game)) { - Permanent giant = game.getPermanent(target.getFirstTarget()); - if (giant != null) { - game.informPlayers("Crush Underfoot: Chosen Giant is " + giant.getName()); - Permanent targetCreature = game.getPermanent(this.getTargetPointer().getFirst(game, source)); - if (targetCreature != null) { - targetCreature.damage(giant.getPower().getValue(), source.getSourceId(), source, game, false, true); - return true; - } - } - } + if (controller == null) { + return false; } - return false; + // Choose a Giant creature you control (not targeted, happens during effect resolving ) + Target target = new TargetPermanent(filter); + target.withNotTarget(true); + if (!target.canChoose(controller.getId(), source, game) + || !controller.chooseTarget(outcome, target, source, game)) { + return false; + } + Permanent giant = game.getPermanent(target.getFirstTarget()); + if (giant == null) { + return false; + } + game.informPlayers("Crush Underfoot: Chosen Giant is " + giant.getName()); + Permanent targetCreature = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + return targetCreature != null && targetCreature.damage( + giant.getPower().getValue(), source.getSourceId(), source, game, false, true + ) > 0; } } diff --git a/Mage.Sets/src/mage/cards/c/CrushingCanopy.java b/Mage.Sets/src/mage/cards/c/CrushingCanopy.java index e55610d8772..7ca22a17ec1 100644 --- a/Mage.Sets/src/mage/cards/c/CrushingCanopy.java +++ b/Mage.Sets/src/mage/cards/c/CrushingCanopy.java @@ -10,6 +10,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetEnchantmentPermanent; @@ -30,7 +31,7 @@ public final class CrushingCanopy extends CardImpl { // Choose one -- // * Destroy target creature with flying. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); // * Destroy target enchantment. Mode mode = new Mode(new DestroyTargetEffect()); diff --git a/Mage.Sets/src/mage/cards/c/CrushingVines.java b/Mage.Sets/src/mage/cards/c/CrushingVines.java index 4492a1c88cb..43cc576d3d8 100644 --- a/Mage.Sets/src/mage/cards/c/CrushingVines.java +++ b/Mage.Sets/src/mage/cards/c/CrushingVines.java @@ -10,6 +10,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetArtifactPermanent; import mage.target.common.TargetCreaturePermanent; @@ -30,7 +31,7 @@ public final class CrushingVines extends CardImpl { // Choose one - Destroy target creature with flying; or destroy target artifact. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); Mode mode = new Mode(new DestroyTargetEffect()); mode.addTarget(new TargetArtifactPermanent()); diff --git a/Mage.Sets/src/mage/cards/c/Cryptex.java b/Mage.Sets/src/mage/cards/c/Cryptex.java index 0972dbec9cd..d3266951d55 100644 --- a/Mage.Sets/src/mage/cards/c/Cryptex.java +++ b/Mage.Sets/src/mage/cards/c/Cryptex.java @@ -4,7 +4,7 @@ import mage.abilities.Ability; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.CollectEvidenceCost; import mage.abilities.costs.common.SacrificeSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.keyword.SurveilEffect; @@ -31,7 +31,7 @@ public final class Cryptex extends CardImpl { this.addAbility(ability); // Sacrifice Cryptex: Surveil 3, then draw three cards. Activate only if Cryptex has five or more unlock counters on it. - Ability sacAbility = new ConditionalActivatedAbility(new SurveilEffect(3, false), new SacrificeSourceCost(), + Ability sacAbility = new ActivateIfConditionActivatedAbility(new SurveilEffect(3, false), new SacrificeSourceCost(), new SourceHasCounterCondition(CounterType.UNLOCK, 5)); sacAbility.addEffect(new DrawCardSourceControllerEffect(3).concatBy(", then")); this.addAbility(sacAbility); diff --git a/Mage.Sets/src/mage/cards/c/CrypticCaves.java b/Mage.Sets/src/mage/cards/c/CrypticCaves.java index 477b0128c45..6bb1fbb463f 100644 --- a/Mage.Sets/src/mage/cards/c/CrypticCaves.java +++ b/Mage.Sets/src/mage/cards/c/CrypticCaves.java @@ -8,13 +8,12 @@ import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.hint.common.LandsYouControlHint; import mage.abilities.mana.ColorlessManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; -import mage.constants.Zone; -import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledLandPermanent; import java.util.UUID; @@ -24,10 +23,9 @@ import java.util.UUID; */ public final class CrypticCaves extends CardImpl { - private static final FilterPermanent filter - = new FilterControlledLandPermanent("you control five or more lands"); - private static final Condition condition - = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 4); + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledLandPermanent("you control five or more lands"), ComparisonType.MORE_THAN, 4 + ); public CrypticCaves(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); @@ -37,12 +35,11 @@ public final class CrypticCaves extends CardImpl { // {1}, {T}, Sacrifice Cryptic Caves: Draw a card. Activate this ability only if you control five or more lands. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), - new GenericManaCost(1), condition + new DrawCardSourceControllerEffect(1), new GenericManaCost(1), condition ); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); - this.addAbility(ability); + this.addAbility(ability.addHint(LandsYouControlHint.instance)); } private CrypticCaves(final CrypticCaves card) { diff --git a/Mage.Sets/src/mage/cards/c/Cryptoplasm.java b/Mage.Sets/src/mage/cards/c/Cryptoplasm.java index cf026f39adf..992c3065349 100644 --- a/Mage.Sets/src/mage/cards/c/Cryptoplasm.java +++ b/Mage.Sets/src/mage/cards/c/Cryptoplasm.java @@ -15,6 +15,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.util.functions.CopyApplier; @@ -40,7 +41,7 @@ public final class Cryptoplasm extends CardImpl { // At the beginning of your upkeep, you may have Cryptoplasm become a copy of another target creature. If you do, Cryptoplasm gains this ability. Ability ability = new BeginningOfUpkeepTriggeredAbility(new CryptoplasmEffect(), true); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CultConscript.java b/Mage.Sets/src/mage/cards/c/CultConscript.java index 4c8f1f78044..35efa4a9d12 100644 --- a/Mage.Sets/src/mage/cards/c/CultConscript.java +++ b/Mage.Sets/src/mage/cards/c/CultConscript.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTappedAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; import mage.constants.SubType; import mage.cards.CardImpl; @@ -39,7 +39,7 @@ public final class CultConscript extends CardImpl { this.addAbility(new EntersBattlefieldTappedAbility()); // {1}{B}: Return Cult Conscript from your graveyard to the battlefield. Activate only if a non-Skeleton creature died under your control this turn. - this.addAbility(new ConditionalActivatedAbility( + this.addAbility(new ActivateIfConditionActivatedAbility( Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldEffect(false, false), new ManaCostsImpl<>("{1}{B}"), diff --git a/Mage.Sets/src/mage/cards/c/CultivatorOfBlades.java b/Mage.Sets/src/mage/cards/c/CultivatorOfBlades.java index c5631434c44..1211fff8723 100644 --- a/Mage.Sets/src/mage/cards/c/CultivatorOfBlades.java +++ b/Mage.Sets/src/mage/cards/c/CultivatorOfBlades.java @@ -32,7 +32,7 @@ public final class CultivatorOfBlades extends CardImpl { // Whenever Cultivator of Blades attacks, you may have other attacking creatures get +X/+X until end of turn, where X is Cultivator of Blades's power. this.addAbility(new AttacksTriggeredAbility(new BoostControlledEffect(SourcePermanentPowerValue.NOT_NEGATIVE, SourcePermanentPowerValue.NOT_NEGATIVE, Duration.EndOfTurn, StaticFilters.FILTER_ATTACKING_CREATURES, true), - true, "Whenever Cultivator of Blades attacks, you may have other attacking creatures get +X/+X until end of turn, where X is Cultivator of Blades's power.")); + true, "Whenever {this} attacks, you may have other attacking creatures get +X/+X until end of turn, where X is {this}'s power.")); } private CultivatorOfBlades(final CultivatorOfBlades card) { diff --git a/Mage.Sets/src/mage/cards/c/CulturalExchange.java b/Mage.Sets/src/mage/cards/c/CulturalExchange.java index 8e6820e0200..b876d746db0 100644 --- a/Mage.Sets/src/mage/cards/c/CulturalExchange.java +++ b/Mage.Sets/src/mage/cards/c/CulturalExchange.java @@ -14,8 +14,8 @@ import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.TargetPlayer; -import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; import java.util.UUID; @@ -79,10 +79,10 @@ class CulturalExchangeEffect extends OneShotEffect { if (creaturesToSwitch == 0) { return true; } - TargetCreaturePermanent target1 = new TargetCreaturePermanent(0, creaturesToSwitch, filter1, true); + TargetPermanent target1 = new TargetPermanent(0, creaturesToSwitch, filter1, true); if (target1.choose(Outcome.Benefit, controller.getId(), source.getSourceId(), source, game)) { int otherToSwitch = target1.getTargets().size(); - TargetCreaturePermanent target2 = new TargetCreaturePermanent(otherToSwitch, otherToSwitch, filter2, true); + TargetPermanent target2 = new TargetPermanent(otherToSwitch, otherToSwitch, filter2, true); if (target2.choose(Outcome.Benefit, controller.getId(), source.getSourceId(), source, game)) { for (UUID creatureId : target1.getTargets()) { Permanent creature = game.getPermanent(creatureId); diff --git a/Mage.Sets/src/mage/cards/c/CunningAdvisor.java b/Mage.Sets/src/mage/cards/c/CunningAdvisor.java index 0ef8c384154..5ec352170ea 100644 --- a/Mage.Sets/src/mage/cards/c/CunningAdvisor.java +++ b/Mage.Sets/src/mage/cards/c/CunningAdvisor.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; @@ -12,25 +10,27 @@ 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 fireshoes */ public final class CunningAdvisor extends CardImpl { public CunningAdvisor(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.HUMAN); this.subtype.add(SubType.ADVISOR); this.power = new MageInt(1); this.toughness = new MageInt(1); // {tap}: Target opponent discards a card. Activate this ability only during your turn, before attackers are declared. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new DiscardTargetEffect(1), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new DiscardTargetEffect(1), new TapSourceCost(), + MyTurnBeforeAttackersDeclaredCondition.instance + ); ability.addTarget(new TargetOpponent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CunningLethemancer.java b/Mage.Sets/src/mage/cards/c/CunningLethemancer.java index 8bf48e56af8..6db2bc16b5a 100644 --- a/Mage.Sets/src/mage/cards/c/CunningLethemancer.java +++ b/Mage.Sets/src/mage/cards/c/CunningLethemancer.java @@ -1,31 +1,29 @@ - package mage.cards.c; -import java.util.UUID; import mage.MageInt; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.effects.common.discard.DiscardEachPlayerEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.game.events.GameEvent.EventType; + +import java.util.UUID; /** - * * @author North */ public final class CunningLethemancer extends CardImpl { public CunningLethemancer(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.HUMAN); this.subtype.add(SubType.WIZARD); this.power = new MageInt(2); this.toughness = new MageInt(2); - this.addAbility(new OnEventTriggeredAbility(EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", new DiscardEachPlayerEffect())); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DiscardEachPlayerEffect())); } private CunningLethemancer(final CunningLethemancer card) { diff --git a/Mage.Sets/src/mage/cards/c/Curfew.java b/Mage.Sets/src/mage/cards/c/Curfew.java index bfcb760aa8c..903e3720e0a 100644 --- a/Mage.Sets/src/mage/cards/c/Curfew.java +++ b/Mage.Sets/src/mage/cards/c/Curfew.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; @@ -13,10 +11,12 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; +import java.util.UUID; + /** - * * @author maxlebedev */ public final class Curfew extends CardImpl { @@ -51,16 +51,17 @@ class CurfewEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - game.informPlayers("Each player returns a creature they control to its owner's hand"); for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { Player player = game.getPlayer(playerId); - if (player != null && game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURE, playerId, game) > 0) { - TargetControlledCreaturePermanent target = new TargetControlledCreaturePermanent(1, 1, StaticFilters.FILTER_CONTROLLED_CREATURE, true); - player.choose(Outcome.ReturnToHand, target, source, game); - Permanent permanent = game.getPermanent(target.getFirstTarget()); - if (permanent != null) { - player.moveCards(permanent, Zone.HAND, source, game); - } + if (player == null || game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURE, playerId, game) <= 0) { + continue; + } + TargetPermanent target = new TargetControlledCreaturePermanent(); + target.withNotTarget(true); + player.choose(Outcome.ReturnToHand, target, source, game); + Permanent permanent = game.getPermanent(target.getFirstTarget()); + if (permanent != null) { + player.moveCards(permanent, Zone.HAND, source, game); } } return true; diff --git a/Mage.Sets/src/mage/cards/c/CurseOfMisfortunes.java b/Mage.Sets/src/mage/cards/c/CurseOfMisfortunes.java index a47226e30e8..253a069fb3f 100644 --- a/Mage.Sets/src/mage/cards/c/CurseOfMisfortunes.java +++ b/Mage.Sets/src/mage/cards/c/CurseOfMisfortunes.java @@ -1,11 +1,10 @@ - package mage.cards.c; import mage.abilities.Ability; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; import mage.abilities.keyword.EnchantAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -17,7 +16,6 @@ import mage.filter.FilterCard; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.NamePredicate; import mage.game.Game; -import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPlayer; @@ -27,16 +25,14 @@ import mage.target.targetpointer.FixedTarget; import java.util.UUID; /** - * * @author BetaSteward */ public final class CurseOfMisfortunes extends CardImpl { public CurseOfMisfortunes(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{4}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{B}"); this.subtype.add(SubType.AURA, SubType.CURSE); - // Enchant player TargetPlayer auraTarget = new TargetPlayer(); this.getSpellAbility().addTarget(auraTarget); @@ -44,7 +40,7 @@ public final class CurseOfMisfortunes extends CardImpl { this.addAbility(new EnchantAbility(auraTarget)); // At the beginning of your upkeep, you may search your library for a Curse card that doesn't have the same name as a Curse attached to enchanted player, put it onto the battlefield attached to that player, then shuffle your library. - this.addAbility(new OnEventTriggeredAbility(GameEvent.EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", new CurseOfMisfortunesEffect(), true)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new CurseOfMisfortunesEffect(), true)); } private CurseOfMisfortunes(final CurseOfMisfortunes card) { @@ -79,7 +75,7 @@ class CurseOfMisfortunesEffect extends OneShotEffect { FilterCard filter = new FilterCard("Curse card that doesn't have the same name as a Curse attached to enchanted player"); filter.add(SubType.CURSE.getPredicate()); // get the names of attached Curses - for (UUID attachmentId: targetPlayer.getAttachments()) { + for (UUID attachmentId : targetPlayer.getAttachments()) { Permanent attachment = game.getPermanent(attachmentId); if (attachment != null && attachment.hasSubtype(SubType.CURSE, game)) { filter.add(Predicates.not(new NamePredicate(attachment.getName()))); diff --git a/Mage.Sets/src/mage/cards/c/CurseOfTheCabal.java b/Mage.Sets/src/mage/cards/c/CurseOfTheCabal.java index 179dd87f298..cb5eefc9879 100644 --- a/Mage.Sets/src/mage/cards/c/CurseOfTheCabal.java +++ b/Mage.Sets/src/mage/cards/c/CurseOfTheCabal.java @@ -1,16 +1,15 @@ package mage.cards.c; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.SuspendedCondition; import mage.abilities.costs.Cost; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.SuspendAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -44,8 +43,9 @@ public final class CurseOfTheCabal extends CardImpl { this.addAbility(new SuspendAbility(2, new ManaCostsImpl<>("{2}{B}{B}"), this)); // At the beginning of each player's upkeep, if Curse of the Cabal is suspended, that player may sacrifice a permanent. If they do, put two time counters on Curse of the Cabal. - this.addAbility(new CurseOfTheCabalInterveningIfTriggeredAbility()); - + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + Zone.EXILED, TargetController.EACH_PLAYER, new CurseOfTheCabalTriggeredAbilityConditionalDelay(), false + ).withInterveningIf(SuspendedCondition.instance)); } private CurseOfTheCabal(final CurseOfTheCabal card) { @@ -62,7 +62,7 @@ class CurseOfTheCabalSacrificeEffect extends OneShotEffect { CurseOfTheCabalSacrificeEffect() { super(Outcome.Sacrifice); - this.staticText = "Target player sacrifices half the permanents they control, rounded down."; + this.staticText = "Target player sacrifices half the permanents they control of their choice, rounded down."; } private CurseOfTheCabalSacrificeEffect(final CurseOfTheCabalSacrificeEffect effect) { @@ -100,36 +100,11 @@ class CurseOfTheCabalSacrificeEffect extends OneShotEffect { } } -class CurseOfTheCabalInterveningIfTriggeredAbility extends ConditionalInterveningIfTriggeredAbility { - - public CurseOfTheCabalInterveningIfTriggeredAbility() { - super(new BeginningOfUpkeepTriggeredAbility( - Zone.EXILED, TargetController.ANY, new CurseOfTheCabalTriggeredAbilityConditionalDelay(), - false - ), - SuspendedCondition.instance, - "At the beginning of each player's upkeep, if {this} is suspended, " - + "that player may sacrifice a permanent. If the player does, " - + "put two time counters on {this}." - ); - // controller has to sac a permanent - // counters aren't placed - } - - private CurseOfTheCabalInterveningIfTriggeredAbility(final CurseOfTheCabalInterveningIfTriggeredAbility effect) { - super(effect); - } - - @Override - public CurseOfTheCabalInterveningIfTriggeredAbility copy() { - return new CurseOfTheCabalInterveningIfTriggeredAbility(this); - } -} - class CurseOfTheCabalTriggeredAbilityConditionalDelay extends AddCountersSourceEffect { public CurseOfTheCabalTriggeredAbilityConditionalDelay() { super(CounterType.TIME.createInstance(), StaticValue.get(2), false, true); + staticText = "that player may sacrifice a permanent of their choice. If the player does, put two time counters on this card"; } @Override diff --git a/Mage.Sets/src/mage/cards/c/CurseOfTheWerefox.java b/Mage.Sets/src/mage/cards/c/CurseOfTheWerefox.java index a9e2e82d4ed..4a6deeea660 100644 --- a/Mage.Sets/src/mage/cards/c/CurseOfTheWerefox.java +++ b/Mage.Sets/src/mage/cards/c/CurseOfTheWerefox.java @@ -3,8 +3,6 @@ package mage.cards.c; import mage.abilities.Ability; import mage.abilities.common.delayed.ReflexiveTriggeredAbility; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.CreateRoleAttachedTargetEffect; -import mage.abilities.effects.common.FightTargetsEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -13,11 +11,9 @@ import mage.constants.RoleType; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; -import mage.target.common.TargetOpponentsCreaturePermanent; import mage.target.targetpointer.FixedTarget; -import mage.util.GameLog; import java.util.UUID; @@ -64,24 +60,15 @@ class CurseOfTheWerefoxEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent target = game.getPermanent(source.getFirstTarget()); - if (target == null) { - return false; - } - - boolean didCreate = - new CreateRoleAttachedTargetEffect(RoleType.MONSTER) - .setTargetPointer(new FixedTarget(target, game)) - .apply(game, source); - if (!didCreate) { + if (target == null || RoleType.MONSTER.createToken(target, game, source).getLastAddedTokenIds().isEmpty()) { return false; } ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility( - new CurseOfTheWerefoxFightEffect(), false, - "that creature fights up to one target creature you don't control" + new CurseOfTheWerefoxFightEffect().setTargetPointer(new FixedTarget(target.getId(), game)), + false, "that creature fights up to one target creature you don't control" ); - ability.getEffects().setTargetPointer(new FixedTarget(target.getId(), game)); - ability.addTarget(new TargetCreaturePermanent(0, 1, StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL, false)); + ability.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); game.fireReflexiveTriggeredAbility(ability, source); return true; } diff --git a/Mage.Sets/src/mage/cards/c/CurtainOfLight.java b/Mage.Sets/src/mage/cards/c/CurtainOfLight.java index 16632d142da..934755dad62 100644 --- a/Mage.Sets/src/mage/cards/c/CurtainOfLight.java +++ b/Mage.Sets/src/mage/cards/c/CurtainOfLight.java @@ -12,6 +12,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.AttackingPredicate; import mage.filter.predicate.permanent.BlockedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -39,7 +40,7 @@ public final class CurtainOfLight extends CardImpl { // Target unblocked attacking creature becomes blocked. this.getSpellAbility().addEffect(new BecomeBlockedTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("
")); diff --git a/Mage.Sets/src/mage/cards/c/CurtainsCall.java b/Mage.Sets/src/mage/cards/c/CurtainsCall.java index 8b9c310c7b4..92beebc118e 100644 --- a/Mage.Sets/src/mage/cards/c/CurtainsCall.java +++ b/Mage.Sets/src/mage/cards/c/CurtainsCall.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.UndauntedAbility; import mage.cards.CardImpl; @@ -9,8 +7,9 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class CurtainsCall extends CardImpl { @@ -20,6 +19,7 @@ public final class CurtainsCall extends CardImpl { // Undaunted this.addAbility(new UndauntedAbility()); + // Destroy two target creatures. this.getSpellAbility().addEffect(new DestroyTargetEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent(2)); diff --git a/Mage.Sets/src/mage/cards/c/Cyclone.java b/Mage.Sets/src/mage/cards/c/Cyclone.java index 7f21d7eea62..09d716b667d 100644 --- a/Mage.Sets/src/mage/cards/c/Cyclone.java +++ b/Mage.Sets/src/mage/cards/c/Cyclone.java @@ -1,14 +1,13 @@ package mage.cards.c; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.costs.Cost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DamageEverythingEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -18,6 +17,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import java.util.UUID; + /** @@ -48,7 +49,7 @@ class CycloneEffect extends OneShotEffect { CycloneEffect() { super(Outcome.Damage); - this.staticText = "Pay Green Mana for each counter to damage everything or sacrifice Cyclone."; + this.staticText = ", then sacrifice {this} unless you pay {G} for each wind counter on it. If you pay, {this} deals damage equal to the number of wind counters on it to each creature and each player"; } private CycloneEffect(final CycloneEffect effect) { diff --git a/Mage.Sets/src/mage/cards/c/CyclopeanTomb.java b/Mage.Sets/src/mage/cards/c/CyclopeanTomb.java index 16a99bafa6f..2de29c123d3 100644 --- a/Mage.Sets/src/mage/cards/c/CyclopeanTomb.java +++ b/Mage.Sets/src/mage/cards/c/CyclopeanTomb.java @@ -8,7 +8,7 @@ import mage.abilities.common.delayed.AtTheBeginOfYourNextUpkeepDelayedTriggeredA import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.BecomesBasicLandTargetEffect; @@ -37,7 +37,7 @@ import java.util.*; */ public final class CyclopeanTomb extends CardImpl { - private static final FilterPermanent filter = new FilterLandPermanent(); + private static final FilterPermanent filter = new FilterLandPermanent("non-Swamp land"); static { filter.add(Predicates.not(SubType.SWAMP.getPredicate())); @@ -47,7 +47,10 @@ public final class CyclopeanTomb extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); // {2}, {tap}: Put a mire counter on target non-Swamp land. That land is a Swamp for as long as it has a mire counter on it. Activate this ability only during your upkeep. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.MIRE.createInstance()), new GenericManaCost(2), new IsStepCondition(PhaseStep.UPKEEP), "{2}, {T}: Put a mire counter on target non-Swamp land. That land is a Swamp for as long as it has a mire counter on it. Activate only during your upkeep."); + Ability ability = new ActivateIfConditionActivatedAbility( + new AddCountersTargetEffect(CounterType.MIRE.createInstance()), + new GenericManaCost(2), IsStepCondition.getMyUpkeep() + ); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetPermanent(filter)); ability.addEffect(new BecomeSwampEffect()); diff --git a/Mage.Sets/src/mage/cards/c/CyclopsGladiator.java b/Mage.Sets/src/mage/cards/c/CyclopsGladiator.java index d9ffd2ac569..c2c3f3e1b74 100644 --- a/Mage.Sets/src/mage/cards/c/CyclopsGladiator.java +++ b/Mage.Sets/src/mage/cards/c/CyclopsGladiator.java @@ -2,7 +2,6 @@ package mage.cards.c; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; @@ -10,14 +9,15 @@ 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.constants.SubType; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; +import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster; + +import java.util.UUID; /** * @@ -26,7 +26,7 @@ import mage.target.common.TargetCreaturePermanent; public final class CyclopsGladiator extends CardImpl { public CyclopsGladiator(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{R}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{R}{R}"); this.subtype.add(SubType.CYCLOPS); this.subtype.add(SubType.WARRIOR); @@ -36,6 +36,8 @@ public final class CyclopsGladiator extends CardImpl { // Whenever Cyclops Gladiator attacks, you may have it deal damage equal to its power to target creature defending player controls. // If you do, that creature deals damage equal to its power to Cyclops Gladiator. Ability ability = new AttacksTriggeredAbility(new CyclopsGladiatorEffect(), true); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_CREATURE)); + ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster()); this.addAbility(ability); } @@ -63,23 +65,12 @@ class CyclopsGladiatorEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - UUID defenderId = game.getCombat().getDefenderId(source.getSourceId()); - if (defenderId != null) { - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); - filter.add(new ControllerIdPredicate(defenderId)); - TargetCreaturePermanent target = new TargetCreaturePermanent(filter); - Player player = game.getPlayer(source.getControllerId()); - if (target.canChoose(source.getControllerId(), source, game)) { - if (player != null && player.chooseTarget(Outcome.Detriment, target, source, game)) { - Permanent permanent = game.getPermanent(target.getFirstTarget()); - Permanent cyclops = game.getPermanent(source.getSourceId()); - if (permanent != null && cyclops != null) { - permanent.damage(cyclops.getPower().getValue(), cyclops.getId(), source, game, false, true); - cyclops.damage(permanent.getPower().getValue(), permanent.getId(), source, game, false, true); - return true; - } - } - } + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + Permanent cyclops = game.getPermanent(source.getSourceId()); + if (permanent != null && cyclops != null) { + permanent.damage(cyclops.getPower().getValue(), cyclops.getId(), source, game, false, true); + cyclops.damage(permanent.getPower().getValue(), permanent.getId(), source, game, false, true); + return true; } return false; } diff --git a/Mage.Sets/src/mage/cards/c/CytoplastManipulator.java b/Mage.Sets/src/mage/cards/c/CytoplastManipulator.java index 2c91d858969..2a1ad209c57 100644 --- a/Mage.Sets/src/mage/cards/c/CytoplastManipulator.java +++ b/Mage.Sets/src/mage/cards/c/CytoplastManipulator.java @@ -18,8 +18,11 @@ import mage.constants.SubType; import mage.constants.Duration; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_CREATURE_P1P1; + /** * * @author JotaPeRL @@ -44,7 +47,7 @@ public final class CytoplastManipulator extends CardImpl { "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(effect, new ManaCostsImpl<>("{U}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_P1P1)); + ability.addTarget(new TargetPermanent(FILTER_CREATURE_P1P1)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/Cytoshape.java b/Mage.Sets/src/mage/cards/c/Cytoshape.java index bbbed0cfc4d..fb6807cd653 100644 --- a/Mage.Sets/src/mage/cards/c/Cytoshape.java +++ b/Mage.Sets/src/mage/cards/c/Cytoshape.java @@ -1,4 +1,3 @@ - package mage.cards.c; import mage.abilities.Ability; @@ -14,26 +13,22 @@ import mage.filter.predicate.Predicates; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.Target; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import mage.util.functions.EmptyCopyApplier; import java.util.UUID; /** - * * @author jeffwadsworth */ public final class Cytoshape extends CardImpl { - public Cytoshape(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}{U}"); // Choose a nonlegendary creature on the battlefield. Target creature becomes a copy of that creature until end of turn. this.getSpellAbility().addEffect(new CytoshapeEffect()); - - FilterCreaturePermanent filter = new FilterCreaturePermanent("target creature that will become a copy"); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent().withChooseHint("to become a copy")); } private Cytoshape(final Cytoshape card) { @@ -53,9 +48,11 @@ class CytoshapeEffect extends OneShotEffect { static { filter.add(Predicates.not(SuperType.LEGENDARY.getPredicate())); } + CytoshapeEffect() { super(Outcome.Copy); - this.staticText = "Choose a nonlegendary creature on the battlefield. Target creature becomes a copy of that creature until end of turn."; + this.staticText = "Choose a nonlegendary creature on the battlefield. " + + "Target creature becomes a copy of that creature until end of turn."; } private CytoshapeEffect(final CytoshapeEffect effect) { @@ -69,7 +66,7 @@ class CytoshapeEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability ability) { - Target target = new TargetCreaturePermanent(1, 1, filter, true); + Target target = new TargetPermanent(1, 1, filter, true); target.choose(Outcome.Copy, ability.getControllerId(), ability, game); Permanent copyFrom = game.getPermanent(target.getFirstTarget()); if (copyFrom != null) { diff --git a/Mage.Sets/src/mage/cards/c/CytospawnShambler.java b/Mage.Sets/src/mage/cards/c/CytospawnShambler.java index 93a3487f1b2..7f885b399f4 100644 --- a/Mage.Sets/src/mage/cards/c/CytospawnShambler.java +++ b/Mage.Sets/src/mage/cards/c/CytospawnShambler.java @@ -16,8 +16,11 @@ import mage.constants.SubType; import mage.constants.Duration; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_CREATURE_P1P1; + /** * * @author JotaPeRL @@ -36,7 +39,7 @@ public final class CytospawnShambler extends CardImpl { // {G}: Target creature with a +1/+1 counter on it gains trample until end of turn. Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{G}")); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_P1P1)); + ability.addTarget(new TargetPermanent(FILTER_CREATURE_P1P1)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DakmorLancer.java b/Mage.Sets/src/mage/cards/d/DakmorLancer.java index 0014e1a5257..07a2c8fb163 100644 --- a/Mage.Sets/src/mage/cards/d/DakmorLancer.java +++ b/Mage.Sets/src/mage/cards/d/DakmorLancer.java @@ -10,8 +10,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author LoneFox @@ -28,7 +31,7 @@ public final class DakmorLancer extends CardImpl { // When Dakmor Lancer enters the battlefield, destroy target nonblack creature. Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + ability.addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DanceOfMany.java b/Mage.Sets/src/mage/cards/d/DanceOfMany.java index 1b266fb784e..d85eb04151c 100644 --- a/Mage.Sets/src/mage/cards/d/DanceOfMany.java +++ b/Mage.Sets/src/mage/cards/d/DanceOfMany.java @@ -23,6 +23,7 @@ import mage.filter.predicate.permanent.TokenPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; @@ -45,7 +46,7 @@ public final class DanceOfMany extends CardImpl { // When Dance of Many enters the battlefield, create a token that's a copy of target nontoken creature. Ability ability = new EntersBattlefieldTriggeredAbility(new DanceOfManyCreateTokenCopyEffect(), false); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // When Dance of Many leaves the battlefield, exile the token. diff --git a/Mage.Sets/src/mage/cards/d/DarajaGriffin.java b/Mage.Sets/src/mage/cards/d/DarajaGriffin.java index 06f046cd475..1448c10141c 100644 --- a/Mage.Sets/src/mage/cards/d/DarajaGriffin.java +++ b/Mage.Sets/src/mage/cards/d/DarajaGriffin.java @@ -16,6 +16,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -41,7 +42,7 @@ public final class DarajaGriffin extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Sacrifice Daraja Griffin: Destroy target black creature. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DarigaazReincarnated.java b/Mage.Sets/src/mage/cards/d/DarigaazReincarnated.java index 5a05b6caaee..45f2e5e18aa 100644 --- a/Mage.Sets/src/mage/cards/d/DarigaazReincarnated.java +++ b/Mage.Sets/src/mage/cards/d/DarigaazReincarnated.java @@ -2,16 +2,15 @@ package mage.cards.d; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -52,7 +51,9 @@ public final class DarigaazReincarnated extends CardImpl { this.addAbility(new SimpleStaticAbility(new DarigaazReincarnatedDiesEffect())); // At the beginning of your upkeep, if Darigaaz is exiled with an egg counter on it, remove an egg counter from it. Then if Darigaaz has no egg counters on it, return it to the battlefield. - this.addAbility(new DarigaazReincarnatedInterveningIfTriggeredAbility()); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + Zone.EXILED, TargetController.YOU, new DarigaazReincarnatedReturnEffect(), false + ).withInterveningIf(DarigaazReincarnatedCondition.instance)); } private DarigaazReincarnated(final DarigaazReincarnated card) { @@ -108,30 +109,11 @@ class DarigaazReincarnatedDiesEffect extends ReplacementEffectImpl { } -class DarigaazReincarnatedInterveningIfTriggeredAbility extends ConditionalInterveningIfTriggeredAbility { - - public DarigaazReincarnatedInterveningIfTriggeredAbility() { - super(new BeginningOfUpkeepTriggeredAbility(Zone.EXILED, TargetController.YOU, new DarigaazReincarnatedReturnEffect(), false), - DarigaazReincarnatedCondition.instance, - "At the beginning of your upkeep, if {this} is exiled with an egg counter on it, " - + "remove an egg counter from it. Then if {this} has no egg counters on it, return it to the battlefield"); - } - - private DarigaazReincarnatedInterveningIfTriggeredAbility(final DarigaazReincarnatedInterveningIfTriggeredAbility effect) { - super(effect); - } - - @Override - public DarigaazReincarnatedInterveningIfTriggeredAbility copy() { - return new DarigaazReincarnatedInterveningIfTriggeredAbility(this); - } -} - class DarigaazReincarnatedReturnEffect extends OneShotEffect { DarigaazReincarnatedReturnEffect() { super(Outcome.Benefit); - this.staticText = ""; + this.staticText = "remove an egg counter from it. Then if this card has no egg counters on it, return it to the battlefield"; } private DarigaazReincarnatedReturnEffect(final DarigaazReincarnatedReturnEffect effect) { @@ -165,10 +147,13 @@ enum DarigaazReincarnatedCondition implements Condition { @Override public boolean apply(Game game, Ability source) { Card card = game.getCard(source.getSourceId()); - if (card != null) { - return game.getState().getZone(card.getId()) == Zone.EXILED - && card.getCounters(game).getCount(CounterType.EGG) > 0; - } - return false; + return card != null + && game.getState().getZone(card.getId()) == Zone.EXILED + && card.getCounters(game).getCount(CounterType.EGG) > 0; + } + + @Override + public String toString() { + return "this card is exiled with an egg counter on it"; } } diff --git a/Mage.Sets/src/mage/cards/d/DarkBanishing.java b/Mage.Sets/src/mage/cards/d/DarkBanishing.java index b162617a5d8..4d75ffcd23d 100644 --- a/Mage.Sets/src/mage/cards/d/DarkBanishing.java +++ b/Mage.Sets/src/mage/cards/d/DarkBanishing.java @@ -6,8 +6,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author Loki @@ -18,7 +21,7 @@ public final class DarkBanishing extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{B}"); this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); } private DarkBanishing(final DarkBanishing card) { diff --git a/Mage.Sets/src/mage/cards/d/DarkBetrayal.java b/Mage.Sets/src/mage/cards/d/DarkBetrayal.java index 1cc12dcc10a..91ecc4dab9b 100644 --- a/Mage.Sets/src/mage/cards/d/DarkBetrayal.java +++ b/Mage.Sets/src/mage/cards/d/DarkBetrayal.java @@ -10,6 +10,7 @@ import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -29,7 +30,7 @@ public final class DarkBetrayal extends CardImpl { // Destroy target black creature. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - Target target = new TargetCreaturePermanent(filter); + Target target = new TargetPermanent(filter); this.getSpellAbility().addTarget(target); } diff --git a/Mage.Sets/src/mage/cards/d/DarkHatchling.java b/Mage.Sets/src/mage/cards/d/DarkHatchling.java index 3e7398fb753..471b262b837 100644 --- a/Mage.Sets/src/mage/cards/d/DarkHatchling.java +++ b/Mage.Sets/src/mage/cards/d/DarkHatchling.java @@ -11,8 +11,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author LevelX2 @@ -31,7 +34,7 @@ public final class DarkHatchling extends CardImpl { // When Dark Hatchling enters the battlefield, destroy target nonblack creature. It can't be regenerated. Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(true)); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + ability.addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DarkOffering.java b/Mage.Sets/src/mage/cards/d/DarkOffering.java index dd094ee0d4d..a8161e9afb7 100644 --- a/Mage.Sets/src/mage/cards/d/DarkOffering.java +++ b/Mage.Sets/src/mage/cards/d/DarkOffering.java @@ -7,8 +7,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author fireshoes @@ -21,7 +24,7 @@ public final class DarkOffering extends CardImpl { // Destroy target nonblack creature. You gain 3 life. this.getSpellAbility().addEffect(new DestroyTargetEffect()); this.getSpellAbility().addEffect(new GainLifeEffect(3)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); } private DarkOffering(final DarkOffering card) { diff --git a/Mage.Sets/src/mage/cards/d/DarkWithering.java b/Mage.Sets/src/mage/cards/d/DarkWithering.java index 9d2cdb6eae6..e3a6f87ff33 100644 --- a/Mage.Sets/src/mage/cards/d/DarkWithering.java +++ b/Mage.Sets/src/mage/cards/d/DarkWithering.java @@ -8,8 +8,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author magenoxx_at_gmail.com @@ -20,7 +23,7 @@ public final class DarkWithering extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{4}{B}{B}"); // Destroy target nonblack creature. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); // Madness {B} diff --git a/Mage.Sets/src/mage/cards/d/DaruEncampment.java b/Mage.Sets/src/mage/cards/d/DaruEncampment.java index b5d8a77173c..d55e0b8801e 100644 --- a/Mage.Sets/src/mage/cards/d/DaruEncampment.java +++ b/Mage.Sets/src/mage/cards/d/DaruEncampment.java @@ -14,6 +14,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -37,7 +38,7 @@ public final class DaruEncampment extends CardImpl { new BoostTargetEffect(1, 1, Duration.EndOfTurn), new ManaCostsImpl<>("{W}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DaughterOfAutumn.java b/Mage.Sets/src/mage/cards/d/DaughterOfAutumn.java index 732032ad82f..635fe9c3888 100644 --- a/Mage.Sets/src/mage/cards/d/DaughterOfAutumn.java +++ b/Mage.Sets/src/mage/cards/d/DaughterOfAutumn.java @@ -45,7 +45,7 @@ public final class DaughterOfAutumn extends CardImpl { // {W}: The next 1 damage that would be dealt to target white creature this turn is dealt to Daughter of Autumn instead. Ability ability = new SimpleActivatedAbility(new DaughterOfAutumnPreventDamageTargetEffect(Duration.EndOfTurn, 1), new ManaCostsImpl<>("{W}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DauthiCutthroat.java b/Mage.Sets/src/mage/cards/d/DauthiCutthroat.java index 59f10702451..3eacea98f57 100644 --- a/Mage.Sets/src/mage/cards/d/DauthiCutthroat.java +++ b/Mage.Sets/src/mage/cards/d/DauthiCutthroat.java @@ -16,6 +16,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -42,7 +43,7 @@ public final class DauthiCutthroat extends CardImpl { // {1}{B}, {tap}: Destroy target creature with shadow. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new ManaCostsImpl<>("{1}{B}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DauthiJackal.java b/Mage.Sets/src/mage/cards/d/DauthiJackal.java index 34039f12d65..d1e3a29c6fe 100644 --- a/Mage.Sets/src/mage/cards/d/DauthiJackal.java +++ b/Mage.Sets/src/mage/cards/d/DauthiJackal.java @@ -15,6 +15,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterBlockingCreature; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -36,7 +37,7 @@ public final class DauthiJackal extends CardImpl { // {B}{B}, Sacrifice Dauthi Jackal: Destroy target blocking creature. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new ManaCostsImpl<>("{B}{B}")); ability.addCost(new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(new FilterBlockingCreature())); + ability.addTarget(new TargetPermanent(new FilterBlockingCreature())); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DawnhartMentor.java b/Mage.Sets/src/mage/cards/d/DawnhartMentor.java index 6f3341802c6..231300568d9 100644 --- a/Mage.Sets/src/mage/cards/d/DawnhartMentor.java +++ b/Mage.Sets/src/mage/cards/d/DawnhartMentor.java @@ -13,7 +13,10 @@ import mage.abilities.hint.common.CovenHint; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.AbilityWord; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; import mage.game.permanent.token.HumanToken; import mage.target.common.TargetControlledCreaturePermanent; @@ -37,8 +40,8 @@ public final class DawnhartMentor extends CardImpl { // Coven — {5}{G}: Target creature you control gets +3/+3 and gains trample until end of turn. Activate only if you control three or more creatures with different powers. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new BoostTargetEffect(3, 3) - .setText("target creature you control gets +3/+3"), + new BoostTargetEffect(3, 3) + .setText("target creature you control gets +3/+3"), new ManaCostsImpl<>("{5}{G}"), CovenCondition.instance ); ability.addEffect(new GainAbilityTargetEffect( diff --git a/Mage.Sets/src/mage/cards/d/DaybreakRanger.java b/Mage.Sets/src/mage/cards/d/DaybreakRanger.java index ef18fe46a36..cc653c12f4d 100644 --- a/Mage.Sets/src/mage/cards/d/DaybreakRanger.java +++ b/Mage.Sets/src/mage/cards/d/DaybreakRanger.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -44,7 +45,7 @@ public final class DaybreakRanger extends CardImpl { // {tap}: Daybreak Ranger deals 2 damage to target creature with flying. Ability activatedAbility = new SimpleActivatedAbility(new DamageTargetEffect(2), new TapSourceCost()); - activatedAbility.addTarget(new TargetCreaturePermanent(filter)); + activatedAbility.addTarget(new TargetPermanent(filter)); this.addAbility(activatedAbility); // At the beginning of each upkeep, if no spells were cast last turn, transform Daybreak Ranger. this.addAbility(new TransformAbility()); diff --git a/Mage.Sets/src/mage/cards/d/DazzlingBeauty.java b/Mage.Sets/src/mage/cards/d/DazzlingBeauty.java index f039a87452f..f4308183362 100644 --- a/Mage.Sets/src/mage/cards/d/DazzlingBeauty.java +++ b/Mage.Sets/src/mage/cards/d/DazzlingBeauty.java @@ -13,6 +13,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.AttackingPredicate; import mage.filter.predicate.permanent.BlockedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -40,7 +41,7 @@ public final class DazzlingBeauty extends CardImpl { // Target unblocked attacking creature becomes blocked. this.getSpellAbility().addEffect(new BecomeBlockedTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // Draw a card at the beginning of the next turn's upkeep. this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextUpkeepDelayedTriggeredAbility( diff --git a/Mage.Sets/src/mage/cards/d/DeadGone.java b/Mage.Sets/src/mage/cards/d/DeadGone.java index eb3e1c7da47..6bbf1065378 100644 --- a/Mage.Sets/src/mage/cards/d/DeadGone.java +++ b/Mage.Sets/src/mage/cards/d/DeadGone.java @@ -7,10 +7,13 @@ import mage.cards.SplitCard; import mage.constants.CardType; import mage.constants.SpellAbilityType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author dustinconrad */ @@ -27,7 +30,7 @@ public final class DeadGone extends SplitCard { // Gone // Return target creature you don't control to its owner's hand. getRightHalfCard().getSpellAbility().addEffect(new ReturnToHandTargetEffect()); - getRightHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + getRightHalfCard().getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); } private DeadGone(final DeadGone card) { diff --git a/Mage.Sets/src/mage/cards/d/DeadRingers.java b/Mage.Sets/src/mage/cards/d/DeadRingers.java index 125edf0b560..ba6077eea68 100644 --- a/Mage.Sets/src/mage/cards/d/DeadRingers.java +++ b/Mage.Sets/src/mage/cards/d/DeadRingers.java @@ -1,19 +1,22 @@ package mage.cards.d; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.OneShotEffect; 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.game.permanent.Permanent; -import mage.target.Target; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; /** - * * @author LoneFox */ public final class DeadRingers extends CardImpl { @@ -23,7 +26,7 @@ public final class DeadRingers extends CardImpl { // Destroy two target nonblack creatures unless either one is a color the other isn't. They can't be regenerated. this.getSpellAbility().addEffect(new DeadRingersEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(2, 2, StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK, false)); + this.getSpellAbility().addTarget(new TargetPermanent(2, StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); } private DeadRingers(final DeadRingers card) { @@ -36,11 +39,11 @@ public final class DeadRingers extends CardImpl { } } -class DeadRingersEffect extends DestroyTargetEffect { +class DeadRingersEffect extends OneShotEffect { DeadRingersEffect() { - super(true); - staticText = "Destroy two target nonblack creatures unless either one is a color the other isn't. They can't be regenerated."; + super(Outcome.DestroyPermanent); + staticText = "destroy two target nonblack creatures unless either one is a color the other isn't. They can't be regenerated."; } private DeadRingersEffect(final DeadRingersEffect effect) { @@ -54,17 +57,23 @@ class DeadRingersEffect extends DestroyTargetEffect { @Override public boolean apply(Game game, Ability source) { - Target target = source.getTargets().get(0); - if (target != null - && target.getTargets().size() > 1) { - Permanent first = game.getPermanentOrLKIBattlefield(target.getTargets().get(0)); - Permanent second = game.getPermanentOrLKIBattlefield(target.getTargets().get(1)); - if (first != null - && second != null - && first.getColor(game).equals(second.getColor(game))) { - return super.apply(game, source); - } + List permanents = this + .getTargetPointer() + .getTargets(game, source) + .stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + if (permanents.size() < 2) { + return false; } - return false; + Permanent first = permanents.get(0); + Permanent second = permanents.get(1); + if (!first.getColor(game).equals(second.getColor(game))) { + return false; + } + first.destroy(source, game, true); + second.destroy(source, game, true); + return true; } } diff --git a/Mage.Sets/src/mage/cards/d/DeadWeight.java b/Mage.Sets/src/mage/cards/d/DeadWeight.java index 0f7e6378f6f..76d576642b5 100644 --- a/Mage.Sets/src/mage/cards/d/DeadWeight.java +++ b/Mage.Sets/src/mage/cards/d/DeadWeight.java @@ -1,7 +1,5 @@ - package mage.cards.d; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.AttachEffect; @@ -10,30 +8,30 @@ import mage.abilities.keyword.EnchantAbility; 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.SubType; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author Alvin */ public final class DeadWeight extends CardImpl { public DeadWeight(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{B}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{B}"); this.subtype.add(SubType.AURA); - // Enchant creature TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); Ability ability = new EnchantAbility(auraTarget); this.addAbility(ability); + // Enchanted creature gets -2/-2. this.addAbility(new SimpleStaticAbility(new BoostEnchantedEffect(-2, -2, Duration.WhileOnBattlefield))); } diff --git a/Mage.Sets/src/mage/cards/d/Deadshot.java b/Mage.Sets/src/mage/cards/d/Deadshot.java index f58e7d91df0..fa17bc469fa 100644 --- a/Mage.Sets/src/mage/cards/d/Deadshot.java +++ b/Mage.Sets/src/mage/cards/d/Deadshot.java @@ -1,42 +1,31 @@ - package mage.cards.d; -import java.util.UUID; +import mage.abilities.effects.common.DamageWithPowerFromOneToAnotherTargetEffect; import mage.abilities.effects.common.TapTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.other.AnotherTargetPredicate; +import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; -import mage.abilities.effects.common.DamageWithPowerFromOneToAnotherTargetEffect; + +import java.util.UUID; /** - * * @author fireshoes, xenohedron */ public final class Deadshot extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); - - static { - filter.add(new AnotherTargetPredicate(2)); - } - public Deadshot(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}"); // Tap target creature. this.getSpellAbility().addEffect(new TapTargetEffect()); - TargetCreaturePermanent target = new TargetCreaturePermanent(); - target.setTargetTag(1); - this.getSpellAbility().addTarget(target); + this.getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(1)); // It deals damage equal to its power to another target creature. this.getSpellAbility().addEffect(new DamageWithPowerFromOneToAnotherTargetEffect("It")); - target = new TargetCreaturePermanent(filter); - target.setTargetTag(2); - this.getSpellAbility().addTarget(target); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2).setTargetTag(2)); } private Deadshot(final Deadshot card) { @@ -48,4 +37,3 @@ public final class Deadshot extends CardImpl { return new Deadshot(this); } } - diff --git a/Mage.Sets/src/mage/cards/d/DeadshotMinotaur.java b/Mage.Sets/src/mage/cards/d/DeadshotMinotaur.java index 54a594fe08f..8ebaa2c9e90 100644 --- a/Mage.Sets/src/mage/cards/d/DeadshotMinotaur.java +++ b/Mage.Sets/src/mage/cards/d/DeadshotMinotaur.java @@ -15,6 +15,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class DeadshotMinotaur extends CardImpl { // When Deadshot Minotaur enters the battlefield, it deals 3 damage to target creature with flying. Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(3, "it"), false); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // Cycling {RG} this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{R/G}"))); diff --git a/Mage.Sets/src/mage/cards/d/DealBroker.java b/Mage.Sets/src/mage/cards/d/DealBroker.java index 9bc0502b888..a3c28f28cfa 100644 --- a/Mage.Sets/src/mage/cards/d/DealBroker.java +++ b/Mage.Sets/src/mage/cards/d/DealBroker.java @@ -1,6 +1,5 @@ package mage.cards.d; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; @@ -13,6 +12,8 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; +import java.util.UUID; + /** * * @author L_J @@ -28,7 +29,7 @@ public final class DealBroker extends CardImpl { // TODO: Draft specific abilities not implemented // Draft Deal Broker face up. - this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Draft Deal Broker face up."))); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Draft {this} face up."))); // Immediately after the draft, you may reveal a card in your card pool. Each other player may offer you one card in their card pool in exchange. You may accept any one offer. this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Immediately after the draft, you may reveal a card in your card pool. " diff --git a/Mage.Sets/src/mage/cards/d/DeathBomb.java b/Mage.Sets/src/mage/cards/d/DeathBomb.java index 1eb2242cc76..fa69db16a6b 100644 --- a/Mage.Sets/src/mage/cards/d/DeathBomb.java +++ b/Mage.Sets/src/mage/cards/d/DeathBomb.java @@ -8,9 +8,12 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author LoneFox @@ -25,7 +28,7 @@ public final class DeathBomb extends CardImpl { // Destroy target nonblack creature. It can't be regenerated. Its controller loses 2 life. this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); this.getSpellAbility().addEffect(new LoseLifeTargetControllerEffect(2)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK).withChooseHint("to destroy")); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK).withChooseHint("to destroy")); } private DeathBomb(final DeathBomb card) { diff --git a/Mage.Sets/src/mage/cards/d/DeathRattle.java b/Mage.Sets/src/mage/cards/d/DeathRattle.java index a3017aa83b8..9f91487cbae 100644 --- a/Mage.Sets/src/mage/cards/d/DeathRattle.java +++ b/Mage.Sets/src/mage/cards/d/DeathRattle.java @@ -11,6 +11,7 @@ import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -33,7 +34,7 @@ public final class DeathRattle extends CardImpl { // Destroy target nongreen creature. It can't be regenerated. this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } diff --git a/Mage.Sets/src/mage/cards/d/DeathSpark.java b/Mage.Sets/src/mage/cards/d/DeathSpark.java index 6975eb8aca6..a0a2ea34509 100644 --- a/Mage.Sets/src/mage/cards/d/DeathSpark.java +++ b/Mage.Sets/src/mage/cards/d/DeathSpark.java @@ -34,7 +34,7 @@ public final class DeathSpark extends CardImpl { // At the beginning of your upkeep, if Death Spark is in your graveyard with a creature card directly above it, you may pay {1}. If you do, return Death Spark to your hand. this.addAbility(new BeginningOfUpkeepTriggeredAbility( Zone.GRAVEYARD, TargetController.YOU, - new DoIfCostPaid(new ReturnSourceFromGraveyardToHandEffect(), new GenericManaCost(1)), false + new DoIfCostPaid(new ReturnSourceFromGraveyardToHandEffect().setText("return this card to your hand"), new GenericManaCost(1)), false ).withInterveningIf(DeathSparkCondition.instance)); } @@ -71,6 +71,6 @@ enum DeathSparkCondition implements Condition { @Override public String toString() { - return "{this} is in your graveyard with a creature card directly above it"; + return "this card is in your graveyard with a creature card directly above it"; } } diff --git a/Mage.Sets/src/mage/cards/d/DeathStroke.java b/Mage.Sets/src/mage/cards/d/DeathStroke.java index 53a57c1b803..7b1de0240e5 100644 --- a/Mage.Sets/src/mage/cards/d/DeathStroke.java +++ b/Mage.Sets/src/mage/cards/d/DeathStroke.java @@ -8,6 +8,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -26,7 +27,7 @@ public final class DeathStroke extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{B}{B}"); // Destroy target tapped creature. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); } diff --git a/Mage.Sets/src/mage/cards/d/Deathmark.java b/Mage.Sets/src/mage/cards/d/Deathmark.java index 1423365d92a..bb046fd03ee 100644 --- a/Mage.Sets/src/mage/cards/d/Deathmark.java +++ b/Mage.Sets/src/mage/cards/d/Deathmark.java @@ -11,6 +11,7 @@ import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -30,7 +31,7 @@ public final class Deathmark extends CardImpl { public Deathmark(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{B}"); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); } diff --git a/Mage.Sets/src/mage/cards/d/DeathmarkPrelate.java b/Mage.Sets/src/mage/cards/d/DeathmarkPrelate.java index 794f8afcd02..134aece3c74 100644 --- a/Mage.Sets/src/mage/cards/d/DeathmarkPrelate.java +++ b/Mage.Sets/src/mage/cards/d/DeathmarkPrelate.java @@ -17,6 +17,7 @@ import mage.constants.Zone; import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; @@ -46,7 +47,7 @@ public final class DeathmarkPrelate extends CardImpl { Ability ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(true), new ManaCostsImpl<>("{2}{B}")); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeTargetCost(filter1)); - ability.addTarget(new TargetCreaturePermanent(filter2)); + ability.addTarget(new TargetPermanent(filter2)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DeathsPresence.java b/Mage.Sets/src/mage/cards/d/DeathsPresence.java index 8ccfce29cac..bba8dbe3e9b 100644 --- a/Mage.Sets/src/mage/cards/d/DeathsPresence.java +++ b/Mage.Sets/src/mage/cards/d/DeathsPresence.java @@ -1,20 +1,20 @@ package mage.cards.d; -import java.util.UUID; - -import mage.MageObject; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; import mage.counters.CounterType; +import mage.filter.StaticFilters; import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** * @@ -23,10 +23,14 @@ import mage.target.common.TargetControlledCreaturePermanent; public final class DeathsPresence extends CardImpl { public DeathsPresence(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{5}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{5}{G}"); // Whenever a creature you control dies, put X +1/+1 counters on target creature you control, where X is the power of the creature that died. - this.addAbility(new DeathsPresenceTriggeredAbility()); + Ability ability = new DiesCreatureTriggeredAbility( + new AddCountersTargetEffect(CounterType.P1P1.createInstance(), DeathsPresenceDiedPermanentPowerCount.instance), + false, StaticFilters.FILTER_CONTROLLED_CREATURE); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_CREATURE_CONTROLLED)); + this.addAbility(ability); } private DeathsPresence(final DeathsPresence card) { @@ -39,50 +43,30 @@ public final class DeathsPresence extends CardImpl { } } -class DeathsPresenceTriggeredAbility extends TriggeredAbilityImpl { - - public DeathsPresenceTriggeredAbility() { - super(Zone.BATTLEFIELD, null); - setLeavesTheBattlefieldTrigger(true); - } - - private DeathsPresenceTriggeredAbility(final DeathsPresenceTriggeredAbility ability) { - super(ability); - } +enum DeathsPresenceDiedPermanentPowerCount implements DynamicValue { + instance; @Override - public DeathsPresenceTriggeredAbility copy() { - return new DeathsPresenceTriggeredAbility(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 zoneChangeEvent = (ZoneChangeEvent) event; - if (zoneChangeEvent.isDiesEvent()) { - Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); - if (permanent != null && permanent.isControlledBy(this.getControllerId()) && permanent.isCreature(game)) { - this.getTargets().clear(); - this.addTarget(new TargetControlledCreaturePermanent()); - this.getEffects().clear(); - this.addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance(permanent.getPower().getValue()))); - return true; - } + public int calculate(Game game, Ability sourceAbility, Effect effect) { + Permanent targetPermanent = (Permanent) effect.getValue("creatureDied"); + if (targetPermanent != null) { + return targetPermanent.getPower().getValue(); } - return false; + return 0; } @Override - public String getRule() { - return "Whenever a creature you control dies, put X +1/+1 counters on target creature you control, where X is the power of the creature that died."; + public DeathsPresenceDiedPermanentPowerCount copy() { + return DeathsPresenceDiedPermanentPowerCount.instance; } @Override - public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) { - return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game); + public String toString() { + return "X"; + } + + @Override + public String getMessage() { + return "the power of the creature that died"; } } diff --git a/Mage.Sets/src/mage/cards/d/DeceiverOfForm.java b/Mage.Sets/src/mage/cards/d/DeceiverOfForm.java index 46472f791f6..274f2984b79 100644 --- a/Mage.Sets/src/mage/cards/d/DeceiverOfForm.java +++ b/Mage.Sets/src/mage/cards/d/DeceiverOfForm.java @@ -1,12 +1,11 @@ package mage.cards.d; -import java.util.UUID; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CopyEffect; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.*; import mage.constants.*; import mage.filter.StaticFilters; @@ -15,6 +14,8 @@ import mage.game.permanent.Permanent; import mage.game.permanent.PermanentCard; import mage.players.Player; +import java.util.UUID; + /** * * @author LevelX2 @@ -47,7 +48,9 @@ class DeceiverOfFormEffect extends OneShotEffect { DeceiverOfFormEffect() { super(Outcome.Copy); - this.staticText = "reveal the top card of your library. If a creature card is revealed this way, you may have creatures you control other than Deceiver of Form becomes copies of that card until end of turn. You may put that card on the bottom of your library"; + this.staticText = "reveal the top card of your library. If a creature card is revealed this way, " + + "you may have creatures you control other than {this} become copies of that card until end of turn. " + + "You may put that card on the bottom of your library"; } private DeceiverOfFormEffect(final DeceiverOfFormEffect effect) { diff --git a/Mage.Sets/src/mage/cards/d/DecimatorBeetle.java b/Mage.Sets/src/mage/cards/d/DecimatorBeetle.java index 29e3b1a0b2e..1b0d6459c4c 100644 --- a/Mage.Sets/src/mage/cards/d/DecimatorBeetle.java +++ b/Mage.Sets/src/mage/cards/d/DecimatorBeetle.java @@ -18,8 +18,8 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.DefendingPlayerControlsSourceAttackingPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; import java.util.UUID; @@ -51,7 +51,7 @@ public final class DecimatorBeetle extends CardImpl { // Whenever Decimator Beetle attacks, remove a -1/-1 counter from target creature you control and put a -1/-1 counter on up to one target creature defending player controls. ability = new AttacksTriggeredAbility(new DecimatorBeetleEffect(), false); ability.addTarget(new TargetControlledCreaturePermanent()); - ability.addTarget(new TargetCreaturePermanent(0, 1, filter, false)); + ability.addTarget(new TargetPermanent(0, 1, filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DecisiveDenial.java b/Mage.Sets/src/mage/cards/d/DecisiveDenial.java index d6957b31e90..e6a20f79eca 100644 --- a/Mage.Sets/src/mage/cards/d/DecisiveDenial.java +++ b/Mage.Sets/src/mage/cards/d/DecisiveDenial.java @@ -8,12 +8,15 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.TargetSpell; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author TheElk801 */ @@ -28,7 +31,7 @@ public final class DecisiveDenial extends CardImpl { .setText("target creature you control fights target creature you don't control. " + "(Each deals damage equal to its power to the other.)")); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); // • Counter target noncreature spell unless its controller pays {3}. Mode mode = new Mode(new CounterUnlessPaysEffect(new GenericManaCost(3))); diff --git a/Mage.Sets/src/mage/cards/d/Decomposition.java b/Mage.Sets/src/mage/cards/d/Decomposition.java index 521456ac0c8..8fbe385fa0b 100644 --- a/Mage.Sets/src/mage/cards/d/Decomposition.java +++ b/Mage.Sets/src/mage/cards/d/Decomposition.java @@ -36,7 +36,7 @@ public final class Decomposition extends CardImpl { this.subtype.add(SubType.AURA); // Enchant black creature - TargetPermanent auraTarget = new TargetCreaturePermanent(filter); + TargetPermanent auraTarget = new TargetPermanent(filter); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); this.addAbility(new EnchantAbility(auraTarget)); diff --git a/Mage.Sets/src/mage/cards/d/DeepwaterHypnotist.java b/Mage.Sets/src/mage/cards/d/DeepwaterHypnotist.java index 35021e43a5d..28f5f23770a 100644 --- a/Mage.Sets/src/mage/cards/d/DeepwaterHypnotist.java +++ b/Mage.Sets/src/mage/cards/d/DeepwaterHypnotist.java @@ -12,8 +12,11 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Duration; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -30,7 +33,7 @@ public final class DeepwaterHypnotist extends CardImpl { // Inspired — Whenever Deepwater Hypnotist becomes untapped, target creature an opponent controls gets -3/-0 until end of turn. Ability ability = new InspiredAbility(new BoostTargetEffect(-3,0,Duration.EndOfTurn)); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/Defeat.java b/Mage.Sets/src/mage/cards/d/Defeat.java index 8c281809849..9b85431acd7 100644 --- a/Mage.Sets/src/mage/cards/d/Defeat.java +++ b/Mage.Sets/src/mage/cards/d/Defeat.java @@ -9,6 +9,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -28,7 +29,7 @@ public final class Defeat extends CardImpl { // Destroy target creature with power 2 or less. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private Defeat(final Defeat card) { diff --git a/Mage.Sets/src/mage/cards/d/DefendersOfHumanity.java b/Mage.Sets/src/mage/cards/d/DefendersOfHumanity.java index e20d84241bd..d79a39f35fb 100644 --- a/Mage.Sets/src/mage/cards/d/DefendersOfHumanity.java +++ b/Mage.Sets/src/mage/cards/d/DefendersOfHumanity.java @@ -17,7 +17,6 @@ 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.game.permanent.token.WhiteAstartesWarriorToken; @@ -29,7 +28,8 @@ import java.util.UUID; public final class DefendersOfHumanity extends CardImpl { private static final Condition condition = new CompoundCondition( - "you control no creatures and only during your turn", MyTurnCondition.instance, + "you control no creatures and only during your turn", + MyTurnCondition.instance, new PermanentsOnTheBattlefieldCondition( StaticFilters.FILTER_PERMANENT_CREATURE, ComparisonType.EQUAL_TO, 0, true @@ -46,13 +46,12 @@ public final class DefendersOfHumanity extends CardImpl { // {X}{2}{W}, Exile Defenders of Humanity: Create X 2/2 white Astartes Warrior creature tokens with vigilance. Activate only if you control no creatures and only during your turn. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new CreateTokenEffect( - new WhiteAstartesWarriorToken(), mage.abilities.dynamicvalue.common.GetXValue.instance + new WhiteAstartesWarriorToken(), GetXValue.instance ), new ManaCostsImpl<>("{X}{2}{W}"), condition - ).addHint(CreaturesYouControlHint.instance).addHint(MyTurnHint.instance); + ); ability.addCost(new ExileSourceCost()); - this.addAbility(ability); + this.addAbility(ability.addHint(CreaturesYouControlHint.instance).addHint(MyTurnHint.instance)); } private DefendersOfHumanity(final DefendersOfHumanity card) { diff --git a/Mage.Sets/src/mage/cards/d/DefenseOfTheHeart.java b/Mage.Sets/src/mage/cards/d/DefenseOfTheHeart.java index f3ce8f82c72..7278452a172 100644 --- a/Mage.Sets/src/mage/cards/d/DefenseOfTheHeart.java +++ b/Mage.Sets/src/mage/cards/d/DefenseOfTheHeart.java @@ -32,7 +32,7 @@ public final class DefenseOfTheHeart extends CardImpl { // At the beginning of your upkeep, if an opponent controls three or more creatures, sacrifice Defense of the Heart, search your library for up to two creature cards, and put those cards onto the battlefield. Then shuffle your library. Ability ability = new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceEffect()).withInterveningIf(condition); ability.addEffect(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary( - 2, StaticFilters.FILTER_CARD_CREATURES + 0, 2, StaticFilters.FILTER_CARD_CREATURES )).concatBy(",")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DefiantGreatmaw.java b/Mage.Sets/src/mage/cards/d/DefiantGreatmaw.java index 7731c6c3471..48df4f2c41f 100644 --- a/Mage.Sets/src/mage/cards/d/DefiantGreatmaw.java +++ b/Mage.Sets/src/mage/cards/d/DefiantGreatmaw.java @@ -17,6 +17,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.game.Game; import mage.game.events.GameEvent; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; @@ -64,7 +65,7 @@ class DefiantGreatmawTriggeredAbility extends TriggeredAbilityImpl { DefiantGreatmawTriggeredAbility() { super(Zone.BATTLEFIELD, new RemoveCounterTargetEffect(CounterType.M1M1.createInstance(1)), false); - this.addTarget(new TargetCreaturePermanent(filter)); + this.addTarget(new TargetPermanent(filter)); } private DefiantGreatmawTriggeredAbility(final DefiantGreatmawTriggeredAbility ability) { diff --git a/Mage.Sets/src/mage/cards/d/DegaSanctuary.java b/Mage.Sets/src/mage/cards/d/DegaSanctuary.java index 6d1b49c3aee..c127a371083 100644 --- a/Mage.Sets/src/mage/cards/d/DegaSanctuary.java +++ b/Mage.Sets/src/mage/cards/d/DegaSanctuary.java @@ -1,17 +1,15 @@ - package mage.cards.d; -import java.util.UUID; import mage.ObjectColor; -import mage.abilities.Ability; -import mage.abilities.common.SanctuaryInterveningIfTriggeredAbility; +import mage.abilities.common.SanctuaryTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class DegaSanctuary extends CardImpl { @@ -20,12 +18,10 @@ public final class DegaSanctuary extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}"); // At the beginning of your upkeep, if you control a black or red permanent, you gain 2 life. If you control a black permanent and a red permanent, you gain 4 life instead. - Ability ability = new SanctuaryInterveningIfTriggeredAbility( + this.addAbility(new SanctuaryTriggeredAbility( new GainLifeEffect(2), new GainLifeEffect(4), ObjectColor.BLACK, ObjectColor.RED, - "At the beginning of your upkeep, if you control a black or red permanent, you gain 2 life. " - + "If you control a black permanent and a red permanent, you gain 4 life instead." - ); - this.addAbility(ability); + "you gain 2 life. If you control a black permanent and a red permanent, you gain 4 life instead." + )); } private DegaSanctuary(final DegaSanctuary card) { diff --git a/Mage.Sets/src/mage/cards/d/Degavolver.java b/Mage.Sets/src/mage/cards/d/Degavolver.java index ca554f5db41..753be670bad 100644 --- a/Mage.Sets/src/mage/cards/d/Degavolver.java +++ b/Mage.Sets/src/mage/cards/d/Degavolver.java @@ -1,7 +1,6 @@ package mage.cards.d; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; @@ -16,11 +15,12 @@ import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; import mage.counters.CounterType; +import java.util.UUID; + /** * * @author Loki @@ -41,16 +41,16 @@ public final class Degavolver extends CardImpl { // If Degavolver was kicked with its {1}{B} kicker, it enters with two +1/+1 counters on it and with "Pay 3 life: Regenerate Degavolver." EntersBattlefieldAbility ability1 = new EntersBattlefieldAbility( - new AddCountersSourceEffect(CounterType.P1P1.createInstance(2),false), - new KickedCostCondition("{1}{B}"), "If Degavolver was kicked with its {1}{B} kicker, it enters with two +1/+1 counters on it and with \"Pay 3 life: Regenerate Degavolver.\"", - "{this} enters with two +1/+1 counters on it and with \"Pay 3 life: Regenerate Degavolver.\""); + new AddCountersSourceEffect(CounterType.P1P1.createInstance(2), false), + new KickedCostCondition("{1}{B}"), "If {this} was kicked with its {1}{B} kicker, it enters with two +1/+1 counters on it and with \"Pay 3 life: Regenerate this creature.\"", + "{this} enters with two +1/+1 counters on it and with \"Pay 3 life: Regenerate this creature.\""); ((EntersBattlefieldEffect)ability1.getEffects().get(0)).addEffect(new GainAbilitySourceEffect(new SimpleActivatedAbility(new RegenerateSourceEffect(), new PayLifeCost(3)), Duration.WhileOnBattlefield)); this.addAbility(ability1); // If Degavolver was kicked with its {R} kicker, it enters with a +1/+1 counter on it and with first strike. EntersBattlefieldAbility ability2 = new EntersBattlefieldAbility( - new AddCountersSourceEffect(CounterType.P1P1.createInstance(1),false), new KickedCostCondition("{R}"), - "If Degavolver was kicked with its {R} kicker, it enters with a +1/+1 counter on it and with first strike.", + new AddCountersSourceEffect(CounterType.P1P1.createInstance(1), false), new KickedCostCondition("{R}"), + "If {this} was kicked with its {R} kicker, it enters with a +1/+1 counter on it and with first strike.", "{this} enters with a +1/+1 counter on it and with first strike"); ((EntersBattlefieldEffect)ability2.getEffects().get(0)).addEffect(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.WhileOnBattlefield)); this.addAbility(ability2); diff --git a/Mage.Sets/src/mage/cards/d/Delirium.java b/Mage.Sets/src/mage/cards/d/Delirium.java index 62cc5e30fe6..7ec4f49004d 100644 --- a/Mage.Sets/src/mage/cards/d/Delirium.java +++ b/Mage.Sets/src/mage/cards/d/Delirium.java @@ -17,6 +17,7 @@ import mage.filter.predicate.permanent.ControllerIsActivePlayerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -40,7 +41,7 @@ public final class Delirium extends CardImpl { this.addAbility(new CastOnlyIfConditionIsTrueAbility(OnOpponentsTurnCondition.instance, "Cast this spell only during an opponent's turn.")); // Tap target creature that player controls. That creature deals damage equal to its power to the player. Prevent all combat damage that would be dealt to and dealt by the creature this turn. this.getSpellAbility().addEffect(new TapTargetEffect("tap target creature that player controls")); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DeliriumEffect()); this.getSpellAbility().addEffect(new PreventDamageToTargetEffect(Duration.EndOfTurn, true).setText("Prevent all combat damage that would be dealt to")); this.getSpellAbility().addEffect(new PreventDamageByTargetEffect(Duration.EndOfTurn, true).setText("and dealt by the creature this turn.")); diff --git a/Mage.Sets/src/mage/cards/d/DementiaSliver.java b/Mage.Sets/src/mage/cards/d/DementiaSliver.java index 92b47218904..5a5a50ed8e2 100644 --- a/Mage.Sets/src/mage/cards/d/DementiaSliver.java +++ b/Mage.Sets/src/mage/cards/d/DementiaSliver.java @@ -10,10 +10,13 @@ import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ChooseACardNameEffect; import mage.abilities.effects.common.continuous.GainAbilityAllEffect; -import mage.abilities.hint.common.MyTurnHint; import mage.cards.*; -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.StaticFilters; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetOpponent; @@ -39,12 +42,15 @@ public final class DementiaSliver extends CardImpl { this.toughness = new MageInt(3); // All Slivers have "{T}: Name a card. Target opponent reveals a card at random from their hand. If it's the named card, that player discards it. Activate this ability only during your turn." - Ability gainedAbility = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL), new TapSourceCost(), MyTurnCondition.instance); + Ability gainedAbility = new ActivateIfConditionActivatedAbility( + new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL), + new TapSourceCost(), MyTurnCondition.instance + ); gainedAbility.addEffect(new DementiaSliverEffect()); gainedAbility.addTarget(new TargetOpponent()); - gainedAbility.addHint(MyTurnHint.instance); this.addAbility(new SimpleStaticAbility( - new GainAbilityAllEffect(gainedAbility, Duration.WhileOnBattlefield, filter, + new GainAbilityAllEffect( + gainedAbility, Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_ALL_SLIVERS, "All Slivers have \"{T}: Choose a card name. " + "Target opponent reveals a card at random from their hand." + " If that card has the chosen name, that player discards it." @@ -67,7 +73,7 @@ class DementiaSliverEffect extends OneShotEffect { DementiaSliverEffect() { super(Outcome.Damage); - staticText = "Target opponent reveals a card at random from their hand. If that card has the chose name, that player discards it"; + staticText = "Target opponent reveals a card at random from their hand. If that card has the chosen name, that player discards it"; } private DementiaSliverEffect(final DementiaSliverEffect effect) { diff --git a/Mage.Sets/src/mage/cards/d/DemonicCovenant.java b/Mage.Sets/src/mage/cards/d/DemonicCovenant.java index 02be019387c..0ab82065414 100644 --- a/Mage.Sets/src/mage/cards/d/DemonicCovenant.java +++ b/Mage.Sets/src/mage/cards/d/DemonicCovenant.java @@ -1,7 +1,7 @@ package mage.cards.d; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; @@ -12,12 +12,11 @@ import mage.cards.CardSetInfo; import mage.cards.Cards; import mage.constants.CardType; import mage.constants.Outcome; +import mage.constants.SetTargetPointer; import mage.constants.SubType; -import mage.constants.Zone; -import mage.game.Controllable; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; import mage.game.Game; -import mage.game.events.DefenderAttackedEvent; -import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.permanent.token.DemonToken; import mage.players.Player; @@ -30,6 +29,7 @@ import java.util.UUID; * @author TheElk801 */ public final class DemonicCovenant extends CardImpl { + FilterPermanent filter = new FilterControlledPermanent(SubType.DEMON,"Demons you control"); public DemonicCovenant(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.KINDRED, CardType.ENCHANTMENT}, "{4}{B}{B}"); @@ -37,12 +37,14 @@ public final class DemonicCovenant extends CardImpl { this.subtype.add(SubType.DEMON); // Whenever one or more Demons you control attack a player, you draw a card and lose 1 life. - this.addAbility(new DemonicCovenantTriggeredAbility()); + Ability abilityAttack = new AttacksPlayerWithCreaturesTriggeredAbility(new DrawCardSourceControllerEffect(1, true), filter, SetTargetPointer.NONE); + abilityAttack.addEffect(new LoseLifeSourceControllerEffect(1).setText("and lose 1 life")); + this.addAbility(abilityAttack); // At the beginning of your end step, create a 5/5 black Demon creature token with flying, then mill two cards. If two cards that share all their card types were milled this way, sacrifice Demonic Covenant. - Ability ability = new BeginningOfEndStepTriggeredAbility(new CreateTokenEffect(new DemonToken())); - ability.addEffect(new DemonicCovenantEffect()); - this.addAbility(ability); + Ability abilityEndStep = new BeginningOfEndStepTriggeredAbility(new CreateTokenEffect(new DemonToken())); + abilityEndStep.addEffect(new DemonicCovenantEffect()); + this.addAbility(abilityEndStep); } private DemonicCovenant(final DemonicCovenant card) { @@ -55,40 +57,6 @@ public final class DemonicCovenant extends CardImpl { } } -class DemonicCovenantTriggeredAbility extends TriggeredAbilityImpl { - - DemonicCovenantTriggeredAbility() { - super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1, true)); - this.addEffect(new LoseLifeSourceControllerEffect(1).setText("and lose 1 life")); - this.setTriggerPhrase("Whenever one or more Demons you control attack a player, "); - } - - private DemonicCovenantTriggeredAbility(final DemonicCovenantTriggeredAbility ability) { - super(ability); - } - - @Override - public DemonicCovenantTriggeredAbility copy() { - return new DemonicCovenantTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DEFENDER_ATTACKED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return game.getPlayer(event.getTargetId()) != null - && ((DefenderAttackedEvent) event) - .getAttackers(game) - .stream() - .filter(permanent -> permanent.hasSubtype(SubType.DEMON, game)) - .map(Controllable::getControllerId) - .anyMatch(this::isControlledBy); - } -} - class DemonicCovenantEffect extends OneShotEffect { DemonicCovenantEffect() { diff --git a/Mage.Sets/src/mage/cards/d/DenryKlinEditorInChief.java b/Mage.Sets/src/mage/cards/d/DenryKlinEditorInChief.java index 2f83f11f11e..94b6e76573d 100644 --- a/Mage.Sets/src/mage/cards/d/DenryKlinEditorInChief.java +++ b/Mage.Sets/src/mage/cards/d/DenryKlinEditorInChief.java @@ -3,7 +3,7 @@ package mage.cards.d; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.condition.common.SourceHasCountersCondition; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCounterChoiceSourceEffect; @@ -42,7 +42,7 @@ public class DenryKlinEditorInChief extends CardImpl { // Whenever a nontoken creature you control enters, // if Denry has counters on it, put the same number of each kind of counter on that creature. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + this.addAbility(new EntersBattlefieldAllTriggeredAbility( new DenryKlinEditorInChiefCopyCountersEffect(), StaticFilters.FILTER_CONTROLLED_CREATURE_NON_TOKEN ).withInterveningIf(SourceHasCountersCondition.instance)); diff --git a/Mage.Sets/src/mage/cards/d/DepartedDeckhand.java b/Mage.Sets/src/mage/cards/d/DepartedDeckhand.java index eb731ca38e6..1d26fc870d3 100644 --- a/Mage.Sets/src/mage/cards/d/DepartedDeckhand.java +++ b/Mage.Sets/src/mage/cards/d/DepartedDeckhand.java @@ -1,6 +1,6 @@ package mage.cards.d; -import java.util.UUID; +import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.BecomesTargetSourceTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; @@ -9,20 +9,19 @@ import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; import mage.abilities.effects.common.combat.CantBeBlockedTargetEffect; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; -import mage.target.common.TargetControlledCreaturePermanent; -import mage.MageInt; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class DepartedDeckhand extends CardImpl { @@ -63,7 +62,7 @@ public final class DepartedDeckhand extends CardImpl { ).setText("Another target creature you control can't be blocked this turn except by Spirits"), new ManaCostsImpl<>("{3}{U}") ); - ability.addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/Desert.java b/Mage.Sets/src/mage/cards/d/Desert.java index 65f2fdb2149..27aee857b66 100644 --- a/Mage.Sets/src/mage/cards/d/Desert.java +++ b/Mage.Sets/src/mage/cards/d/Desert.java @@ -1,45 +1,47 @@ - package mage.cards.d; -import java.util.UUID; import mage.abilities.Ability; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.mana.ColorlessManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.PhaseStep; -import mage.constants.Zone; +import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.AttackingPredicate; -import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class Desert extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("attacking creature"); + static { filter.add(AttackingPredicate.instance); } + private static final Condition condition = new IsStepCondition(PhaseStep.END_COMBAT, false); + public Desert(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.LAND},""); + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); this.subtype.add(SubType.DESERT); // {tap}: Add {C}. this.addAbility(new ColorlessManaAbility()); + // {tap}: Desert deals 1 damage to target attacking creature. Activate this ability only during the end of combat step. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new TapSourceCost(), new IsStepCondition(PhaseStep.END_COMBAT, false)); - Target target = new TargetCreaturePermanent(filter); - ability.addTarget(target); + Ability ability = new ActivateIfConditionActivatedAbility(new DamageTargetEffect(1), new TapSourceCost(), condition); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DesiccatedNaga.java b/Mage.Sets/src/mage/cards/d/DesiccatedNaga.java index a429b6637d3..134a3c0679e 100644 --- a/Mage.Sets/src/mage/cards/d/DesiccatedNaga.java +++ b/Mage.Sets/src/mage/cards/d/DesiccatedNaga.java @@ -3,6 +3,7 @@ package mage.cards.d; 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.mana.ManaCostsImpl; import mage.abilities.effects.common.GainLifeEffect; @@ -11,8 +12,7 @@ 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; @@ -22,11 +22,7 @@ import java.util.UUID; */ public final class DesiccatedNaga extends CardImpl { - private static final FilterPlaneswalkerPermanent filter = new FilterPlaneswalkerPermanent("you control a Liliana planeswalker"); - - static { - filter.add(SubType.LILIANA.getPredicate()); - } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(new FilterControlledPlaneswalkerPermanent(SubType.LILIANA, "you control a Liliana planeswalker")); public DesiccatedNaga(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); @@ -37,10 +33,9 @@ public final class DesiccatedNaga extends CardImpl { this.toughness = new MageInt(2); // {3}{B}: Target opponent loses 2 life and you gain 2 life. Activate this ability only if you control a Liliana planeswalker. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new LoseLifeTargetEffect(2), - new ManaCostsImpl<>("{3}{B}"), - new PermanentsOnTheBattlefieldCondition(filter)); + Ability ability = new ActivateIfConditionActivatedAbility( + new LoseLifeTargetEffect(2), new ManaCostsImpl<>("{3}{B}"), condition + ); ability.addEffect(new GainLifeEffect(2).concatBy("and")); ability.addTarget(new TargetOpponent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/d/DestroyEvil.java b/Mage.Sets/src/mage/cards/d/DestroyEvil.java index 3c9e218e07a..6faf4381ac8 100644 --- a/Mage.Sets/src/mage/cards/d/DestroyEvil.java +++ b/Mage.Sets/src/mage/cards/d/DestroyEvil.java @@ -10,6 +10,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ToughnessPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetEnchantmentPermanent; @@ -31,7 +32,7 @@ public final class DestroyEvil extends CardImpl { // Choose one-- // * Destroy target creature with toughness 4 or greater. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // * Destroy target enchantment. Mode mode = new Mode(new DestroyTargetEffect()); diff --git a/Mage.Sets/src/mage/cards/d/DetectivesSatchel.java b/Mage.Sets/src/mage/cards/d/DetectivesSatchel.java index 12357dd83fc..384f1f7edd1 100644 --- a/Mage.Sets/src/mage/cards/d/DetectivesSatchel.java +++ b/Mage.Sets/src/mage/cards/d/DetectivesSatchel.java @@ -3,7 +3,7 @@ package mage.cards.d; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.SacrificedArtifactThisTurnCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.keyword.InvestigateEffect; import mage.cards.CardImpl; @@ -26,7 +26,7 @@ public final class DetectivesSatchel extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new InvestigateEffect(2))); // {T}: Create a 1/1 colorless Thopter artifact creature token with flying. Activate only if you've sacrificed an artifact this turn. - this.addAbility(new ConditionalActivatedAbility( + this.addAbility(new ActivateIfConditionActivatedAbility( new CreateTokenEffect(new ThopterColorlessToken()), new TapSourceCost(), SacrificedArtifactThisTurnCondition.instance ).addHint(SacrificedArtifactThisTurnCondition.getHint()), new PermanentsSacrificedWatcher()); diff --git a/Mage.Sets/src/mage/cards/d/DeusOfCalamity.java b/Mage.Sets/src/mage/cards/d/DeusOfCalamity.java index 9c5a614d177..321aaca1eca 100644 --- a/Mage.Sets/src/mage/cards/d/DeusOfCalamity.java +++ b/Mage.Sets/src/mage/cards/d/DeusOfCalamity.java @@ -10,13 +10,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; -import mage.filter.FilterPermanent; -import mage.filter.common.FilterLandPermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.events.GameEvent; -import mage.target.Target; -import mage.target.TargetPermanent; +import mage.target.common.TargetLandPermanent; +import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster; +import mage.target.targetpointer.FixedTarget; import java.util.UUID; @@ -53,6 +51,8 @@ class DeusOfCalamityTriggeredAbility extends TriggeredAbilityImpl { public DeusOfCalamityTriggeredAbility() { super(Zone.BATTLEFIELD, new DestroyTargetEffect(), false); + addTarget(new TargetLandPermanent()); + setTargetAdjuster(new ThatPlayerControlsTargetAdjuster()); } private DeusOfCalamityTriggeredAbility(final DeusOfCalamityTriggeredAbility ability) { @@ -74,11 +74,7 @@ class DeusOfCalamityTriggeredAbility extends TriggeredAbilityImpl { if (event.getSourceId().equals(this.getSourceId()) && event.getAmount() > 5 && game.getOpponents(this.getControllerId()).contains(event.getTargetId())) { - FilterPermanent filter = new FilterLandPermanent("land of the damaged player"); - filter.add(new ControllerIdPredicate(event.getTargetId())); - Target target = new TargetPermanent(filter); - this.getTargets().clear(); - this.addTarget(target); + this.getEffects().setTargetPointer(new FixedTarget(event.getTargetId(), game)); return true; } return false; @@ -86,6 +82,6 @@ class DeusOfCalamityTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever Deus of Calamity deals 6 or more damage to an opponent, destroy target land that player controls."; + return "Whenever {this} deals 6 or more damage to an opponent, destroy target land that player controls."; } } diff --git a/Mage.Sets/src/mage/cards/d/DiamondCity.java b/Mage.Sets/src/mage/cards/d/DiamondCity.java index c39088f9cb4..9df99ce625c 100644 --- a/Mage.Sets/src/mage/cards/d/DiamondCity.java +++ b/Mage.Sets/src/mage/cards/d/DiamondCity.java @@ -5,7 +5,7 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -16,7 +16,6 @@ import mage.abilities.mana.ColorlessManaAbility; 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.permanent.Permanent; @@ -27,7 +26,6 @@ import java.util.List; import java.util.UUID; /** - * * @author notgreat */ public final class DiamondCity extends CardImpl { @@ -46,11 +44,12 @@ public final class DiamondCity extends CardImpl { this.addAbility(new ColorlessManaAbility()); // {T}: Move a shield counter from Diamond City onto target creature. Activate only if two or more creatures entered the battlefield under your control this turn. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new MoveCountersFromSourceToTargetEffect(CounterType.SHIELD), - new TapSourceCost(), DiamondCityCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new MoveCountersFromSourceToTargetEffect(CounterType.SHIELD), + new TapSourceCost(), DiamondCityCondition.instance + ); ability.addTarget(new TargetCreaturePermanent()); - ability.addHint(DiamondCityCreaturesThatEnteredThisTurnCount.getHint()); - this.addAbility(ability, new PermanentsEnteredBattlefieldWatcher()); + this.addAbility(ability.addHint(DiamondCityCreaturesThatEnteredThisTurnCount.getHint()), new PermanentsEnteredBattlefieldWatcher()); } private DiamondCity(final DiamondCity card) { diff --git a/Mage.Sets/src/mage/cards/d/DiaochanArtfulBeauty.java b/Mage.Sets/src/mage/cards/d/DiaochanArtfulBeauty.java index f1ae94a56c6..5f431d70650 100644 --- a/Mage.Sets/src/mage/cards/d/DiaochanArtfulBeauty.java +++ b/Mage.Sets/src/mage/cards/d/DiaochanArtfulBeauty.java @@ -5,16 +5,16 @@ import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.common.MyTurnBeforeAttackersDeclaredCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetOpponentsChoicePermanent; +import mage.target.targetpointer.EachTargetPointer; import java.util.UUID; @@ -33,9 +33,16 @@ public final class DiaochanArtfulBeauty extends CardImpl { this.toughness = new MageInt(1); // {tap}: Destroy target creature of your choice, then destroy target creature of an opponent's choice. Activate this ability only during your turn, before attackers are declared. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new DiaochanArtfulBeautyDestroyEffect(), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new DestroyTargetEffect() + .setTargetPointer(new EachTargetPointer()) + .setText("destroy target creature of your choice, then destroy target creature of an opponent's choice"), + new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance + ); ability.addTarget(new TargetCreaturePermanent()); - ability.addTarget(new TargetOpponentsChoicePermanent(1, 1, StaticFilters.FILTER_PERMANENT_CREATURE, false)); + ability.addTarget(new TargetOpponentsChoicePermanent( + 1, 1, StaticFilters.FILTER_PERMANENT_CREATURE, false + )); this.addAbility(ability); } @@ -48,38 +55,3 @@ public final class DiaochanArtfulBeauty extends CardImpl { return new DiaochanArtfulBeauty(this); } } - -class DiaochanArtfulBeautyDestroyEffect extends OneShotEffect { - - DiaochanArtfulBeautyDestroyEffect() { - super(Outcome.DestroyPermanent); - this.staticText = "Destroy target creature of your choice, then destroy target creature of an opponent's choice"; - } - - private DiaochanArtfulBeautyDestroyEffect(final DiaochanArtfulBeautyDestroyEffect effect) { - super(effect); - } - - @Override - public DiaochanArtfulBeautyDestroyEffect copy() { - return new DiaochanArtfulBeautyDestroyEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Permanent firstTarget = game.getPermanent(source.getFirstTarget()); - if (firstTarget != null) { - firstTarget.destroy(source, game, false); - - } - Permanent secondTarget = game.getPermanent(source.getTargets().get(1).getFirstTarget()); - if (secondTarget != null) { - secondTarget.destroy(source, game, false); - } - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/d/DihadaBinderOfWills.java b/Mage.Sets/src/mage/cards/d/DihadaBinderOfWills.java index 9ea7e36b145..dc1696e2297 100644 --- a/Mage.Sets/src/mage/cards/d/DihadaBinderOfWills.java +++ b/Mage.Sets/src/mage/cards/d/DihadaBinderOfWills.java @@ -19,7 +19,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.token.TreasureToken; import mage.players.Player; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -51,7 +51,7 @@ public final class DihadaBinderOfWills extends CardImpl { ability.addEffect(new GainAbilityTargetEffect( IndestructibleAbility.getInstance(), Duration.UntilYourNextTurn ).setText(", and indestructible until your next turn.")); - ability.addTarget(new TargetCreaturePermanent(0, 1, filter, false)); + ability.addTarget(new TargetPermanent(0, 1, filter)); this.addAbility(ability); // -3: Reveal the top four cards of your library. diff --git a/Mage.Sets/src/mage/cards/d/DimirCharm.java b/Mage.Sets/src/mage/cards/d/DimirCharm.java index e17f78a2a69..a102a832ab3 100644 --- a/Mage.Sets/src/mage/cards/d/DimirCharm.java +++ b/Mage.Sets/src/mage/cards/d/DimirCharm.java @@ -19,6 +19,7 @@ import mage.filter.predicate.mageobject.PowerPredicate; import mage.game.Game; import mage.players.Player; import mage.target.TargetCard; +import mage.target.TargetPermanent; import mage.target.TargetPlayer; import mage.target.TargetSpell; import mage.target.common.TargetCreaturePermanent; @@ -46,7 +47,7 @@ public final class DimirCharm extends CardImpl { //or destroy target creature with power 2 or less Mode mode1 = new Mode(new DestroyTargetEffect()); - mode1.addTarget(new TargetCreaturePermanent(filterCreature)); + mode1.addTarget(new TargetPermanent(filterCreature)); this.getSpellAbility().addMode(mode1); //or look at the top three cards of target player's library, then put one back and the rest into that player's graveyard diff --git a/Mage.Sets/src/mage/cards/d/DimirStrandcatcher.java b/Mage.Sets/src/mage/cards/d/DimirStrandcatcher.java new file mode 100644 index 00000000000..9f2c5e97a3d --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DimirStrandcatcher.java @@ -0,0 +1,174 @@ +package mage.cards.d; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksWithCreaturesTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.players.Player; +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 DimirStrandcatcher extends CardImpl { + + public DimirStrandcatcher(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U/B}{U/B}"); + + this.subtype.add(SubType.FAERIE); + this.subtype.add(SubType.ROGUE); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenever you attack, surveil X, where X is the number of opponents being attacked. + this.addAbility(new AttacksWithCreaturesTriggeredAbility(new DimirStrandcatcherEffect(), 1)); + + // At the beginning of each end step, if three or more cards were put into your graveyard from anywhere other than the battlefield this turn, draw a card. + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.EACH_PLAYER, new DrawCardSourceControllerEffect(1), + false, DimirStrandcatcherCondition.instance + ).addHint(DimirStrandcatcherValue.getHint()), new DimirStrandcatcherWatcher()); + } + + private DimirStrandcatcher(final DimirStrandcatcher card) { + super(card); + } + + @Override + public DimirStrandcatcher copy() { + return new DimirStrandcatcher(this); + } +} + +class DimirStrandcatcherEffect extends OneShotEffect { + + DimirStrandcatcherEffect() { + super(Outcome.Benefit); + staticText = "surveil X, where X is the number of opponents being attacked"; + } + + private DimirStrandcatcherEffect(final DimirStrandcatcherEffect effect) { + super(effect); + } + + @Override + public DimirStrandcatcherEffect copy() { + return new DimirStrandcatcherEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + int count = game + .getOpponents(source.getControllerId()) + .stream() + .filter(game.getCombat().getDefenders()::contains) + .mapToInt(x -> 1) + .sum(); + return player.surveil(count, source, game); + } +} + +enum DimirStrandcatcherCondition implements Condition { + instance; + + @Override + public boolean apply(Game game, Ability source) { + return DimirStrandcatcherValue.instance.calculate(game, source, null) >= 3; + } + + @Override + public String toString() { + return "three or more cards were put into your graveyard from anywhere other than the battlefield this turn"; + } +} + +enum DimirStrandcatcherValue implements DynamicValue { + instance; + private static final Hint hint = new ValueHint( + "Cards put into your graveyard from anywhere other than the battlefield this turn", instance + ); + + public static Hint getHint() { + return hint; + } + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + return DimirStrandcatcherWatcher.getValue(game, sourceAbility); + } + + @Override + public DimirStrandcatcherValue copy() { + return this; + } + + @Override + public String getMessage() { + return ""; + } + + @Override + public String toString() { + return "1"; + } +} + +class DimirStrandcatcherWatcher extends Watcher { + + private final Map map = new HashMap<>(); + + DimirStrandcatcherWatcher() { + super(WatcherScope.GAME); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() != GameEvent.EventType.ZONE_CHANGE) { + return; + } + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + if (Zone.GRAVEYARD.match(zEvent.getToZone()) && !Zone.BATTLEFIELD.match(zEvent.getFromZone())) { + map.compute(game.getOwnerId(zEvent.getTargetId()), CardUtil::setOrIncrementValue); + } + } + + @Override + public void reset() { + super.reset(); + map.clear(); + } + + static int getValue(Game game, Ability source) { + return game + .getState() + .getWatcher(DimirStrandcatcherWatcher.class) + .map + .getOrDefault(source.getControllerId(), 0); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DireFleetPoisoner.java b/Mage.Sets/src/mage/cards/d/DireFleetPoisoner.java index 58df2723d95..c4f5b9a6721 100644 --- a/Mage.Sets/src/mage/cards/d/DireFleetPoisoner.java +++ b/Mage.Sets/src/mage/cards/d/DireFleetPoisoner.java @@ -17,6 +17,7 @@ import mage.constants.SubType; import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.AttackingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -53,7 +54,7 @@ public final class DireFleetPoisoner extends CardImpl { effect = new GainAbilityTargetEffect(DeathtouchAbility.getInstance(), Duration.EndOfTurn); effect.setText("and gains deathtouch until end of turn"); ability.addEffect(effect); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DiscipleOfBolas.java b/Mage.Sets/src/mage/cards/d/DiscipleOfBolas.java index 9add46c6857..83228895223 100644 --- a/Mage.Sets/src/mage/cards/d/DiscipleOfBolas.java +++ b/Mage.Sets/src/mage/cards/d/DiscipleOfBolas.java @@ -1,25 +1,23 @@ - package mage.cards.d; -import java.util.UUID; import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.common.SacrificeTargetCost; 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.filter.StaticFilters; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.Target; -import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class DiscipleOfBolas extends CardImpl { @@ -65,21 +63,24 @@ class DiscipleOfBolasEffect 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); - target.setRequired(true); - if (target.canChoose(source.getControllerId(), source, game)) { - controller.chooseTarget(outcome, target, source, game); - Permanent sacrificed = game.getPermanent(target.getFirstTarget()); - if (sacrificed != null) { - sacrificed.sacrifice(source, game); - int power = sacrificed.getPower().getValue(); - controller.gainLife(power, game, source); - controller.drawCards(power, source, game); - } - } - return true; + if (controller == null) { + return false; } - return false; + SacrificeTargetCost cost = new SacrificeTargetCost(StaticFilters.FILTER_ANOTHER_CREATURE); + if (!cost.canPay(source, source, source.getControllerId(), game) + || !cost.pay(source, game, source, source.getControllerId(), true)) { + return false; + } + int power = cost + .getPermanents() + .stream() + .map(MageObject::getPower) + .mapToInt(MageInt::getValue) + .sum(); + if (power > 0) { + controller.gainLife(power, game, source); + controller.drawCards(power, source, game); + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/d/DiseasedVermin.java b/Mage.Sets/src/mage/cards/d/DiseasedVermin.java index cc0d2f0ee1e..49f364fc910 100644 --- a/Mage.Sets/src/mage/cards/d/DiseasedVermin.java +++ b/Mage.Sets/src/mage/cards/d/DiseasedVermin.java @@ -1,19 +1,16 @@ package mage.cards.d; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.dynamicvalue.common.CountersSourceCount; +import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; -import mage.constants.SubType; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.WatcherScope; import mage.counters.CounterType; import mage.filter.FilterOpponent; @@ -21,17 +18,25 @@ import mage.filter.predicate.ObjectSourcePlayer; import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPlayer; import mage.watchers.Watcher; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class DiseasedVermin extends CardImpl { + private static final FilterOpponent filter = new FilterOpponent("player previously dealt damage by {this}"); + + static { + filter.add(new DiseasedVerminPredicate()); + } + public DiseasedVermin(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); @@ -46,12 +51,11 @@ public final class DiseasedVermin extends CardImpl { false)); // At the beginning of your upkeep, Diseased Vermin deals X damage to target opponent previously dealt damage by it, where X is the number of infection counters on it. - Ability ability = new BeginningOfUpkeepTriggeredAbility( - new DiseasedVerminEffect() - ); + Ability ability = new BeginningOfUpkeepTriggeredAbility(new DamageTargetEffect(new CountersSourceCount(CounterType.INFECTION)) + .setText("{this} deals X damage to target opponent previously dealt damage by it, where X is the number of infection counters on it")); + ability.addTarget(new TargetPlayer(filter)); ability.addWatcher(new DiseasedVerminWatcher()); this.addAbility(ability); - } private DiseasedVermin(final DiseasedVermin card) { @@ -64,51 +68,6 @@ public final class DiseasedVermin extends CardImpl { } } -class DiseasedVerminEffect extends OneShotEffect { - - static final FilterOpponent filter = new FilterOpponent("player previously dealt damage by {this}"); - - static { - filter.add(new DiseasedVerminPredicate()); - } - - public DiseasedVerminEffect() { - super(Outcome.Benefit); - this.staticText = "{this} deals X damage to target opponent previously dealt damage by it, where X is the number of infection counters on it"; - } - - private DiseasedVerminEffect(final DiseasedVerminEffect effect) { - super(effect); - } - - @Override - public DiseasedVerminEffect copy() { - return new DiseasedVerminEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if (sourcePermanent != null - && controller != null) { - TargetPlayer targetOpponent = new TargetPlayer(1, 1, false, filter); - if (targetOpponent.canChoose(controller.getId(), source, game) - && controller.choose(Outcome.Damage, targetOpponent, source, game)) { - Player opponent = game.getPlayer(targetOpponent.getFirstTarget()); - if (opponent != null - && sourcePermanent.getCounters(game).getCount(CounterType.INFECTION) > 0) { - opponent.damage( - sourcePermanent.getCounters(game).getCount(CounterType.INFECTION), - source.getSourceId(), source, game, false, true); - return true; - } - } - } - return false; - } -} - class DiseasedVerminPredicate implements ObjectSourcePlayerPredicate { @Override diff --git a/Mage.Sets/src/mage/cards/d/DispenseJustice.java b/Mage.Sets/src/mage/cards/d/DispenseJustice.java index 19870987397..700076f16fb 100644 --- a/Mage.Sets/src/mage/cards/d/DispenseJustice.java +++ b/Mage.Sets/src/mage/cards/d/DispenseJustice.java @@ -7,7 +7,6 @@ import mage.abilities.effects.common.SacrificeEffect; import mage.abilities.hint.common.MetalcraftHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.Outcome; import mage.filter.common.FilterAttackingCreature; @@ -44,7 +43,7 @@ public final class DispenseJustice extends CardImpl { class DispenseJusticeEffect extends OneShotEffect { - private static final String effectText = "Target player sacrifices an attacking creature.\r\n\r\n" + private static final String effectText = "Target player sacrifices an attacking creature.
" + "Metalcraft — That player sacrifices two attacking creatures instead if you control three or more artifacts"; private static final FilterAttackingCreature filter = new FilterAttackingCreature(); diff --git a/Mage.Sets/src/mage/cards/d/Displace.java b/Mage.Sets/src/mage/cards/d/Displace.java index fe45adc664d..00715cdc183 100644 --- a/Mage.Sets/src/mage/cards/d/Displace.java +++ b/Mage.Sets/src/mage/cards/d/Displace.java @@ -4,7 +4,6 @@ import mage.abilities.effects.common.ExileThenReturnTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.StaticFilters; import mage.target.common.TargetControlledCreaturePermanent; import java.util.UUID; @@ -18,8 +17,8 @@ public final class Displace extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}"); // Exile up to two target creatures you control, then return those cards to the battlefield under their owner's control. - this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, 2, StaticFilters.FILTER_CONTROLLED_CREATURES, false)); this.getSpellAbility().addEffect(new ExileThenReturnTargetEffect(false, true)); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, 2)); } private Displace(final Displace card) { diff --git a/Mage.Sets/src/mage/cards/d/DisruptingScepter.java b/Mage.Sets/src/mage/cards/d/DisruptingScepter.java index c4543772094..b69953b1046 100644 --- a/Mage.Sets/src/mage/cards/d/DisruptingScepter.java +++ b/Mage.Sets/src/mage/cards/d/DisruptingScepter.java @@ -4,13 +4,11 @@ import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.discard.DiscardTargetEffect; -import mage.abilities.hint.common.MyTurnHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; import mage.target.TargetPlayer; import java.util.UUID; @@ -24,10 +22,11 @@ public final class DisruptingScepter extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); // {3}, {T}: Target player discards a card. Activate this ability only during your turn. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new DiscardTargetEffect(1), new ManaCostsImpl<>("{3}"), MyTurnCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new DiscardTargetEffect(1), new GenericManaCost(3), MyTurnCondition.instance + ); ability.addTarget(new TargetPlayer()); ability.addCost(new TapSourceCost()); - ability.addHint(MyTurnHint.instance); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DisruptiveStormbrood.java b/Mage.Sets/src/mage/cards/d/DisruptiveStormbrood.java index 382d66191e4..fb459b5a2b7 100644 --- a/Mage.Sets/src/mage/cards/d/DisruptiveStormbrood.java +++ b/Mage.Sets/src/mage/cards/d/DisruptiveStormbrood.java @@ -49,7 +49,7 @@ public final class DisruptiveStormbrood extends OmenCard { // Destroy target creature with power 3 or less. Effect spellEffect = new DestroyTargetEffect(); this.getSpellCard().getSpellAbility().addEffect(spellEffect); - this.getSpellCard().getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellCard().getSpellAbility().addTarget(new TargetPermanent(filter)); this.finalizeOmen(); } diff --git a/Mage.Sets/src/mage/cards/d/DissensionInTheRanks.java b/Mage.Sets/src/mage/cards/d/DissensionInTheRanks.java index 5c3567832f9..0aea464bfd5 100644 --- a/Mage.Sets/src/mage/cards/d/DissensionInTheRanks.java +++ b/Mage.Sets/src/mage/cards/d/DissensionInTheRanks.java @@ -1,7 +1,5 @@ - package mage.cards.d; -import java.util.UUID; import mage.abilities.effects.common.FightTargetsEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -9,35 +7,31 @@ import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.other.AnotherTargetPredicate; import mage.filter.predicate.permanent.BlockingPredicate; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class DissensionInTheRanks extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("blocking creature"); + private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("another target blocking creature"); static { filter.add(BlockingPredicate.instance); + filter2.add(new AnotherTargetPredicate(2)); + filter2.add(BlockingPredicate.instance); } public DissensionInTheRanks(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{R}{R}"); // Target blocking creature fights another target blocking creature. this.getSpellAbility().addEffect(new FightTargetsEffect(false)); - TargetCreaturePermanent target = new TargetCreaturePermanent(1, 1, filter, false); - target.setTargetTag(1); - this.getSpellAbility().addTarget(target); - - FilterCreaturePermanent filter2 = new FilterCreaturePermanent("another target blocking creature"); - filter2.add(new AnotherTargetPredicate(2)); - filter2.add(BlockingPredicate.instance); - TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter2); - target2.setTargetTag(2); - this.getSpellAbility().addTarget(target2); + this.getSpellAbility().addTarget(new TargetPermanent(filter).setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPermanent(filter2).setTargetTag(2)); } private DissensionInTheRanks(final DissensionInTheRanks card) { diff --git a/Mage.Sets/src/mage/cards/d/DistinguishedConjurer.java b/Mage.Sets/src/mage/cards/d/DistinguishedConjurer.java index 3054e46f84f..8f8c8f9b45d 100644 --- a/Mage.Sets/src/mage/cards/d/DistinguishedConjurer.java +++ b/Mage.Sets/src/mage/cards/d/DistinguishedConjurer.java @@ -15,7 +15,7 @@ import mage.constants.SubType; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -45,7 +45,7 @@ public final class DistinguishedConjurer extends CardImpl { // {4}{W}, {T}: Exile another target creature you control, then return it to the battlefield under its owner’s control. Ability ability = new SimpleActivatedAbility(new ExileThenReturnTargetEffect(false, false), new ManaCostsImpl<>("{4}{W}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DiveBomber.java b/Mage.Sets/src/mage/cards/d/DiveBomber.java index a0e9813d5dd..b03c80744ef 100644 --- a/Mage.Sets/src/mage/cards/d/DiveBomber.java +++ b/Mage.Sets/src/mage/cards/d/DiveBomber.java @@ -15,6 +15,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterAttackingOrBlockingCreature; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -35,7 +36,7 @@ public final class DiveBomber extends CardImpl { // {tap}, Sacrifice Dive Bomber: Dive Bomber deals 2 damage to target attacking or blocking creature. Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(2, "it"), new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(new FilterAttackingOrBlockingCreature())); + ability.addTarget(new TargetPermanent(new FilterAttackingOrBlockingCreature())); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DivebomberGriffin.java b/Mage.Sets/src/mage/cards/d/DivebomberGriffin.java index 843b097a2f6..f5c4909ab4f 100644 --- a/Mage.Sets/src/mage/cards/d/DivebomberGriffin.java +++ b/Mage.Sets/src/mage/cards/d/DivebomberGriffin.java @@ -15,6 +15,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterAttackingOrBlockingCreature; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -34,7 +35,7 @@ public final class DivebomberGriffin extends CardImpl { // {tap}, Sacrifice Divebomber Griffin: Divebomber Griffin deals 3 damage to target attacking or blocking creature. Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(3, "it"), new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(new FilterAttackingOrBlockingCreature())); + ability.addTarget(new TargetPermanent(new FilterAttackingOrBlockingCreature())); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DivergentTransformations.java b/Mage.Sets/src/mage/cards/d/DivergentTransformations.java index 6ffb47fbddf..93adbb3d663 100644 --- a/Mage.Sets/src/mage/cards/d/DivergentTransformations.java +++ b/Mage.Sets/src/mage/cards/d/DivergentTransformations.java @@ -1,7 +1,5 @@ - package mage.cards.d; -import java.util.*; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; @@ -15,8 +13,9 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import java.util.*; + /** - * * @author LevelX2 */ public final class DivergentTransformations extends CardImpl { @@ -26,6 +25,7 @@ public final class DivergentTransformations extends CardImpl { // Undaunted this.addAbility(new UndauntedAbility()); + // Exile two target creatures. For each of those creatures, its controller reveals cards from the top of their library until they reveal a creature card, puts that card onto the battlefield, then shuffles the rest into their library. this.getSpellAbility().addEffect(new DivergentTransformationsEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent(2)); diff --git a/Mage.Sets/src/mage/cards/d/DiversionaryTactics.java b/Mage.Sets/src/mage/cards/d/DiversionaryTactics.java index 3cf25dae0ff..a988dfc5ef3 100644 --- a/Mage.Sets/src/mage/cards/d/DiversionaryTactics.java +++ b/Mage.Sets/src/mage/cards/d/DiversionaryTactics.java @@ -1,7 +1,5 @@ - package mage.cards.d; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapTargetCost; @@ -9,30 +7,28 @@ import mage.abilities.effects.common.TapTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.filter.StaticFilters; +import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * @author Loki */ public final class DiversionaryTactics extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); - - static { - filter.add(TappedPredicate.UNTAPPED); - } - public DiversionaryTactics(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}"); - Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new TapTargetCost(new TargetControlledCreaturePermanent(2, 2, filter, false))); + Ability ability = new SimpleActivatedAbility( + new TapTargetEffect(), + new TapTargetCost( + new TargetControlledPermanent(2, StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURES) + ) + ); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); - } private DiversionaryTactics(final DiversionaryTactics card) { diff --git a/Mage.Sets/src/mage/cards/d/DivineResilience.java b/Mage.Sets/src/mage/cards/d/DivineResilience.java index 58b3d0b1272..9c7cd13dd52 100644 --- a/Mage.Sets/src/mage/cards/d/DivineResilience.java +++ b/Mage.Sets/src/mage/cards/d/DivineResilience.java @@ -7,21 +7,18 @@ import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.StaticFilters; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.targetadjustment.ConditionalTargetAdjuster; import java.util.UUID; /** - * * @author ciaccona007 */ public final class DivineResilience extends CardImpl { public DivineResilience(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}"); - // Kicker {2}{W} this.addAbility(new KickerAbility("{2}{W}")); @@ -34,7 +31,7 @@ public final class DivineResilience extends CardImpl { this.getSpellAbility().setTargetAdjuster(new ConditionalTargetAdjuster( KickedCondition.ONCE, new TargetControlledCreaturePermanent(), - new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, StaticFilters.FILTER_CONTROLLED_CREATURES, false) + new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE) )); } diff --git a/Mage.Sets/src/mage/cards/d/DivineVerdict.java b/Mage.Sets/src/mage/cards/d/DivineVerdict.java index 4671f1054c1..1f40296ebc4 100644 --- a/Mage.Sets/src/mage/cards/d/DivineVerdict.java +++ b/Mage.Sets/src/mage/cards/d/DivineVerdict.java @@ -7,6 +7,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterAttackingOrBlockingCreature; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -19,7 +20,7 @@ public final class DivineVerdict extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{W}"); // Destroy target attacking or blocking creature. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterAttackingOrBlockingCreature())); + this.getSpellAbility().addTarget(new TargetPermanent(new FilterAttackingOrBlockingCreature())); this.getSpellAbility().addEffect(new DestroyTargetEffect()); } diff --git a/Mage.Sets/src/mage/cards/d/DizzyingGaze.java b/Mage.Sets/src/mage/cards/d/DizzyingGaze.java index 104cbca60a1..6a8e61e8df0 100644 --- a/Mage.Sets/src/mage/cards/d/DizzyingGaze.java +++ b/Mage.Sets/src/mage/cards/d/DizzyingGaze.java @@ -50,7 +50,7 @@ public final class DizzyingGaze extends CardImpl { // {R}: Enchanted creature deals 1 damage to target creature with flying. Ability ability2 = new SimpleActivatedAbility(new DamageTargetEffect(1), new ManaCostsImpl<>("{R}")); - ability2.addTarget(new TargetCreaturePermanent(filter)); + ability2.addTarget(new TargetPermanent(filter)); this.addAbility(new SimpleStaticAbility( new GainAbilityAttachedEffect( ability2, diff --git a/Mage.Sets/src/mage/cards/d/DjinnOfInfiniteDeceits.java b/Mage.Sets/src/mage/cards/d/DjinnOfInfiniteDeceits.java index 204e8a8bf80..1bab6cf6e2e 100644 --- a/Mage.Sets/src/mage/cards/d/DjinnOfInfiniteDeceits.java +++ b/Mage.Sets/src/mage/cards/d/DjinnOfInfiniteDeceits.java @@ -1,10 +1,9 @@ - package mage.cards.d; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.IsPhaseCondition; import mage.abilities.costs.common.TapSourceCost; @@ -15,22 +14,25 @@ import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class DjinnOfInfiniteDeceits extends CardImpl { - private static final String rule = "Exchange control of two target nonlegendary creatures"; private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonlegendary creature"); + static { filter.add(Predicates.not(SuperType.LEGENDARY.getPredicate())); } + private static final Condition condition = new InvertCondition(new IsPhaseCondition(TurnPhase.COMBAT)); + public DjinnOfInfiniteDeceits(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.DJINN); this.power = new MageInt(2); @@ -38,13 +40,12 @@ public final class DjinnOfInfiniteDeceits extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); + // {tap}: Exchange control of two target nonlegendary creatures. You can't activate this ability during combat. - Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, - new ExchangeControlTargetEffect(Duration.EndOfGame, rule), - new TapSourceCost(), - new InvertCondition(new IsPhaseCondition(TurnPhase.COMBAT))); - ability.addTarget(new TargetCreaturePermanent(2,2, filter, false)); + Ability ability = new ActivateIfConditionActivatedAbility(new ExchangeControlTargetEffect( + Duration.EndOfGame, "exchange control of two target nonlegendary creatures" + ), new TapSourceCost(), condition); + ability.addTarget(new TargetPermanent(2, filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DoOrDie.java b/Mage.Sets/src/mage/cards/d/DoOrDie.java index 0b95336936b..3eb90a3df48 100644 --- a/Mage.Sets/src/mage/cards/d/DoOrDie.java +++ b/Mage.Sets/src/mage/cards/d/DoOrDie.java @@ -12,21 +12,20 @@ import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.TargetPlayer; -import mage.target.common.TargetCreaturePermanent; import java.util.ArrayList; import java.util.List; import java.util.UUID; /** - * * @author fireshoes */ public final class DoOrDie extends CardImpl { public DoOrDie(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}"); // Separate all creatures target player controls into two piles. Destroy all creatures in the pile of that player's choice. They can't be regenerated. this.getSpellAbility().addEffect(new DoOrDieEffect()); @@ -68,7 +67,7 @@ class DoOrDieEffect extends OneShotEffect { } FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures to put in the first pile"); filter.add(new ControllerIdPredicate(targetPlayer.getId())); - TargetCreaturePermanent creatures = new TargetCreaturePermanent(0, Integer.MAX_VALUE, filter, true); + TargetPermanent creatures = new TargetPermanent(0, Integer.MAX_VALUE, filter, true); List pile1 = new ArrayList<>(); if (player.choose(Outcome.Neutral, creatures, source, game)) { List targets = creatures.getTargets(); diff --git a/Mage.Sets/src/mage/cards/d/DoggedHunter.java b/Mage.Sets/src/mage/cards/d/DoggedHunter.java index bed092c443d..57204e79ed1 100644 --- a/Mage.Sets/src/mage/cards/d/DoggedHunter.java +++ b/Mage.Sets/src/mage/cards/d/DoggedHunter.java @@ -14,6 +14,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TokenPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -37,7 +38,7 @@ public final class DoggedHunter extends CardImpl { // {tap}: Destroy target creature token. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/Dominate.java b/Mage.Sets/src/mage/cards/d/Dominate.java index b8b10c2bf99..7f7559415b8 100644 --- a/Mage.Sets/src/mage/cards/d/Dominate.java +++ b/Mage.Sets/src/mage/cards/d/Dominate.java @@ -7,6 +7,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.Duration; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetadjustment.XManaValueTargetAdjuster; @@ -22,7 +23,7 @@ public final class Dominate extends CardImpl { // Gain control of target creature with converted mana cost X or less. this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.Custom, true)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature with mana value X or less"))); + this.getSpellAbility().addTarget(new TargetPermanent(new FilterCreaturePermanent("creature with mana value X or less"))); this.getSpellAbility().setTargetAdjuster(new XManaValueTargetAdjuster(ComparisonType.OR_LESS)); } diff --git a/Mage.Sets/src/mage/cards/d/DominatingVampire.java b/Mage.Sets/src/mage/cards/d/DominatingVampire.java index 08825f5dafd..c32d45efb8d 100644 --- a/Mage.Sets/src/mage/cards/d/DominatingVampire.java +++ b/Mage.Sets/src/mage/cards/d/DominatingVampire.java @@ -19,6 +19,7 @@ import mage.filter.predicate.ObjectSourcePlayer; import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -46,7 +47,7 @@ public final class DominatingVampire extends CardImpl { Ability ability = new EntersBattlefieldTriggeredAbility(new GainControlTargetEffect(Duration.EndOfTurn)); ability.addEffect(new UntapTargetEffect().setText("Untap that creature")); ability.addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn, "It gains haste until end of turn")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/Domineer.java b/Mage.Sets/src/mage/cards/d/Domineer.java index e41877951dc..56343d37c6a 100644 --- a/Mage.Sets/src/mage/cards/d/Domineer.java +++ b/Mage.Sets/src/mage/cards/d/Domineer.java @@ -34,7 +34,7 @@ public final class Domineer extends CardImpl { this.subtype.add(SubType.AURA); // Enchant artifact creature - TargetPermanent auraTarget = new TargetCreaturePermanent(filter); + TargetPermanent auraTarget = new TargetPermanent(filter); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.GainControl)); Ability ability = new EnchantAbility(auraTarget); diff --git a/Mage.Sets/src/mage/cards/d/DomineeringWill.java b/Mage.Sets/src/mage/cards/d/DomineeringWill.java index 50e0a160ae4..f003a3215e4 100644 --- a/Mage.Sets/src/mage/cards/d/DomineeringWill.java +++ b/Mage.Sets/src/mage/cards/d/DomineeringWill.java @@ -1,7 +1,5 @@ - package mage.cards.d; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.Effect; @@ -20,12 +18,13 @@ import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.AttackingPredicate; import mage.game.Game; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.TargetPlayer; -import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.SecondTargetPointer; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class DomineeringWill extends CardImpl { @@ -37,13 +36,12 @@ public final class DomineeringWill extends CardImpl { } public DomineeringWill(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{U}"); // Target player gains control of up to three target nonattacking creatures until end of turn. Untap those creatures. They block this turn if able. this.getSpellAbility().addEffect(new DomineeringWillEffect()); this.getSpellAbility().addTarget(new TargetPlayer()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 3, filter, false)); - + this.getSpellAbility().addTarget(new TargetPermanent(0, 3, filter)); } private DomineeringWill(final DomineeringWill card) { diff --git a/Mage.Sets/src/mage/cards/d/DomriRade.java b/Mage.Sets/src/mage/cards/d/DomriRade.java index 5e1f5f38d5c..004167705ec 100644 --- a/Mage.Sets/src/mage/cards/d/DomriRade.java +++ b/Mage.Sets/src/mage/cards/d/DomriRade.java @@ -11,15 +11,16 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.cards.CardsImpl; import mage.constants.*; -import mage.filter.StaticFilters; import mage.game.Game; import mage.game.command.emblems.DomriRadeEmblem; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2; + /** * @author LevelX2 */ @@ -36,15 +37,10 @@ public final class DomriRade extends CardImpl { this.addAbility(new LoyaltyAbility(new DomriRadeEffect1(), 1)); // -2: Target creature you control fights another target creature. - LoyaltyAbility ability2 = new LoyaltyAbility(new FightTargetsEffect(false), -2); - TargetControlledCreaturePermanent target = new TargetControlledCreaturePermanent(); - target.setTargetTag(1); - ability2.addTarget(target); - - TargetCreaturePermanent target2 = new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2); - target2.setTargetTag(2); - ability2.addTarget(target2); - this.addAbility(ability2); + LoyaltyAbility ability = new LoyaltyAbility(new FightTargetsEffect(false), -2); + ability.addTarget(new TargetControlledCreaturePermanent().setTargetTag(1)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_CREATURE_TARGET_2).setTargetTag(2)); + this.addAbility(ability); // -7: You get an emblem with "Creatures you control have double strike, trample, hexproof and haste." this.addAbility(new LoyaltyAbility(new GetEmblemEffect(new DomriRadeEmblem()), -7)); diff --git a/Mage.Sets/src/mage/cards/d/DomrisNodorog.java b/Mage.Sets/src/mage/cards/d/DomrisNodorog.java index 2c289dd233a..61c39fd1411 100644 --- a/Mage.Sets/src/mage/cards/d/DomrisNodorog.java +++ b/Mage.Sets/src/mage/cards/d/DomrisNodorog.java @@ -18,7 +18,7 @@ import java.util.UUID; */ public final class DomrisNodorog extends CardImpl { - private static final FilterCard filter = new FilterCard("card named Domri, City Smasher"); + private static final FilterCard filter = new FilterCard("a card named Domri, City Smasher"); static { filter.add(new NamePredicate("Domri, City Smasher")); diff --git a/Mage.Sets/src/mage/cards/d/DongZhouTheTyrant.java b/Mage.Sets/src/mage/cards/d/DongZhouTheTyrant.java index c54bc1bc11f..01648c0600c 100644 --- a/Mage.Sets/src/mage/cards/d/DongZhouTheTyrant.java +++ b/Mage.Sets/src/mage/cards/d/DongZhouTheTyrant.java @@ -11,10 +11,13 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * @author fireshoes */ @@ -30,7 +33,7 @@ public final class DongZhouTheTyrant extends CardImpl { // When Dong Zhou, the Tyrant enters the battlefield, target creature an opponent controls deals damage equal to its power to that player. Ability ability = new EntersBattlefieldTriggeredAbility(new DongZhouTheTyrantEffect(), false); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DoomBlade.java b/Mage.Sets/src/mage/cards/d/DoomBlade.java index e406967e20d..1cd2e858779 100644 --- a/Mage.Sets/src/mage/cards/d/DoomBlade.java +++ b/Mage.Sets/src/mage/cards/d/DoomBlade.java @@ -6,8 +6,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author LokiX @@ -17,7 +20,7 @@ public final class DoomBlade extends CardImpl { public DoomBlade(UUID ownerId, CardSetInfo setInfo){ super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{B}"); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); } diff --git a/Mage.Sets/src/mage/cards/d/Downsize.java b/Mage.Sets/src/mage/cards/d/Downsize.java index 197021b8205..96c802234f5 100644 --- a/Mage.Sets/src/mage/cards/d/Downsize.java +++ b/Mage.Sets/src/mage/cards/d/Downsize.java @@ -9,10 +9,13 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author LevelX2 */ @@ -22,7 +25,7 @@ public final class Downsize extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}"); // Target creature you don't control gets -4/-0 until end of turn. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.getSpellAbility().addEffect(new BoostTargetEffect(-4, 0, Duration.EndOfTurn)); // Overload {2}{U} (You may cast this spell for its overload cost. If you do, change its text by replacing all instances of "target" with "each.") diff --git a/Mage.Sets/src/mage/cards/d/DrEggman.java b/Mage.Sets/src/mage/cards/d/DrEggman.java new file mode 100644 index 00000000000..50dd35f2378 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DrEggman.java @@ -0,0 +1,93 @@ +package mage.cards.d; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.FaceVillainousChoiceOpponentsEffect; +import mage.abilities.effects.common.PutCardFromHandOntoBattlefieldEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.choices.FaceVillainousChoice; +import mage.choices.VillainousChoice; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicates; +import mage.game.Game; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class DrEggman extends CardImpl { + + private static final FaceVillainousChoice choice = new FaceVillainousChoice( + Outcome.Discard, new DrEggmanFirstChoice(), new DrEggmanSecondChoice() + ); + + public DrEggman(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{B}{R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SCIENTIST); + this.power = new MageInt(3); + this.toughness = new MageInt(6); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // At the beginning of your end step, draw a card. Then each opponent faces a villainous choice -- That player discards a card, or you may put a Construct, Robot, or Vehicle card from your hand onto the battlefield. + Ability ability = new BeginningOfEndStepTriggeredAbility(new DrawCardSourceControllerEffect(1)); + ability.addEffect(new FaceVillainousChoiceOpponentsEffect(choice).concatBy("Then")); + this.addAbility(ability); + } + + private DrEggman(final DrEggman card) { + super(card); + } + + @Override + public DrEggman copy() { + return new DrEggman(this); + } +} + +class DrEggmanFirstChoice extends VillainousChoice { + DrEggmanFirstChoice() { + super("That player discards a card", "Discard a card"); + } + + @Override + public boolean doChoice(Player player, Game game, Ability source) { + return !player.discard(1, false, false, source, game).isEmpty(); + } +} + +class DrEggmanSecondChoice extends VillainousChoice { + private static final FilterCard filter = new FilterCard("Construct, Robot, or Vehicle card"); + + static { + filter.add(Predicates.or( + SubType.CONSTRUCT.getPredicate(), + SubType.ROBOT.getPredicate(), + SubType.VEHICLE.getPredicate() + )); + } + + DrEggmanSecondChoice() { + super("you may put a Construct, Robot, or Vehicle card from your hand onto the battlefield", + "{controller} may put a Construct, Robot, or Vehicle card from their hand onto the battlefield"); + } + + @Override + public boolean doChoice(Player player, Game game, Ability source) { + return new PutCardFromHandOntoBattlefieldEffect(filter).apply(game, source); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DragonGrip.java b/Mage.Sets/src/mage/cards/d/DragonGrip.java index 3cf21d87ea0..135ff97830f 100644 --- a/Mage.Sets/src/mage/cards/d/DragonGrip.java +++ b/Mage.Sets/src/mage/cards/d/DragonGrip.java @@ -34,8 +34,7 @@ public final class DragonGrip extends CardImpl { AsThoughEffect effect = new CastAsThoughItHadFlashSourceEffect(Duration.EndOfGame); this.addAbility(new SimpleStaticAbility(Zone.ALL, new ConditionalAsThoughEffect(effect, 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)); + + "you may cast this spell as though it had flash")).addHint(FerociousHint.instance)); // Enchant creature TargetPermanent auraTarget = new TargetCreaturePermanent(); diff --git a/Mage.Sets/src/mage/cards/d/DragonScarredBear.java b/Mage.Sets/src/mage/cards/d/DragonScarredBear.java index 116d6ad24df..8c842f767e3 100644 --- a/Mage.Sets/src/mage/cards/d/DragonScarredBear.java +++ b/Mage.Sets/src/mage/cards/d/DragonScarredBear.java @@ -1,9 +1,6 @@ - package mage.cards.d; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.common.FormidableCondition; import mage.abilities.costs.mana.ManaCostsImpl; @@ -13,28 +10,24 @@ import mage.cards.CardSetInfo; import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class DragonScarredBear extends CardImpl { public DragonScarredBear(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); this.subtype.add(SubType.BEAR); this.power = new MageInt(3); this.toughness = new MageInt(2); // Formidable — {1}{G}: Regenerate Dragon-Scarred Bear. Activate this only if creatures you control have total power 8 or greater. - Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, - new RegenerateSourceEffect(), - new ManaCostsImpl<>("{1}{G}"), - FormidableCondition.instance); - ability.setAbilityWord(AbilityWord.FORMIDABLE); - this.addAbility(ability); + this.addAbility(new ActivateIfConditionActivatedAbility( + new RegenerateSourceEffect(), new ManaCostsImpl<>("{1}{G}"), FormidableCondition.instance + ).setAbilityWord(AbilityWord.FORMIDABLE)); } private DragonScarredBear(final DragonScarredBear card) { diff --git a/Mage.Sets/src/mage/cards/d/DragonTempest.java b/Mage.Sets/src/mage/cards/d/DragonTempest.java index fa9ce3d15a6..bc1be2dfc26 100644 --- a/Mage.Sets/src/mage/cards/d/DragonTempest.java +++ b/Mage.Sets/src/mage/cards/d/DragonTempest.java @@ -1,8 +1,7 @@ package mage.cards.d; import mage.abilities.Ability; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; -import mage.abilities.effects.Effect; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.FlyingAbility; @@ -10,8 +9,9 @@ import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterControlledPermanent; -import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; import mage.game.Game; import mage.game.permanent.Permanent; @@ -25,31 +25,27 @@ import java.util.UUID; */ public final class DragonTempest extends CardImpl { - private static final FilterCreaturePermanent filterFlying = new FilterCreaturePermanent("a creature with flying"); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("a creature you control with flying"); + private static final FilterPermanent filter2 = new FilterControlledPermanent(SubType.DRAGON, "a Dragon you control"); static { - filterFlying.add(new AbilityPredicate(FlyingAbility.class)); + filter.add(new AbilityPredicate(FlyingAbility.class)); } public DragonTempest(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}"); // Whenever a creature with flying you control enters, it gains haste until the end of turn. - Effect effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn); - effect.setText("it gains haste until end of turn"); - this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, effect, filterFlying, false, SetTargetPointer.PERMANENT)); + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + Zone.BATTLEFIELD, new GainAbilityTargetEffect(HasteAbility.getInstance()) + .setText("it gains haste until end of turn"), + filter, false, SetTargetPointer.PERMANENT + )); // Whenever a Dragon you control enters, it deals X damage to any target, where X is the number of Dragons you control. - Ability ability = new EntersBattlefieldControlledTriggeredAbility( - Zone.BATTLEFIELD, - new DragonTempestDamageEffect(), - new FilterCreaturePermanent(SubType.DRAGON, "a Dragon"), - false, - SetTargetPointer.NONE - ); + Ability ability = new EntersBattlefieldAllTriggeredAbility(new DragonTempestDamageEffect(), filter2); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); - } private DragonTempest(final DragonTempest card) { diff --git a/Mage.Sets/src/mage/cards/d/DragonWhisperer.java b/Mage.Sets/src/mage/cards/d/DragonWhisperer.java index a747b2246f4..84cf4f1273b 100644 --- a/Mage.Sets/src/mage/cards/d/DragonWhisperer.java +++ b/Mage.Sets/src/mage/cards/d/DragonWhisperer.java @@ -1,9 +1,6 @@ - package mage.cards.d; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.FormidableCondition; @@ -16,42 +13,38 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AbilityWord; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; import mage.game.permanent.token.DragonToken; +import java.util.UUID; + /** - * * @author fireshoes */ public final class DragonWhisperer extends CardImpl { public DragonWhisperer(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}{R}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.SHAMAN); this.power = new MageInt(2); this.toughness = new MageInt(2); // {R}: Dragon Whisperer gains flying until end of turn. - this.addAbility(new SimpleActivatedAbility( - new GainAbilitySourceEffect(FlyingAbility.getInstance(), - Duration.EndOfTurn), new ManaCostsImpl<>("{R}"))); - + this.addAbility(new SimpleActivatedAbility(new GainAbilitySourceEffect( + FlyingAbility.getInstance(), Duration.EndOfTurn + ), new ManaCostsImpl<>("{R}"))); + // {1}{R}: Dragon Whisperer get +1/+0 until end of turn this.addAbility(new SimpleActivatedAbility( - new BoostSourceEffect(1, 0, Duration.EndOfTurn), - new ManaCostsImpl<>("{1}{R}"))); - + new BoostSourceEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl<>("{1}{R}") + )); + // — {4}{R}{R}: Create a 4/4 red Dragon creature token with flying. Activate this ability only if creatures you control have total power 8 or greater. - Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, - new CreateTokenEffect(new DragonToken()), - new ManaCostsImpl<>("{4}{R}{R}"), - FormidableCondition.instance); - ability.setAbilityWord(AbilityWord.FORMIDABLE); - this.addAbility(ability); + this.addAbility(new ActivateIfConditionActivatedAbility( + new CreateTokenEffect(new DragonToken()), new ManaCostsImpl<>("{4}{R}{R}"), FormidableCondition.instance + ).setAbilityWord(AbilityWord.FORMIDABLE)); } private DragonWhisperer(final DragonWhisperer card) { diff --git a/Mage.Sets/src/mage/cards/d/DragonloftIdol.java b/Mage.Sets/src/mage/cards/d/DragonloftIdol.java index 805fe54d118..1ce9f55bc99 100644 --- a/Mage.Sets/src/mage/cards/d/DragonloftIdol.java +++ b/Mage.Sets/src/mage/cards/d/DragonloftIdol.java @@ -1,7 +1,6 @@ package mage.cards.d; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -14,9 +13,14 @@ import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +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 LevelX2 @@ -38,9 +42,9 @@ public final class DragonloftIdol extends CardImpl { // As long as you control a Dragon, Dragonloft Idol gets +1/+1 and has flying and trample. - Effect effect = new ConditionalContinuousEffect(new BoostSourceEffect(1,1, Duration.WhileOnBattlefield), + Effect effect = new ConditionalContinuousEffect(new BoostSourceEffect(1, 1, Duration.WhileOnBattlefield), new PermanentsOnTheBattlefieldCondition(filter), - "As long as you control a Dragon, Dragonloft Idol gets +1/+1"); + "As long as you control a Dragon, {this} gets +1/+1"); Ability ability = new SimpleStaticAbility(effect); effect = new ConditionalContinuousEffect(new GainAbilitySourceEffect(FlyingAbility.getInstance()), new PermanentsOnTheBattlefieldCondition(filter), diff --git a/Mage.Sets/src/mage/cards/d/DrainingWhelk.java b/Mage.Sets/src/mage/cards/d/DrainingWhelk.java index fa73344bb77..f5b8454e477 100644 --- a/Mage.Sets/src/mage/cards/d/DrainingWhelk.java +++ b/Mage.Sets/src/mage/cards/d/DrainingWhelk.java @@ -1,7 +1,6 @@ package mage.cards.d; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -18,6 +17,8 @@ import mage.game.Game; import mage.game.stack.Spell; import mage.target.TargetSpell; +import java.util.UUID; + /** * * @author emerald000 @@ -57,7 +58,7 @@ class DrainingWhelkEffect extends CounterTargetEffect { DrainingWhelkEffect() { super(); - staticText = "counter target spell. Put X +1/+1 counters on Draining Whelk, where X is that spell's mana value"; + staticText = "counter target spell. Put X +1/+1 counters on {this}, where X is that spell's mana value"; } private DrainingWhelkEffect(final DrainingWhelkEffect effect) { diff --git a/Mage.Sets/src/mage/cards/d/DreadWanderer.java b/Mage.Sets/src/mage/cards/d/DreadWanderer.java index 892f355ce9a..b6d521ebb53 100644 --- a/Mage.Sets/src/mage/cards/d/DreadWanderer.java +++ b/Mage.Sets/src/mage/cards/d/DreadWanderer.java @@ -1,11 +1,10 @@ package mage.cards.d; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTappedAbility; import mage.abilities.condition.common.HeckbentCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -14,8 +13,9 @@ import mage.constants.SubType; import mage.constants.TimingRule; import mage.constants.Zone; +import java.util.UUID; + /** - * * @author fireshoes */ public final class DreadWanderer extends CardImpl { @@ -33,17 +33,10 @@ public final class DreadWanderer extends CardImpl { // {2}{B}: Return Dread Wanderer from your graveyard to the battlefield. // Activate this ability only any time you could cast a sorcery and only if you have one or fewer cards in hand. - ConditionalActivatedAbility ability = new ConditionalActivatedAbility( - Zone.GRAVEYARD, - new ReturnSourceFromGraveyardToBattlefieldEffect(), - new ManaCostsImpl<>("{2}{B}"), - HeckbentCondition.instance, - "{2}{B}: Return {this} from your graveyard to the battlefield. " - + "Activate only as a sorcery " - + "and only if you have one or fewer cards in hand." - ); - ability.setTiming(TimingRule.SORCERY); - addAbility(ability); + this.addAbility(new ActivateIfConditionActivatedAbility( + Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldEffect(), + new ManaCostsImpl<>("{2}{B}"), HeckbentCondition.instance + ).setTiming(TimingRule.SORCERY)); } private DreadWanderer(final DreadWanderer card) { diff --git a/Mage.Sets/src/mage/cards/d/DreadlightMonstrosity.java b/Mage.Sets/src/mage/cards/d/DreadlightMonstrosity.java index b4cdbe27ed4..b39e5a84055 100644 --- a/Mage.Sets/src/mage/cards/d/DreadlightMonstrosity.java +++ b/Mage.Sets/src/mage/cards/d/DreadlightMonstrosity.java @@ -14,7 +14,6 @@ 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 java.util.Collection; @@ -25,10 +24,6 @@ import java.util.UUID; */ public final class DreadlightMonstrosity extends CardImpl { - private static final Hint hint = new ConditionHint( - DreadlightMonstrosityCondition.instance, "You own a card in exile" - ); - public DreadlightMonstrosity(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}{U}"); @@ -42,9 +37,9 @@ public final class DreadlightMonstrosity extends CardImpl { // {3}{U}{U}: Dreadlight Monstrosity can't be blocked this turn. Activate only if you own a card in exile. this.addAbility(new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new CantBeBlockedSourceEffect(Duration.EndOfTurn), + new CantBeBlockedSourceEffect(Duration.EndOfTurn), new ManaCostsImpl<>("{3}{U}{U}"), DreadlightMonstrosityCondition.instance - ).addHint(hint)); + ).addHint(DreadlightMonstrosityCondition.getHint())); } private DreadlightMonstrosity(final DreadlightMonstrosity card) { @@ -59,6 +54,11 @@ public final class DreadlightMonstrosity extends CardImpl { enum DreadlightMonstrosityCondition implements Condition { instance; + private static final Hint hint = new ConditionHint(instance); + + public static Hint getHint() { + return hint; + } @Override public boolean apply(Game game, Ability source) { @@ -75,4 +75,4 @@ enum DreadlightMonstrosityCondition implements Condition { public String toString() { return "you own a card in exile"; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/d/DreamTides.java b/Mage.Sets/src/mage/cards/d/DreamTides.java index 72ba7428972..bf72a5e91b0 100644 --- a/Mage.Sets/src/mage/cards/d/DreamTides.java +++ b/Mage.Sets/src/mage/cards/d/DreamTides.java @@ -2,14 +2,17 @@ package mage.cards.d; import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.Cost; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DontUntapInControllersUntapStepAllEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.Predicates; @@ -19,7 +22,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import mage.util.ManaUtil; import java.util.UUID; @@ -74,25 +77,25 @@ class DreamTidesEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if (player != null && sourcePermanent != null) { - int countBattlefield = game.getBattlefield().getAllActivePermanents(filter, game.getActivePlayerId(), game).size(); - while (player.canRespond() && countBattlefield > 0 && player.chooseUse(Outcome.AIDontUseIt, "Pay {2} and untap a tapped nongreen creature under your control?", source, game)) { - Target tappedCreatureTarget = new TargetControlledCreaturePermanent(1, 1, filter, true); - if (player.choose(Outcome.Detriment, tappedCreatureTarget, source, game)) { - Cost cost = ManaUtil.createManaCost(2, false); - Permanent tappedCreature = game.getPermanent(tappedCreatureTarget.getFirstTarget()); - - if (cost.pay(source, game, source, player.getId(), false)) { - tappedCreature.untap(game); - } - } - countBattlefield = game.getBattlefield().getAllActivePermanents(filter, game.getActivePlayerId(), game).size(); - } - return true; + if (player == null || sourcePermanent == null) { + return false; } - return false; + int countBattlefield = game.getBattlefield().getAllActivePermanents(filter, game.getActivePlayerId(), game).size(); + while (player.canRespond() && countBattlefield > 0 && player.chooseUse(Outcome.AIDontUseIt, "Pay {2} and untap a tapped nongreen creature under your control?", source, game)) { + Target tappedCreatureTarget = new TargetPermanent(filter); + tappedCreatureTarget.withNotTarget(true); + if (player.choose(Outcome.Detriment, tappedCreatureTarget, source, game)) { + Cost cost = ManaUtil.createManaCost(2, false); + Permanent tappedCreature = game.getPermanent(tappedCreatureTarget.getFirstTarget()); + + if (cost.pay(source, game, source, player.getId(), false)) { + tappedCreature.untap(game); + } + } + countBattlefield = game.getBattlefield().getAllActivePermanents(filter, game.getActivePlayerId(), game).size(); + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/d/DregsOfSorrow.java b/Mage.Sets/src/mage/cards/d/DregsOfSorrow.java index 55c1aeb8995..f48a9fbd379 100644 --- a/Mage.Sets/src/mage/cards/d/DregsOfSorrow.java +++ b/Mage.Sets/src/mage/cards/d/DregsOfSorrow.java @@ -7,11 +7,14 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetadjustment.XTargetsCountAdjuster; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURES_NON_BLACK; + /** * @author LevelX2 */ @@ -23,7 +26,7 @@ public final class DregsOfSorrow extends CardImpl { // Destroy X target nonblack creatures. Draw X cards. this.getSpellAbility().addEffect(new DestroyTargetEffect("Destroy X target nonblack creatures")); this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(GetXValue.instance)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURES_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURES_NON_BLACK)); this.getSpellAbility().setTargetAdjuster(new XTargetsCountAdjuster()); } diff --git a/Mage.Sets/src/mage/cards/d/DressDown.java b/Mage.Sets/src/mage/cards/d/DressDown.java index cba8de87977..990cd029159 100644 --- a/Mage.Sets/src/mage/cards/d/DressDown.java +++ b/Mage.Sets/src/mage/cards/d/DressDown.java @@ -1,23 +1,22 @@ package mage.cards.d; -import java.util.UUID; - import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.effects.common.continuous.LoseAllAbilitiesAllEffect; import mage.abilities.keyword.FlashAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; +import mage.constants.TargetController; import mage.filter.StaticFilters; -import mage.game.events.GameEvent; + +import java.util.UUID; /** - * * @author weirddan455 */ public final class DressDown extends CardImpl { @@ -32,12 +31,13 @@ public final class DressDown extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1))); // Creatures lose all abilities. - this.addAbility(new SimpleStaticAbility(new LoseAllAbilitiesAllEffect(StaticFilters.FILTER_PERMANENT_CREATURES, Duration.WhileOnBattlefield))); + this.addAbility(new SimpleStaticAbility(new LoseAllAbilitiesAllEffect( + StaticFilters.FILTER_PERMANENT_CREATURES, Duration.WhileOnBattlefield + ))); // At the beginning of the end step, sacrifice Dress Down. - this.addAbility(new OnEventTriggeredAbility( - GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", - true, new SacrificeSourceEffect() + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.NEXT, new SacrificeSourceEffect(), false )); } diff --git a/Mage.Sets/src/mage/cards/d/DromokaDunecaster.java b/Mage.Sets/src/mage/cards/d/DromokaDunecaster.java index 95038c35611..865042b51f0 100644 --- a/Mage.Sets/src/mage/cards/d/DromokaDunecaster.java +++ b/Mage.Sets/src/mage/cards/d/DromokaDunecaster.java @@ -16,6 +16,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class DromokaDunecaster extends CardImpl { // {1}{W}, {T}: Tap target creature without flying. SimpleActivatedAbility ability = new SimpleActivatedAbility(new TapTargetEffect(), new ManaCostsImpl<>("{1}{W}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DromokasCommand.java b/Mage.Sets/src/mage/cards/d/DromokasCommand.java index dc7a823495e..bae49454683 100644 --- a/Mage.Sets/src/mage/cards/d/DromokasCommand.java +++ b/Mage.Sets/src/mage/cards/d/DromokasCommand.java @@ -15,6 +15,7 @@ import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterEnchantmentPermanent; import mage.filter.common.FilterInstantOrSorcerySpell; +import mage.target.TargetPermanent; import mage.target.TargetPlayer; import mage.target.TargetSpell; import mage.target.common.TargetControlledCreaturePermanent; @@ -22,6 +23,8 @@ import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author jeffwadsworth */ @@ -53,7 +56,7 @@ public final class DromokasCommand extends CardImpl { effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance()); effect.setText("Put a +1/+1 counter on target creature"); mode = new Mode(effect); - mode.addTarget(new TargetCreaturePermanent(filterCreature)); + mode.addTarget(new TargetPermanent(filterCreature)); this.getSpellAbility().getModes().addMode(mode); // or Target creature you control fights target creature you don't control. @@ -61,7 +64,7 @@ public final class DromokasCommand extends CardImpl { effect.setText("Target creature you control fights target creature you don't control"); mode = new Mode(effect); mode.addTarget(new TargetControlledCreaturePermanent()); - mode.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + mode.addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.getSpellAbility().getModes().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/d/DroolingGroodion.java b/Mage.Sets/src/mage/cards/d/DroolingGroodion.java index 69eb9f6df0e..aeddf9fa34f 100644 --- a/Mage.Sets/src/mage/cards/d/DroolingGroodion.java +++ b/Mage.Sets/src/mage/cards/d/DroolingGroodion.java @@ -1,6 +1,5 @@ package mage.cards.d; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -12,12 +11,15 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.SecondTargetPointer; +import java.util.UUID; + +import static mage.filter.StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2; + /** - * * @author LevelX2 */ public final class DroolingGroodion extends CardImpl { @@ -31,19 +33,10 @@ public final class DroolingGroodion extends CardImpl { // {2}{B}{G}, Sacrifice a creature: Target creature gets +2/+2 until end of turn. Another target creature gets -2/-2 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(2, 2), new ManaCostsImpl<>("{2}{B}{G}")); - ability.addEffect(new BoostTargetEffect(-2, -2).setTargetPointer(new SecondTargetPointer())); ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_CREATURE)); - - TargetCreaturePermanent target = new TargetCreaturePermanent(); - target.setTargetTag(1); - target.withChooseHint("gets +2/+2"); - ability.addTarget(target); - - target = new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2); - target.setTargetTag(2); - target.withChooseHint("gets -2/-2"); - ability.addTarget(target); - + ability.addEffect(new BoostTargetEffect(-2, -2).setTargetPointer(new SecondTargetPointer())); + ability.addTarget(new TargetCreaturePermanent().setTargetTag(1).withChooseHint("gets +2/+2")); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_CREATURE_TARGET_2).setTargetTag(2).withChooseHint("gets -2/-2")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DropkickBomber.java b/Mage.Sets/src/mage/cards/d/DropkickBomber.java index 9d9a949ec8e..13086554ec7 100644 --- a/Mage.Sets/src/mage/cards/d/DropkickBomber.java +++ b/Mage.Sets/src/mage/cards/d/DropkickBomber.java @@ -15,16 +15,14 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; /** - * * @author ciaccona007 */ public final class DropkickBomber extends CardImpl { @@ -41,7 +39,7 @@ public final class DropkickBomber extends CardImpl { public DropkickBomber(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); - + this.subtype.add(SubType.GOBLIN); this.subtype.add(SubType.WARRIOR); this.power = new MageInt(2); @@ -67,7 +65,7 @@ public final class DropkickBomber extends CardImpl { Duration.EndOfTurn ).setText("and \"When this creature deals combat damage, sacrifice it.\"") ); - ability.addTarget(new TargetControlledCreaturePermanent(filter2)); + ability.addTarget(new TargetPermanent(filter2)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DrunauCorpseTrawler.java b/Mage.Sets/src/mage/cards/d/DrunauCorpseTrawler.java index fa3b97a66e3..827cd6e99ae 100644 --- a/Mage.Sets/src/mage/cards/d/DrunauCorpseTrawler.java +++ b/Mage.Sets/src/mage/cards/d/DrunauCorpseTrawler.java @@ -18,8 +18,11 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.game.permanent.token.ZombieToken; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.constants.SubType.ZOMBIE; + /** * * @author LevelX2 @@ -37,7 +40,7 @@ public final class DrunauCorpseTrawler extends CardImpl { // {2}{B}: Target Zombie gains deathtouch until end of turn. Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(DeathtouchAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{2}{B}")); - ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent(SubType.ZOMBIE, "Zombie"))); + ability.addTarget(new TargetPermanent(new FilterCreaturePermanent(ZOMBIE, "Zombie"))); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DuelForDominance.java b/Mage.Sets/src/mage/cards/d/DuelForDominance.java index b7c8409769c..f72fbc629bf 100644 --- a/Mage.Sets/src/mage/cards/d/DuelForDominance.java +++ b/Mage.Sets/src/mage/cards/d/DuelForDominance.java @@ -11,11 +11,14 @@ import mage.constants.AbilityWord; import mage.constants.CardType; import mage.counters.CounterType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author xenohedron */ @@ -26,7 +29,7 @@ public final class DuelForDominance extends CardImpl { // Coven — Choose target creature you control and target creature you don't control. this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); // If you control three or more creatures with different powers, put a +1/+1 counter on the chosen creature you control. this.getSpellAbility().addEffect(new ConditionalOneShotEffect( new AddCountersTargetEffect(CounterType.P1P1.createInstance()), diff --git a/Mage.Sets/src/mage/cards/d/DuelistsHeritage.java b/Mage.Sets/src/mage/cards/d/DuelistsHeritage.java index b8ae9f11e06..47ccd3f0f27 100644 --- a/Mage.Sets/src/mage/cards/d/DuelistsHeritage.java +++ b/Mage.Sets/src/mage/cards/d/DuelistsHeritage.java @@ -14,6 +14,7 @@ import mage.constants.Zone; import mage.filter.common.FilterAttackingCreature; import mage.game.Game; import mage.game.events.GameEvent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -33,7 +34,7 @@ public final class DuelistsHeritage extends CardImpl { effect.setOutcome(Outcome.Benefit); Ability ability = new DuelistsHeritageTriggeredAbility( Zone.BATTLEFIELD, effect); - ability.addTarget(new TargetCreaturePermanent(new FilterAttackingCreature())); + ability.addTarget(new TargetPermanent(new FilterAttackingCreature())); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DugganPrivateDetective.java b/Mage.Sets/src/mage/cards/d/DugganPrivateDetective.java index f2f19b21ccf..b61a987a088 100644 --- a/Mage.Sets/src/mage/cards/d/DugganPrivateDetective.java +++ b/Mage.Sets/src/mage/cards/d/DugganPrivateDetective.java @@ -17,10 +17,13 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * @author Cguy7777 */ @@ -49,7 +52,7 @@ public final class DugganPrivateDetective extends CardImpl { new ManaCostsImpl<>("{1}{G}"), TimingRule.INSTANT); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); ability.withFlavorWord("The Most Important Punch in History"); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/Duneblast.java b/Mage.Sets/src/mage/cards/d/Duneblast.java index 606fdd89e55..618331f9450 100644 --- a/Mage.Sets/src/mage/cards/d/Duneblast.java +++ b/Mage.Sets/src/mage/cards/d/Duneblast.java @@ -1,8 +1,5 @@ - package mage.cards.d; -import java.util.Objects; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; @@ -10,26 +7,24 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; import mage.filter.StaticFilters; -import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class Duneblast extends CardImpl { public Duneblast(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{W}{B}{G}"); - + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{W}{B}{G}"); // Choose up to one creature. Destroy the rest. this.getSpellAbility().addEffect(new DuneblastEffect()); - } private Duneblast(final Duneblast card) { @@ -61,20 +56,22 @@ class DuneblastEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Target target = new TargetCreaturePermanent(0,1,new FilterCreaturePermanent("creature to keep"), true); - target.setRequired(true); - Permanent creatureToKeep = null; - if (controller.choose(outcome, target, source, game)) { - creatureToKeep = game.getPermanent(target.getFirstTarget()); - } - for(Permanent creature: game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURES, source.getControllerId(), source, game)) { - if (!Objects.equals(creature, creatureToKeep)) { - creature.destroy(source, game, false); - } - } - return true; + if (controller == null) { + return false; } - return false; + Target target = new TargetCreaturePermanent(0, 1); + target.withNotTarget(true); + target.withChooseHint("to keep"); + target.setRequired(true); + controller.choose(outcome, target, source, game); + Permanent creatureToKeep = game.getPermanent(target.getFirstTarget()); + for (Permanent creature : game.getBattlefield().getActivePermanents( + StaticFilters.FILTER_PERMANENT_CREATURES, source.getControllerId(), source, game + )) { + if (!creature.equals(creatureToKeep)) { + creature.destroy(source, game, false); + } + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/d/DungeonDescent.java b/Mage.Sets/src/mage/cards/d/DungeonDescent.java index 265a5dde952..0598a7bd3c4 100644 --- a/Mage.Sets/src/mage/cards/d/DungeonDescent.java +++ b/Mage.Sets/src/mage/cards/d/DungeonDescent.java @@ -1,7 +1,5 @@ package mage.cards.d; -import java.util.UUID; - import mage.abilities.Ability; import mage.abilities.common.ActivateAsSorceryActivatedAbility; import mage.abilities.common.EntersBattlefieldTappedAbility; @@ -17,10 +15,10 @@ import mage.constants.CardType; import mage.constants.SuperType; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; /** - * * @author weirddan455 */ public final class DungeonDescent extends CardImpl { @@ -45,7 +43,7 @@ public final class DungeonDescent extends CardImpl { // {4}, {T}, Tap an untapped legendary creature you control: Venture into the dungeon. Activate only as a sorcery. Ability ability = new ActivateAsSorceryActivatedAbility(new VentureIntoTheDungeonEffect(), new GenericManaCost(4)); ability.addCost(new TapSourceCost()); - ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(filter))); + ability.addCost(new TapTargetCost(filter)); ability.addHint(CurrentDungeonHint.instance); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DungeonGeists.java b/Mage.Sets/src/mage/cards/d/DungeonGeists.java index f15cecd6eb5..166a2ceecfd 100644 --- a/Mage.Sets/src/mage/cards/d/DungeonGeists.java +++ b/Mage.Sets/src/mage/cards/d/DungeonGeists.java @@ -17,10 +17,13 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * @author BetaSteward */ @@ -38,7 +41,7 @@ public final class DungeonGeists extends CardImpl { // When Dungeon Geists enters the battlefield, tap target creature an opponent controls. That creature doesn't untap during its controller's untap step for as long as you control Dungeon Geists. Ability ability = new EntersBattlefieldTriggeredAbility(new TapTargetEffect(), false); ability.addEffect(new DontUntapInControllersUntapStepTargetEffect(Duration.WhileControlled)); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/Duplicant.java b/Mage.Sets/src/mage/cards/d/Duplicant.java index 96ba6d2ea3a..560300b7464 100644 --- a/Mage.Sets/src/mage/cards/d/Duplicant.java +++ b/Mage.Sets/src/mage/cards/d/Duplicant.java @@ -16,6 +16,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TokenPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.List; @@ -41,7 +42,7 @@ public final class Duplicant extends CardImpl { // Imprint - When Duplicant enters the battlefield, you may exile target nontoken creature. Ability ability = new EntersBattlefieldTriggeredAbility(new DuplicantExileTargetEffect(), true); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); ability.setAbilityWord(AbilityWord.IMPRINT); this.addAbility(ability); // As long as the exiled card is a creature card, Duplicant has that card's power, toughness, and creature types. It's still a Shapeshifter. diff --git a/Mage.Sets/src/mage/cards/d/DuskborneSkymarcher.java b/Mage.Sets/src/mage/cards/d/DuskborneSkymarcher.java index b8a3861e1ee..64243cd4b41 100644 --- a/Mage.Sets/src/mage/cards/d/DuskborneSkymarcher.java +++ b/Mage.Sets/src/mage/cards/d/DuskborneSkymarcher.java @@ -17,6 +17,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.AttackingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -45,7 +46,7 @@ public final class DuskborneSkymarcher extends CardImpl { // {W}, {T}: Target attacking vampire gets +1/+1 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(1, 1, Duration.EndOfTurn), new ManaCostsImpl<>("{W}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DwarvenArmory.java b/Mage.Sets/src/mage/cards/d/DwarvenArmory.java index 91ea7cf64ef..3fa047b3291 100644 --- a/Mage.Sets/src/mage/cards/d/DwarvenArmory.java +++ b/Mage.Sets/src/mage/cards/d/DwarvenArmory.java @@ -1,38 +1,38 @@ package mage.cards.d; -import java.util.UUID; import mage.abilities.Ability; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.PhaseStep; -import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.StaticFilters; -import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class DwarvenArmory extends CardImpl { + private static final Condition condition = new IsStepCondition(PhaseStep.UPKEEP, false); + public DwarvenArmory(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}{R}"); // {2}, Sacrifice a land: Put a +2/+2 counter on target creature. Activate this ability only during any upkeep step. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, + Ability ability = new ActivateIfConditionActivatedAbility( new AddCountersTargetEffect(CounterType.P2P2.createInstance()), - new ManaCostsImpl<>("{2}"), - new IsStepCondition(PhaseStep.UPKEEP, false), - null); + new ManaCostsImpl<>("{2}"), condition + ); ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_LAND)); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/d/DwarvenCatapult.java b/Mage.Sets/src/mage/cards/d/DwarvenCatapult.java index d08553454ab..221b456587b 100644 --- a/Mage.Sets/src/mage/cards/d/DwarvenCatapult.java +++ b/Mage.Sets/src/mage/cards/d/DwarvenCatapult.java @@ -17,13 +17,12 @@ import mage.util.CardUtil; import java.util.UUID; /** - * * @author MarcoMarin */ public final class DwarvenCatapult extends CardImpl { public DwarvenCatapult(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{R}"); // Dwarven Catapult deals X damage divided evenly, rounded down, among all creatures target opponent controls. this.getSpellAbility().addTarget(new TargetOpponent()); @@ -55,10 +54,11 @@ class DwarvenCatapultEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { int howMany = game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURES, source.getFirstTarget(), game).size(); - int amount = CardUtil.getSourceCostsTag(game, source, "X", 0)/howMany; - - DamageAllControlledTargetEffect dmgEffect = new DamageAllControlledTargetEffect(amount, new FilterCreaturePermanent()); - return dmgEffect.apply(game, source); + if (howMany > 0) { + int amount = CardUtil.getSourceCostsTag(game, source, "X", 0) / howMany; + return new DamageAllControlledTargetEffect(amount, new FilterCreaturePermanent()).apply(game, source); + } + return false; } @Override diff --git a/Mage.Sets/src/mage/cards/d/DwarvenDemolitionTeam.java b/Mage.Sets/src/mage/cards/d/DwarvenDemolitionTeam.java index 7149e308f38..dfb90ce8d07 100644 --- a/Mage.Sets/src/mage/cards/d/DwarvenDemolitionTeam.java +++ b/Mage.Sets/src/mage/cards/d/DwarvenDemolitionTeam.java @@ -13,6 +13,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -36,7 +37,7 @@ public final class DwarvenDemolitionTeam extends CardImpl { // {tap}: Destroy target Wall. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DwarvenLieutenant.java b/Mage.Sets/src/mage/cards/d/DwarvenLieutenant.java index a4e401f1476..528f70cf541 100644 --- a/Mage.Sets/src/mage/cards/d/DwarvenLieutenant.java +++ b/Mage.Sets/src/mage/cards/d/DwarvenLieutenant.java @@ -14,6 +14,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -37,7 +38,7 @@ public final class DwarvenLieutenant extends CardImpl { // {1}{R}: Target Dwarf creature gets +1/+0 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl<>("{1}{R}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DwarvenNomad.java b/Mage.Sets/src/mage/cards/d/DwarvenNomad.java index 0a007e756b5..b6297ca12c5 100644 --- a/Mage.Sets/src/mage/cards/d/DwarvenNomad.java +++ b/Mage.Sets/src/mage/cards/d/DwarvenNomad.java @@ -15,6 +15,7 @@ import mage.constants.ComparisonType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,7 +39,7 @@ public final class DwarvenNomad extends CardImpl { // {T}: Target creature with power 2 or less can't be blocked this turn. Ability ability = new SimpleActivatedAbility(new CantBeBlockedTargetEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DwarvenPony.java b/Mage.Sets/src/mage/cards/d/DwarvenPony.java index 0c8537dc7ae..01dd5ad79ce 100644 --- a/Mage.Sets/src/mage/cards/d/DwarvenPony.java +++ b/Mage.Sets/src/mage/cards/d/DwarvenPony.java @@ -16,6 +16,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class DwarvenPony extends CardImpl { Ability ability = new SimpleActivatedAbility( new GainAbilityTargetEffect(new MountainwalkAbility(false), Duration.EndOfTurn), new ManaCostsImpl<>("{1}{R}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DwarvenSeaClan.java b/Mage.Sets/src/mage/cards/d/DwarvenSeaClan.java index fa3a13b4df6..6cafeb67f3c 100644 --- a/Mage.Sets/src/mage/cards/d/DwarvenSeaClan.java +++ b/Mage.Sets/src/mage/cards/d/DwarvenSeaClan.java @@ -1,33 +1,32 @@ package mage.cards.d; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.DamageTargetEffect; -import mage.constants.PhaseStep; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; +import mage.constants.PhaseStep; +import mage.constants.SubType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterAttackingOrBlockingCreature; import mage.filter.predicate.permanent.ControllerControlsIslandPredicate; import mage.game.Game; import mage.target.TargetPermanent; +import java.util.UUID; + /** - * * @author noahg */ public final class DwarvenSeaClan extends CardImpl { - private static final FilterAttackingOrBlockingCreature filter = new FilterAttackingOrBlockingCreature(); + private static final FilterPermanent filter = new FilterAttackingOrBlockingCreature("attacking or blocking creature whose controller controls an Island"); static { filter.add(ControllerControlsIslandPredicate.instance); @@ -35,19 +34,18 @@ public final class DwarvenSeaClan extends CardImpl { public DwarvenSeaClan(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); - + this.subtype.add(SubType.DWARF); this.power = new MageInt(1); this.toughness = new MageInt(1); // {tap}: Choose target attacking or blocking creature whose controller controls an Island. Dwarven Sea Clan deals 2 damage to that creature at end of combat. Activate this ability only before the end of combat step. - Effect effect = new CreateDelayedTriggeredAbilityEffect(new AtTheEndOfCombatDelayedTriggeredAbility(new DamageTargetEffect(2, true, "that creature"))); - effect.setText("Choose target attacking or blocking creature whose controller controls an Island. Dwarven Sea Clan deals 2 damage to that creature at end of combat."); Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, - effect, - new TapSourceCost(), - BeforeEndCombatCondition.getInstance() + new CreateDelayedTriggeredAbilityEffect(new AtTheEndOfCombatDelayedTriggeredAbility( + new DamageTargetEffect(2, true, "that creature") + )).setText("Choose target attacking or blocking creature whose controller controls an Island. " + + "{this} deals 2 damage to that creature at end of combat."), + new TapSourceCost(), BeforeEndCombatCondition.getInstance() ); ability.addTarget(new TargetPermanent(filter)); addAbility(ability); @@ -73,7 +71,7 @@ class BeforeEndCombatCondition implements Condition { @Override public boolean apply(Game game, Ability source) { PhaseStep phaseStep = game.getTurnStepType(); - if(phaseStep.getIndex() < PhaseStep.END_COMBAT.getIndex()) { + if (phaseStep.getIndex() < PhaseStep.END_COMBAT.getIndex()) { return true; } return false; diff --git a/Mage.Sets/src/mage/cards/d/DwarvenWarriors.java b/Mage.Sets/src/mage/cards/d/DwarvenWarriors.java index 5bc2d1b8b6a..2deb081afea 100644 --- a/Mage.Sets/src/mage/cards/d/DwarvenWarriors.java +++ b/Mage.Sets/src/mage/cards/d/DwarvenWarriors.java @@ -15,6 +15,7 @@ import mage.constants.ComparisonType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,7 +39,7 @@ public final class DwarvenWarriors extends CardImpl { // {T}: Target creature with power 2 or less can't be blocked this turn. Ability ability = new SimpleActivatedAbility(new CantBeBlockedTargetEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/d/DwarvenWeaponsmith.java b/Mage.Sets/src/mage/cards/d/DwarvenWeaponsmith.java index c511bc5951b..a175e97aa23 100644 --- a/Mage.Sets/src/mage/cards/d/DwarvenWeaponsmith.java +++ b/Mage.Sets/src/mage/cards/d/DwarvenWeaponsmith.java @@ -1,42 +1,39 @@ - package mage.cards.d; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; 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.constants.PhaseStep; -import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.StaticFilters; -import mage.filter.common.FilterControlledArtifactPermanent; -import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LoneFox */ public final class DwarvenWeaponsmith extends CardImpl { public DwarvenWeaponsmith(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.DWARF); this.subtype.add(SubType.ARTIFICER); this.power = new MageInt(1); this.toughness = new MageInt(1); // {tap}, Sacrifice an artifact: Put a +1/+1 counter on target creature. Activate this ability only during your upkeep. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.P1P1.createInstance()), - new TapSourceCost(), new IsStepCondition(PhaseStep.UPKEEP)); + Ability ability = new ActivateIfConditionActivatedAbility( + new AddCountersTargetEffect(CounterType.P1P1.createInstance()), + new TapSourceCost(), IsStepCondition.getMyUpkeep() + ); ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_ARTIFACT)); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/e/EagleOfDeliverance.java b/Mage.Sets/src/mage/cards/e/EagleOfDeliverance.java index 71c58d6f990..450ea1ab8cf 100644 --- a/Mage.Sets/src/mage/cards/e/EagleOfDeliverance.java +++ b/Mage.Sets/src/mage/cards/e/EagleOfDeliverance.java @@ -17,7 +17,7 @@ import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -41,7 +41,7 @@ public final class EagleOfDeliverance extends CardImpl { TriggeredAbility trigger = new EntersBattlefieldTriggeredAbility( new AddCountersTargetEffect(CounterType.INDESTRUCTIBLE.createInstance()) ); - trigger.addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); + trigger.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); trigger.addEffect(new EagleOfDeliveranceEffect()); this.addAbility(trigger); } @@ -80,4 +80,4 @@ class EagleOfDeliveranceEffect extends OneShotEffect { } return new DrawCardSourceControllerEffect(1).apply(game, source); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/e/Earthbind.java b/Mage.Sets/src/mage/cards/e/Earthbind.java index ccef1b4d6a5..2ed7479beac 100644 --- a/Mage.Sets/src/mage/cards/e/Earthbind.java +++ b/Mage.Sets/src/mage/cards/e/Earthbind.java @@ -1,7 +1,6 @@ package mage.cards.e; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.Effect; @@ -14,13 +13,15 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AttachmentType; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * * @author escplan9 (Derek Monturo - dmontur1 at gmail dot com) @@ -60,7 +61,7 @@ class EarthbindEffect extends OneShotEffect { EarthbindEffect() { super(Outcome.Damage); - staticText = "if enchanted creature has flying, {this} deals 2 damage to that creature and Earthbind gains \"Enchanted creature loses flying.\""; + staticText = "if enchanted creature has flying, {this} deals 2 damage to that creature and {this} gains \"Enchanted creature loses flying.\""; } private EarthbindEffect(final EarthbindEffect effect) { diff --git a/Mage.Sets/src/mage/cards/e/Earthcraft.java b/Mage.Sets/src/mage/cards/e/Earthcraft.java index 730000169af..325992325aa 100644 --- a/Mage.Sets/src/mage/cards/e/Earthcraft.java +++ b/Mage.Sets/src/mage/cards/e/Earthcraft.java @@ -1,7 +1,5 @@ - package mage.cards.e; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapTargetCost; @@ -10,24 +8,22 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SuperType; -import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.common.FilterControlledPermanent; -import mage.filter.predicate.permanent.TappedPredicate; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.common.FilterLandPermanent; import mage.target.TargetPermanent; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; + +import java.util.UUID; /** * @author Loki */ public final class Earthcraft extends CardImpl { - private static final FilterControlledCreaturePermanent filterCreature = new FilterControlledCreaturePermanent("untapped creature you control"); - private static final FilterControlledPermanent filterLand = new FilterControlledPermanent("basic land"); + private static final FilterPermanent filterLand = new FilterLandPermanent("basic land"); static { - filterCreature.add(TappedPredicate.UNTAPPED); - filterLand.add(CardType.LAND.getPredicate()); filterLand.add(SuperType.BASIC.getPredicate()); } @@ -35,7 +31,10 @@ public final class Earthcraft extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); // Tap an untapped creature you control: Untap target basic land. - Ability ability = new SimpleActivatedAbility(new UntapTargetEffect(), new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filterCreature, true))); + Ability ability = new SimpleActivatedAbility( + new UntapTargetEffect(), + new TapTargetCost(new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURE)) + ); ability.addTarget(new TargetPermanent(filterLand)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/Earthlore.java b/Mage.Sets/src/mage/cards/e/Earthlore.java index 38750d5e969..27167959e23 100644 --- a/Mage.Sets/src/mage/cards/e/Earthlore.java +++ b/Mage.Sets/src/mage/cards/e/Earthlore.java @@ -1,11 +1,9 @@ - package mage.cards.e; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.AttachedToMatchesFilterCondition; -import mage.abilities.costs.Cost; import mage.abilities.costs.common.TapAttachedCost; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; @@ -13,55 +11,48 @@ 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.Duration; -import mage.constants.Zone; +import mage.constants.SubType; import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.filter.common.FilterBlockingCreature; -import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.permanent.TappedPredicate; import mage.target.TargetPermanent; import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author L_J */ public final class Earthlore extends CardImpl { - private static final FilterControlledPermanent filterLand = new FilterControlledPermanent("land you control"); - - static { - filterLand.add(CardType.LAND.getPredicate()); - } - private static final FilterPermanent filterUntapped = new FilterPermanent("enchanted land is untapped"); - + static { filterUntapped.add(TappedPredicate.UNTAPPED); } + private static final Condition condition = new AttachedToMatchesFilterCondition(filterUntapped); + public Earthlore(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{G}"); this.subtype.add(SubType.AURA); // Enchant land you control - TargetPermanent auraTarget = new TargetControlledPermanent(filterLand); + TargetPermanent auraTarget = new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // Tap enchanted land: Target blocking creature gets +1/+2 until end of turn. Activate this ability only if enchanted land is untapped. - Cost cost = new TapAttachedCost(); - cost.setText("Tap enchanted land"); - Ability ability2 = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new BoostTargetEffect(1, 2, Duration.EndOfTurn), cost, new AttachedToMatchesFilterCondition(filterUntapped)); - ability2.addTarget(new TargetCreaturePermanent(new FilterBlockingCreature("blocking creature"))); - this.addAbility(ability2); - + Ability ability = new ActivateIfConditionActivatedAbility( + new BoostTargetEffect(1, 2), + new TapAttachedCost().setText("Tap enchanted land"), condition + ); + ability.addTarget(new TargetPermanent(new FilterBlockingCreature("blocking creature"))); + this.addAbility(ability); } private Earthlore(final Earthlore card) { diff --git a/Mage.Sets/src/mage/cards/e/EarthshakerKhenra.java b/Mage.Sets/src/mage/cards/e/EarthshakerKhenra.java index 760114463da..144dfa9100c 100644 --- a/Mage.Sets/src/mage/cards/e/EarthshakerKhenra.java +++ b/Mage.Sets/src/mage/cards/e/EarthshakerKhenra.java @@ -19,6 +19,7 @@ import mage.filter.predicate.ObjectSourcePlayer; import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -51,7 +52,7 @@ public final class EarthshakerKhenra extends CardImpl { .setText("target creature with power less than or equal " + "to {this}'s power can't block this turn") ); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // Eternalize {4}{R}{R} diff --git a/Mage.Sets/src/mage/cards/e/EarwigSquad.java b/Mage.Sets/src/mage/cards/e/EarwigSquad.java index fa1ed4663f9..2661f3a0605 100644 --- a/Mage.Sets/src/mage/cards/e/EarwigSquad.java +++ b/Mage.Sets/src/mage/cards/e/EarwigSquad.java @@ -33,7 +33,7 @@ public final class EarwigSquad extends CardImpl { // When Earwig Squad enters the battlefield, if its prowl cost was paid, search target opponent's library for three cards and exile them. Then that player shuffles their library. Ability ability = new EntersBattlefieldTriggeredAbility( - new SearchLibraryAndExileTargetEffect(3, true), false + new SearchLibraryAndExileTargetEffect(3, false), false ).withInterveningIf(ProwlCostWasPaidCondition.instance); ability.addTarget(new TargetOpponent()); this.addAbility(ability.addHint(ProwlCostWasPaidHint.instance)); diff --git a/Mage.Sets/src/mage/cards/e/EasternPaladin.java b/Mage.Sets/src/mage/cards/e/EasternPaladin.java index 508336db108..101aa076962 100644 --- a/Mage.Sets/src/mage/cards/e/EasternPaladin.java +++ b/Mage.Sets/src/mage/cards/e/EasternPaladin.java @@ -18,6 +18,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -41,7 +42,7 @@ public final class EasternPaladin extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new ManaCostsImpl<>("{B}{B}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); ability.addCost(new TapSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/EatenBySpiders.java b/Mage.Sets/src/mage/cards/e/EatenBySpiders.java index 3c22bfbd165..7dddb3e0b6b 100644 --- a/Mage.Sets/src/mage/cards/e/EatenBySpiders.java +++ b/Mage.Sets/src/mage/cards/e/EatenBySpiders.java @@ -15,6 +15,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -35,7 +36,7 @@ public final class EatenBySpiders extends CardImpl { // Destroy target creature with flying and all Equipment attached to that creature. this.getSpellAbility().addEffect(new EatenBySpidersEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private EatenBySpiders(final EatenBySpiders card) { diff --git a/Mage.Sets/src/mage/cards/e/EaterOfVirtue.java b/Mage.Sets/src/mage/cards/e/EaterOfVirtue.java index fdc8088aa17..2396ce6f30c 100644 --- a/Mage.Sets/src/mage/cards/e/EaterOfVirtue.java +++ b/Mage.Sets/src/mage/cards/e/EaterOfVirtue.java @@ -1,7 +1,5 @@ package mage.cards.e; -import java.util.Set; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.DiesAttachedTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -9,38 +7,20 @@ import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; -import mage.abilities.keyword.DeathtouchAbility; -import mage.abilities.keyword.DoubleStrikeAbility; -import mage.abilities.keyword.EquipAbility; -import mage.abilities.keyword.FirstStrikeAbility; -import mage.abilities.keyword.FlyingAbility; -import mage.abilities.keyword.HasteAbility; -import mage.abilities.keyword.HexproofAbility; -import mage.abilities.keyword.IndestructibleAbility; -import mage.abilities.keyword.LifelinkAbility; -import mage.abilities.keyword.MenaceAbility; -import mage.abilities.keyword.ProtectionAbility; -import mage.abilities.keyword.ReachAbility; -import mage.abilities.keyword.TrampleAbility; -import mage.abilities.keyword.VigilanceAbility; +import mage.abilities.keyword.*; 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.SetTargetPointer; -import mage.constants.SubLayer; -import mage.constants.SubType; -import mage.constants.SuperType; -import mage.constants.Zone; +import mage.constants.*; import mage.game.ExileZone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.util.CardUtil; +import java.util.Set; +import java.util.UUID; + /** * @author jeffwadsworth */ @@ -112,7 +92,7 @@ class EaterOfVirtueGainAbilityAttachedEffect extends ContinuousEffectImpl { EaterOfVirtueGainAbilityAttachedEffect() { super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); - staticText = "As long as a card exiled with Eater of Virtue has flying, equipped creature has flying. The same is true for first strike, double strike, deathtouch, haste, hexproof, indestructible, lifelink, menace, protection, reach, trample, and vigilance"; + staticText = "As long as a card exiled with {this} has flying, equipped creature has flying. The same is true for first strike, double strike, deathtouch, haste, hexproof, indestructible, lifelink, menace, protection, reach, trample, and vigilance"; } private EaterOfVirtueGainAbilityAttachedEffect(final EaterOfVirtueGainAbilityAttachedEffect effect) { diff --git a/Mage.Sets/src/mage/cards/e/EbonPraetor.java b/Mage.Sets/src/mage/cards/e/EbonPraetor.java index 46fbd45637e..40c076b68fe 100644 --- a/Mage.Sets/src/mage/cards/e/EbonPraetor.java +++ b/Mage.Sets/src/mage/cards/e/EbonPraetor.java @@ -1,10 +1,7 @@ - package mage.cards.e; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.Cost; @@ -14,16 +11,21 @@ import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class EbonPraetor extends CardImpl { @@ -45,8 +47,11 @@ public final class EbonPraetor extends CardImpl { this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.M2M2.createInstance()))); // Sacrifice a creature: Remove a -2/-2 counter from Ebon Praetor. If the sacrificed creature was a Thrull, put a +1/+0 counter on Ebon Praetor. Activate this ability only during your upkeep and only once each turn. - Ability ability = new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, new RemoveCounterSourceEffect(CounterType.M2M2.createInstance()), - new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_CREATURE), 1, new IsStepCondition(PhaseStep.UPKEEP)); + Ability ability = new LimitedTimesPerTurnActivatedAbility( + Zone.BATTLEFIELD, new RemoveCounterSourceEffect(CounterType.M2M2.createInstance()), + new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_CREATURE), + 1, IsStepCondition.getMyUpkeep() + ); ability.addEffect(new EbonPraetorEffect()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/EbonyHorse.java b/Mage.Sets/src/mage/cards/e/EbonyHorse.java index 05bf3cea578..fbd8d8d8672 100644 --- a/Mage.Sets/src/mage/cards/e/EbonyHorse.java +++ b/Mage.Sets/src/mage/cards/e/EbonyHorse.java @@ -18,6 +18,7 @@ import mage.constants.TargetController; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.AttackingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -44,7 +45,7 @@ public final class EbonyHorse extends CardImpl { effect = new PreventCombatDamageBySourceEffect(Duration.EndOfTurn); effect.setText("and dealt by that creature this turn"); ability.addEffect(effect); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/EchoingAssault.java b/Mage.Sets/src/mage/cards/e/EchoingAssault.java new file mode 100644 index 00000000000..985ecd88d62 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EchoingAssault.java @@ -0,0 +1,107 @@ +package mage.cards.e; + +import mage.abilities.Ability; +import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenCopyTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.MenaceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SetTargetPointer; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; +import mage.util.CardUtil; + +import java.util.UUID; + +/** + * @author notgreat + */ +public final class EchoingAssault extends CardImpl { + + private static final FilterPermanent filter = new FilterCreaturePermanent("nontoken creature that's attacking that player"); + + static { + filter.add(TokenPredicate.FALSE); + filter.add(EchoingAssaultPredicate.instance); + } + + public EchoingAssault(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{R}"); + + + // Creature tokens you control have menace. + this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect( + new MenaceAbility(false), Duration.WhileOnBattlefield, StaticFilters.FILTER_CREATURE_TOKENS + ))); + + // Whenever you attack a player, choose target nontoken creature that's attacking that player. Create a token that's a copy of that creature, except it's 1/1. The token enters tapped and attacking that player. Sacrifice it at the beginning of the next end step. + Ability ability = new AttacksPlayerWithCreaturesTriggeredAbility(new EchoingAssaultEffect(), SetTargetPointer.NONE); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); + } + + private EchoingAssault(final EchoingAssault card) { + super(card); + } + + @Override + public EchoingAssault copy() { + return new EchoingAssault(this); + } +} + +enum EchoingAssaultPredicate implements ObjectSourcePlayerPredicate { + instance; + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + return CardUtil.getEffectValueFromAbility(input.getSource(), "playerAttacked", UUID.class) + .filter(uuid -> uuid.equals(game.getCombat().getDefenderId(input.getObject().getId()))) + .isPresent(); + } +} + +class EchoingAssaultEffect extends OneShotEffect { + + EchoingAssaultEffect() { + super(Outcome.Benefit); + staticText = "choose target nontoken creature that's attacking that player. Create a token that's a copy of that creature, except it's 1/1. The token enters tapped and attacking that player. Sacrifice it at the beginning of the next end step."; + } + + private EchoingAssaultEffect(final EchoingAssaultEffect effect) { + super(effect); + } + + @Override + public EchoingAssaultEffect copy() { + return new EchoingAssaultEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Object attackedPlayer = getValue("playerAttacked"); + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (permanent == null || !(attackedPlayer instanceof UUID)) { + return false; + } + CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(null, null, false, + 1, true, true, (UUID) attackedPlayer, 1, 1, false); + effect.setSavedPermanent(permanent); + effect.apply(game, source); + effect.sacrificeTokensCreatedAtNextEndStep(game, source); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/e/EddytrailHawk.java b/Mage.Sets/src/mage/cards/e/EddytrailHawk.java index 2fa949d573c..30078a71682 100644 --- a/Mage.Sets/src/mage/cards/e/EddytrailHawk.java +++ b/Mage.Sets/src/mage/cards/e/EddytrailHawk.java @@ -17,6 +17,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.filter.common.FilterAttackingCreature; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -43,7 +44,7 @@ public final class EddytrailHawk extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new GetEnergyCountersControllerEffect(2))); // Whenever Eddytrail Hawk attacks, you may pay {E}. If you do, another target attacking creature gains flying until end of turn. Ability ability = new AttacksTriggeredAbility(new DoIfCostPaid(new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), new PayEnergyCost(1))); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/EdificeOfAuthority.java b/Mage.Sets/src/mage/cards/e/EdificeOfAuthority.java index 2eb546cec93..03f08147896 100644 --- a/Mage.Sets/src/mage/cards/e/EdificeOfAuthority.java +++ b/Mage.Sets/src/mage/cards/e/EdificeOfAuthority.java @@ -7,7 +7,7 @@ import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.RestrictionEffect; import mage.abilities.effects.common.combat.CantAttackTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -40,7 +40,7 @@ public final class EdificeOfAuthority extends CardImpl { this.addAbility(ability); // {1}, {T}: Until your next turn, target creature can't attack or block and its activated abilities can't be activated. Activate this ability only if there are three or more brick counter on Edifice of Authority. - Ability ability2 = new ConditionalActivatedAbility(new EdificeOfAuthorityEffect(), new GenericManaCost(1), condition); + Ability ability2 = new ActivateIfConditionActivatedAbility(new EdificeOfAuthorityEffect(), new GenericManaCost(1), condition); ability2.addCost(new TapSourceCost()); ability2.addTarget(new TargetCreaturePermanent()); this.addAbility(ability2); diff --git a/Mage.Sets/src/mage/cards/e/EerieInterlude.java b/Mage.Sets/src/mage/cards/e/EerieInterlude.java index d4268449675..72d7698beb5 100644 --- a/Mage.Sets/src/mage/cards/e/EerieInterlude.java +++ b/Mage.Sets/src/mage/cards/e/EerieInterlude.java @@ -4,7 +4,6 @@ import mage.abilities.effects.common.ExileReturnBattlefieldNextEndStepTargetEffe import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.StaticFilters; import mage.target.common.TargetControlledCreaturePermanent; import java.util.UUID; @@ -15,12 +14,12 @@ import java.util.UUID; public final class EerieInterlude extends CardImpl { public EerieInterlude(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[] {CardType.INSTANT}, "{2}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}"); // Exile any number of target creatures you control. Return those cards to the // battlefield under their owner's control at the beginning of the next end step. this.getSpellAbility().addEffect(new ExileReturnBattlefieldNextEndStepTargetEffect()); - this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, StaticFilters.FILTER_CONTROLLED_CREATURES, false)); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE)); } private EerieInterlude(final EerieInterlude card) { diff --git a/Mage.Sets/src/mage/cards/e/EfreetWeaponmaster.java b/Mage.Sets/src/mage/cards/e/EfreetWeaponmaster.java index d166d5247b4..1f98778f5d2 100644 --- a/Mage.Sets/src/mage/cards/e/EfreetWeaponmaster.java +++ b/Mage.Sets/src/mage/cards/e/EfreetWeaponmaster.java @@ -13,7 +13,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.filter.StaticFilters; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -37,7 +37,7 @@ public final class EfreetWeaponmaster extends CardImpl { Ability ability = new EntersBattlefieldOrTurnedFaceUpTriggeredAbility( new BoostTargetEffect(3, 0, Duration.EndOfTurn) ); - ability.addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); this.addAbility(ability); // Morph {2}{U}{R}{W} diff --git a/Mage.Sets/src/mage/cards/e/EladamriKorvecdal.java b/Mage.Sets/src/mage/cards/e/EladamriKorvecdal.java index 2a61a0911e4..cd24716ae5b 100644 --- a/Mage.Sets/src/mage/cards/e/EladamriKorvecdal.java +++ b/Mage.Sets/src/mage/cards/e/EladamriKorvecdal.java @@ -53,7 +53,7 @@ public final class EladamriKorvecdal extends CardImpl { // {G}, {T}, Tap two untapped creatures you control: Reveal a card from your hand or the top card of your library. If you reveal a creature card this way, put it onto the battlefield. Activate only during your turn. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new EladamriKorvecdalEffect(), new ManaCostsImpl<>("{G}"), MyTurnCondition.instance + new EladamriKorvecdalEffect(), new ManaCostsImpl<>("{G}"), MyTurnCondition.instance ); ability.addCost(new TapSourceCost()); ability.addCost(new TapTargetCost(new TargetControlledPermanent( @@ -163,4 +163,4 @@ class EladamriKorvecdalEffect extends OneShotEffect { } return true; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/e/EldraziDisplacer.java b/Mage.Sets/src/mage/cards/e/EldraziDisplacer.java index b2399147e84..b963eff65c4 100644 --- a/Mage.Sets/src/mage/cards/e/EldraziDisplacer.java +++ b/Mage.Sets/src/mage/cards/e/EldraziDisplacer.java @@ -12,10 +12,13 @@ import mage.constants.CardType; import mage.constants.PutCards; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * @author LevelX2 */ @@ -32,7 +35,7 @@ public final class EldraziDisplacer extends CardImpl { // {2}{C}: Exile another target creature, then return it to the battlefield tapped under its owner's control. Ability ability = new SimpleActivatedAbility(new ExileThenReturnTargetEffect(false, false, PutCards.BATTLEFIELD_TAPPED), new ManaCostsImpl<>("{2}{C}")); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/EldraziMimic.java b/Mage.Sets/src/mage/cards/e/EldraziMimic.java index 71ae0a5678f..380ef35460a 100644 --- a/Mage.Sets/src/mage/cards/e/EldraziMimic.java +++ b/Mage.Sets/src/mage/cards/e/EldraziMimic.java @@ -2,14 +2,15 @@ package mage.cards.e; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.SetBasePowerToughnessTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.mageobject.ColorlessPredicate; import mage.game.Game; @@ -24,7 +25,7 @@ import java.util.UUID; */ public final class EldraziMimic extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another colorless creature"); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("another colorless creature you control"); static { filter.add(AnotherPredicate.instance); @@ -39,7 +40,7 @@ public final class EldraziMimic extends CardImpl { // Whenever another colorless creature you control enters, you may have the base power and toughness of Eldrazi Mimic // become that creature's power and toughness until end of turn. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + this.addAbility(new EntersBattlefieldAllTriggeredAbility( Zone.BATTLEFIELD, new EldraziMimicEffect(), filter, true, SetTargetPointer.PERMANENT )); @@ -59,7 +60,7 @@ class EldraziMimicEffect extends OneShotEffect { EldraziMimicEffect() { super(Outcome.BoostCreature); - staticText = "you may have the base power and toughness of {this} become that creature's power and toughness until end of turn"; + staticText = "you may change {this}'s base power and toughness to that creature's power and toughness until end of turn"; } private EldraziMimicEffect(final EldraziMimicEffect effect) { diff --git a/Mage.Sets/src/mage/cards/e/EldraziObligator.java b/Mage.Sets/src/mage/cards/e/EldraziObligator.java index 9f96a410810..88e08b5d541 100644 --- a/Mage.Sets/src/mage/cards/e/EldraziObligator.java +++ b/Mage.Sets/src/mage/cards/e/EldraziObligator.java @@ -20,6 +20,7 @@ import mage.constants.SubType; import mage.constants.Duration; import mage.filter.common.FilterCreaturePermanent; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -51,7 +52,7 @@ public final class EldraziObligator extends CardImpl { // When you cast Eldrazi Obligator, you may pay {1}{C}. If you do, gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn. Ability ability = new CastSourceTriggeredAbility(costPaidEffect); - Target target = new TargetCreaturePermanent(new FilterCreaturePermanent()); + Target target = new TargetPermanent(new FilterCreaturePermanent()); ability.addTarget(target); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/Electrickery.java b/Mage.Sets/src/mage/cards/e/Electrickery.java index 06bd5c7d6a6..080f40aa755 100644 --- a/Mage.Sets/src/mage/cards/e/Electrickery.java +++ b/Mage.Sets/src/mage/cards/e/Electrickery.java @@ -8,10 +8,13 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author LevelX2 */ @@ -21,7 +24,7 @@ public final class Electrickery extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}"); // Electrickery deals 1 damage to target creature you don't control. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.getSpellAbility().addEffect(new DamageTargetEffect(1)); // Overload {1}{R} (You may cast this spell for its overload cost. If you do, change its text by replacing all instances of "target" with "each.") diff --git a/Mage.Sets/src/mage/cards/e/ElementalBond.java b/Mage.Sets/src/mage/cards/e/ElementalBond.java index 93b0d78975f..b4ecb0170b8 100644 --- a/Mage.Sets/src/mage/cards/e/ElementalBond.java +++ b/Mage.Sets/src/mage/cards/e/ElementalBond.java @@ -1,8 +1,6 @@ - package mage.cards.e; -import java.util.UUID; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -12,23 +10,24 @@ import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import java.util.UUID; + /** - * * @author emerald000 */ public final class ElementalBond extends CardImpl { - private static final FilterPermanent filter = new FilterControlledCreaturePermanent("a creature with power 3 or greater"); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("a creature you control with power 3 or greater"); static { filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 2)); } public ElementalBond(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); // Whenever a creature with power 3 or greater you control enters, draw a card. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility(new DrawCardSourceControllerEffect(1), filter)); + this.addAbility(new EntersBattlefieldAllTriggeredAbility(new DrawCardSourceControllerEffect(1), filter)); } private ElementalBond(final ElementalBond card) { diff --git a/Mage.Sets/src/mage/cards/e/EliteScaleguard.java b/Mage.Sets/src/mage/cards/e/EliteScaleguard.java index 3b871ebe303..bc4e861d5ae 100644 --- a/Mage.Sets/src/mage/cards/e/EliteScaleguard.java +++ b/Mage.Sets/src/mage/cards/e/EliteScaleguard.java @@ -1,6 +1,5 @@ package mage.cards.e; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksCreatureYouControlTriggeredAbility; @@ -16,10 +15,12 @@ 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.TargetPermanent; import mage.target.targetadjustment.TargetAdjuster; import mage.target.targetpointer.FirstTargetPointer; +import java.util.UUID; + /** * @author emerald000 */ @@ -41,7 +42,7 @@ public final class EliteScaleguard extends CardImpl { false, StaticFilters.FILTER_CONTROLLED_CREATURE_P1P1, true); - ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature defending player controls"))); + ability.addTarget(new TargetPermanent(new FilterCreaturePermanent("creature defending player controls"))); ability.setTargetAdjuster(EliteScaleguardTargetAdjuster.instance); this.addAbility(ability); } @@ -70,7 +71,6 @@ enum EliteScaleguardTargetAdjuster implements TargetAdjuster { } } ability.getTargets().clear(); - TargetCreaturePermanent target = new TargetCreaturePermanent(filterDefender); - ability.addTarget(target); + ability.addTarget(new TargetPermanent(filterDefender)); } } diff --git a/Mage.Sets/src/mage/cards/e/ElvenFortress.java b/Mage.Sets/src/mage/cards/e/ElvenFortress.java index 7b6c2a404aa..58447dbe001 100644 --- a/Mage.Sets/src/mage/cards/e/ElvenFortress.java +++ b/Mage.Sets/src/mage/cards/e/ElvenFortress.java @@ -12,6 +12,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterBlockingCreature; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -25,7 +26,7 @@ public final class ElvenFortress extends CardImpl { // {1}{G}: Target blocking creature gets +0/+1 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(0, 1, Duration.EndOfTurn), new ManaCostsImpl<>("{1}{G}")); - ability.addTarget(new TargetCreaturePermanent(new FilterBlockingCreature())); + ability.addTarget(new TargetPermanent(new FilterBlockingCreature())); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/ElvishArchivist.java b/Mage.Sets/src/mage/cards/e/ElvishArchivist.java index d8fa064aa98..381e69c7ddb 100644 --- a/Mage.Sets/src/mage/cards/e/ElvishArchivist.java +++ b/Mage.Sets/src/mage/cards/e/ElvishArchivist.java @@ -1,7 +1,7 @@ package mage.cards.e; import mage.MageInt; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; @@ -9,7 +9,9 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.counters.CounterType; -import mage.filter.StaticFilters; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledArtifactPermanent; +import mage.filter.common.FilterControlledEnchantmentPermanent; import java.util.UUID; @@ -18,6 +20,9 @@ import java.util.UUID; */ public final class ElvishArchivist extends CardImpl { + private static final FilterPermanent filter = new FilterControlledArtifactPermanent("one or more artifacts you control"); + private static final FilterPermanent filter2 = new FilterControlledEnchantmentPermanent("one or more enchantments you control"); + public ElvishArchivist(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); @@ -27,18 +32,14 @@ public final class ElvishArchivist extends CardImpl { this.toughness = new MageInt(1); // Whenever one or more artifacts enter the battlefield under your control, put two +1/+1 counters on Elvish Archivist. This ability triggers only once each turn. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility( - new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)), - StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT - ).setTriggersLimitEachTurn(1) - .setTriggerPhrase("Whenever one or more artifacts enter the battlefield under your control, ")); + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)), filter + ).setTriggersLimitEachTurn(1)); // Whenever one or more enchantments enter the battlefield under your control, draw a card. This ability triggers only once each turn. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility( - new DrawCardSourceControllerEffect(1), - StaticFilters.FILTER_CONTROLLED_PERMANENT_ENCHANTMENT - ).setTriggersLimitEachTurn(1) - .setTriggerPhrase("Whenever one or more enchantments enter the battlefield under your control, ")); + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + new DrawCardSourceControllerEffect(1), filter2 + ).setTriggersLimitEachTurn(1)); } private ElvishArchivist(final ElvishArchivist card) { diff --git a/Mage.Sets/src/mage/cards/e/ElvishPathcutter.java b/Mage.Sets/src/mage/cards/e/ElvishPathcutter.java index e44dbfb0d4f..39e1b3d7201 100644 --- a/Mage.Sets/src/mage/cards/e/ElvishPathcutter.java +++ b/Mage.Sets/src/mage/cards/e/ElvishPathcutter.java @@ -15,6 +15,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,7 +39,7 @@ public final class ElvishPathcutter extends CardImpl { // {2}{G}: Target Elf creature gains forestwalk until end of turn. Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(new ForestwalkAbility(false), Duration.EndOfTurn), new ManaCostsImpl<>("{2}{G}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/ElvishScout.java b/Mage.Sets/src/mage/cards/e/ElvishScout.java index 9c5a2d865b4..5528ae94f66 100644 --- a/Mage.Sets/src/mage/cards/e/ElvishScout.java +++ b/Mage.Sets/src/mage/cards/e/ElvishScout.java @@ -1,40 +1,38 @@ - package mage.cards.e; -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.Effect; import mage.abilities.effects.common.PreventDamageByTargetEffect; import mage.abilities.effects.common.PreventDamageToTargetEffect; import mage.abilities.effects.common.UntapTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.permanent.AttackingPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author LoneFox */ public final class ElvishScout extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("attacking creature you control"); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("attacking creature you control"); static { filter.add(AttackingPredicate.instance); } public ElvishScout(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}"); this.subtype.add(SubType.ELF); this.subtype.add(SubType.SCOUT); this.power = new MageInt(1); @@ -43,13 +41,12 @@ public final class ElvishScout extends CardImpl { // {G}, {tap}: Untap target attacking creature you control. Prevent all combat damage that would be dealt to and dealt by it this turn. Ability ability = new SimpleActivatedAbility(new UntapTargetEffect(), new ManaCostsImpl<>("{G}")); ability.addCost(new TapSourceCost()); - Effect effect = new PreventDamageByTargetEffect(Duration.EndOfTurn, true); - effect.setText("Prevent all combat damage that would be dealt to"); - ability.addEffect(effect); - effect = new PreventDamageToTargetEffect(Duration.EndOfTurn, Integer.MAX_VALUE, true); - effect.setText("and dealt by it this turn"); - ability.addEffect(effect); - ability.addTarget(new TargetControlledCreaturePermanent(filter)); + ability.addEffect(new PreventDamageByTargetEffect(Duration.EndOfTurn, true) + .setText("Prevent all combat damage that would be dealt to")); + ability.addEffect(new PreventDamageToTargetEffect( + Duration.EndOfTurn, Integer.MAX_VALUE, true + ).setText("and dealt by it this turn")); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/ElvishSkysweeper.java b/Mage.Sets/src/mage/cards/e/ElvishSkysweeper.java index 9aff07445f5..be06a8f9757 100644 --- a/Mage.Sets/src/mage/cards/e/ElvishSkysweeper.java +++ b/Mage.Sets/src/mage/cards/e/ElvishSkysweeper.java @@ -17,6 +17,7 @@ import mage.constants.Zone; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; @@ -43,7 +44,7 @@ public final class ElvishSkysweeper extends CardImpl { // {4}{G}, Sacrifice a creature: Destroy target creature with flying. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new ManaCostsImpl<>("{4}{G}")); ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_CREATURE)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/ElvishWarmaster.java b/Mage.Sets/src/mage/cards/e/ElvishWarmaster.java index 4be24168211..ac8f1f5cd6b 100644 --- a/Mage.Sets/src/mage/cards/e/ElvishWarmaster.java +++ b/Mage.Sets/src/mage/cards/e/ElvishWarmaster.java @@ -2,7 +2,7 @@ package mage.cards.e; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.CreateTokenEffect; @@ -15,6 +15,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.game.permanent.token.ElfWarriorToken; @@ -26,7 +27,7 @@ import java.util.UUID; */ public final class ElvishWarmaster extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent(SubType.ELF, "one or more other Elves"); + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.ELF, "one or more other Elves you control"); private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent(SubType.ELF, "Elves"); static { @@ -42,7 +43,7 @@ public final class ElvishWarmaster extends CardImpl { this.toughness = new MageInt(2); // Whenever one or more other Elves you control enters, create a 1/1 green Elf Warrior creature token. This ability triggers only once each turn. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + this.addAbility(new EntersBattlefieldAllTriggeredAbility( new CreateTokenEffect(new ElfWarriorToken()), filter ).setTriggersLimitEachTurn(1)); diff --git a/Mage.Sets/src/mage/cards/e/EmberwildeAugur.java b/Mage.Sets/src/mage/cards/e/EmberwildeAugur.java index f4fd107c7d4..f922013091a 100644 --- a/Mage.Sets/src/mage/cards/e/EmberwildeAugur.java +++ b/Mage.Sets/src/mage/cards/e/EmberwildeAugur.java @@ -1,7 +1,5 @@ - package mage.cards.e; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; @@ -12,12 +10,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.PhaseStep; -import mage.constants.Zone; import mage.target.common.TargetPlayerOrPlaneswalker; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class EmberwildeAugur extends CardImpl { @@ -32,10 +29,8 @@ public final class EmberwildeAugur extends CardImpl { // Sacrifice Emberwilde Augur: Emberwilde Augur deals 3 damage to target player. Activate this ability only during your upkeep. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new DamageTargetEffect(3, "it"), - new SacrificeSourceCost(), - new IsStepCondition(PhaseStep.UPKEEP)); + new SacrificeSourceCost(), IsStepCondition.getMyUpkeep()); ability.addTarget(new TargetPlayerOrPlaneswalker()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/EmptyShrineKannushi.java b/Mage.Sets/src/mage/cards/e/EmptyShrineKannushi.java index 09bf4f22be0..fdb8e33b2ea 100644 --- a/Mage.Sets/src/mage/cards/e/EmptyShrineKannushi.java +++ b/Mage.Sets/src/mage/cards/e/EmptyShrineKannushi.java @@ -114,7 +114,7 @@ class EmptyShrineKannushiProtectionAbility extends ProtectionAbility { @Override public String getRule() { - return "Empty-Shrine Kannushi has protection from the colors of permanents you control."; + return "{this} has protection from the colors of permanents you control."; } } diff --git a/Mage.Sets/src/mage/cards/e/EncaseInIce.java b/Mage.Sets/src/mage/cards/e/EncaseInIce.java index 9dc67bbfc9c..200c3f5ebbc 100644 --- a/Mage.Sets/src/mage/cards/e/EncaseInIce.java +++ b/Mage.Sets/src/mage/cards/e/EncaseInIce.java @@ -44,7 +44,7 @@ public final class EncaseInIce extends CardImpl { this.addAbility(FlashAbility.getInstance()); // Enchant red or green creature - TargetPermanent auraTarget = new TargetCreaturePermanent(filter); + TargetPermanent auraTarget = new TargetPermanent(filter); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); this.addAbility(new EnchantAbility(auraTarget)); diff --git a/Mage.Sets/src/mage/cards/e/EndlessAtlas.java b/Mage.Sets/src/mage/cards/e/EndlessAtlas.java index 913fad07686..929ffa35b86 100644 --- a/Mage.Sets/src/mage/cards/e/EndlessAtlas.java +++ b/Mage.Sets/src/mage/cards/e/EndlessAtlas.java @@ -1,8 +1,5 @@ package mage.cards.e; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.Condition; @@ -12,13 +9,15 @@ import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class EndlessAtlas extends CardImpl { @@ -28,10 +27,8 @@ public final class EndlessAtlas extends CardImpl { // {2}, {T}: Draw a card. Activate this ability only if you control three or more lands with the same name. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), - new GenericManaCost(2), - new EndlessAtlasCondition() + new GenericManaCost(2), EndlessAtlasCondition.instance ); ability.addCost(new TapSourceCost()); this.addAbility(ability); @@ -47,7 +44,8 @@ public final class EndlessAtlas extends CardImpl { } } -class EndlessAtlasCondition implements Condition { +enum EndlessAtlasCondition implements Condition { + instance; @Override public boolean apply(Game game, Ability source) { diff --git a/Mage.Sets/src/mage/cards/e/EndlessRanksOfTheDead.java b/Mage.Sets/src/mage/cards/e/EndlessRanksOfTheDead.java index ed43c862c98..667e117aede 100644 --- a/Mage.Sets/src/mage/cards/e/EndlessRanksOfTheDead.java +++ b/Mage.Sets/src/mage/cards/e/EndlessRanksOfTheDead.java @@ -1,34 +1,34 @@ - package mage.cards.e; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.common.FilterControlledPermanent; import mage.game.Game; -import mage.game.events.GameEvent.EventType; import mage.game.permanent.token.ZombieToken; +import java.util.UUID; + /** - * * @author BetaSteward */ public final class EndlessRanksOfTheDead extends CardImpl { public EndlessRanksOfTheDead(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, create X 2/2 black Zombie creature tokens, // where X is half the number of Zombies you control, rounded down. - this.addAbility(new OnEventTriggeredAbility(EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", - new CreateTokenEffect(new ZombieToken(), new HalfZombiesCount()))); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new CreateTokenEffect(new ZombieToken(), HalfZombiesCount.instance) + )); } @@ -42,23 +42,19 @@ public final class EndlessRanksOfTheDead extends CardImpl { } } -class HalfZombiesCount implements DynamicValue { +enum HalfZombiesCount implements DynamicValue { + instance; - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); - - static { - filter.add(SubType.ZOMBIE.getPredicate()); - } + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.ZOMBIE); @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - int amount = game.getBattlefield().countAll(filter, sourceAbility.getControllerId(), game) / 2; - return amount; + return game.getBattlefield().count(filter, sourceAbility.getControllerId(), sourceAbility, game) / 2; } @Override public HalfZombiesCount copy() { - return new HalfZombiesCount(); + return this; } @Override diff --git a/Mage.Sets/src/mage/cards/e/EnduringInnocence.java b/Mage.Sets/src/mage/cards/e/EnduringInnocence.java index a6a858d5355..0979d175c57 100644 --- a/Mage.Sets/src/mage/cards/e/EnduringInnocence.java +++ b/Mage.Sets/src/mage/cards/e/EnduringInnocence.java @@ -2,7 +2,7 @@ package mage.cards.e; import mage.MageInt; import mage.abilities.common.EnduringGlimmerTriggeredAbility; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.keyword.LifelinkAbility; import mage.cards.CardImpl; @@ -22,7 +22,7 @@ import java.util.UUID; */ public final class EnduringInnocence extends CardImpl { - private static final FilterPermanent filter = new FilterControlledCreaturePermanent(); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("one or more other creatures you control with power 2 or less"); static { filter.add(AnotherPredicate.instance); @@ -41,10 +41,9 @@ public final class EnduringInnocence extends CardImpl { this.addAbility(LifelinkAbility.getInstance()); // Whenever one or more other creatures you control with power 2 or less enter, draw a card. This ability triggers only once each turn. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + this.addAbility(new EntersBattlefieldAllTriggeredAbility( new DrawCardSourceControllerEffect(1), filter - ).setTriggersLimitEachTurn(1) - .setTriggerPhrase("Whenever one or more other creatures you control with power 2 or less enter, ")); + ).setTriggersLimitEachTurn(1)); // When Enduring Innocence dies, if it was a creature, return it to the battlefield under its owner's control. It's an enchantment. this.addAbility(new EnduringGlimmerTriggeredAbility()); diff --git a/Mage.Sets/src/mage/cards/e/EnduringVictory.java b/Mage.Sets/src/mage/cards/e/EnduringVictory.java index 9fb4f85bf2f..7a9b2ef1bf1 100644 --- a/Mage.Sets/src/mage/cards/e/EnduringVictory.java +++ b/Mage.Sets/src/mage/cards/e/EnduringVictory.java @@ -8,6 +8,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterAttackingOrBlockingCreature; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -20,7 +21,7 @@ public final class EnduringVictory extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{4}{W}"); // Destroy target attacking or blocking creature. Bolster 1. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterAttackingOrBlockingCreature())); + this.getSpellAbility().addTarget(new TargetPermanent(new FilterAttackingOrBlockingCreature())); this.getSpellAbility().addEffect(new DestroyTargetEffect()); this.getSpellAbility().addEffect(new BolsterEffect(1)); } diff --git a/Mage.Sets/src/mage/cards/e/EnergyTap.java b/Mage.Sets/src/mage/cards/e/EnergyTap.java index a1c89e44828..aa7f0c0d602 100644 --- a/Mage.Sets/src/mage/cards/e/EnergyTap.java +++ b/Mage.Sets/src/mage/cards/e/EnergyTap.java @@ -1,6 +1,5 @@ package mage.cards.e; -import java.util.UUID; import mage.Mana; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; @@ -13,10 +12,11 @@ import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author spjspj */ public final class EnergyTap extends CardImpl { @@ -31,7 +31,7 @@ public final class EnergyTap extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{U}"); // Tap target untapped creature you control. If you do, add an amount of {C} equal to that creature's converted mana cost. - this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new EnergyTapEffect()); } diff --git a/Mage.Sets/src/mage/cards/e/EnergyVortex.java b/Mage.Sets/src/mage/cards/e/EnergyVortex.java index 017a8a5e11a..daf465e579b 100644 --- a/Mage.Sets/src/mage/cards/e/EnergyVortex.java +++ b/Mage.Sets/src/mage/cards/e/EnergyVortex.java @@ -15,7 +15,9 @@ import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; @@ -49,12 +51,11 @@ public final class EnergyVortex extends CardImpl { // {X}: Put X vortex counters on Energy Vortex. Activate this ability only during your upkeep. this.addAbility(new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new AddCountersSourceEffect( CounterType.VORTEX.createInstance(), GetXValue.instance, true ), new ManaCostsImpl<>("{X}"), - new IsStepCondition(PhaseStep.UPKEEP) + IsStepCondition.getMyUpkeep() )); } diff --git a/Mage.Sets/src/mage/cards/e/EnslavedDwarf.java b/Mage.Sets/src/mage/cards/e/EnslavedDwarf.java index b24361a8199..8b7ac13fc2b 100644 --- a/Mage.Sets/src/mage/cards/e/EnslavedDwarf.java +++ b/Mage.Sets/src/mage/cards/e/EnslavedDwarf.java @@ -20,6 +20,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -48,7 +49,7 @@ public final class EnslavedDwarf extends CardImpl { effect = new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn); effect.setText("and gains first strike until end of turn"); ability.addEffect(effect); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/EntanglingVines.java b/Mage.Sets/src/mage/cards/e/EntanglingVines.java index 394f004d1bc..fa8ea12f57e 100644 --- a/Mage.Sets/src/mage/cards/e/EntanglingVines.java +++ b/Mage.Sets/src/mage/cards/e/EntanglingVines.java @@ -35,7 +35,7 @@ public final class EntanglingVines extends CardImpl { // Enchant tapped creature - TargetPermanent auraTarget = new TargetCreaturePermanent(filter); + TargetPermanent auraTarget = new TargetPermanent(filter); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); this.addAbility(new EnchantAbility(auraTarget)); diff --git a/Mage.Sets/src/mage/cards/e/EnthrallingVictor.java b/Mage.Sets/src/mage/cards/e/EnthrallingVictor.java index 8d091b1fc43..45428757d83 100644 --- a/Mage.Sets/src/mage/cards/e/EnthrallingVictor.java +++ b/Mage.Sets/src/mage/cards/e/EnthrallingVictor.java @@ -19,6 +19,7 @@ import mage.constants.Duration; import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; @@ -48,7 +49,7 @@ public final class EnthrallingVictor extends CardImpl { effect.setText("untap that creature"); ability.addEffect(effect); ability.addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn, "it gains haste until end of turn")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/EntrancingMelody.java b/Mage.Sets/src/mage/cards/e/EntrancingMelody.java index ac81fb37a4e..2a71a9d366b 100644 --- a/Mage.Sets/src/mage/cards/e/EntrancingMelody.java +++ b/Mage.Sets/src/mage/cards/e/EntrancingMelody.java @@ -7,6 +7,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetadjustment.XManaValueTargetAdjuster; @@ -24,7 +25,7 @@ public final class EntrancingMelody extends CardImpl { // Gain control of target creature with converted mana cost X. this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.Custom, true)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().setTargetAdjuster(new XManaValueTargetAdjuster()); } diff --git a/Mage.Sets/src/mage/cards/e/EowynFearlessKnight.java b/Mage.Sets/src/mage/cards/e/EowynFearlessKnight.java index 007d1481630..2e9583ac6d6 100644 --- a/Mage.Sets/src/mage/cards/e/EowynFearlessKnight.java +++ b/Mage.Sets/src/mage/cards/e/EowynFearlessKnight.java @@ -76,6 +76,11 @@ enum EowynFearlessKnightPredicate implements ObjectSourcePlayerPredicate permanent.getPower().getValue() < input.getObject().getPower().getValue()).orElse(false); } + + @Override + public String toString() { + return "another Human entered the battlefield under your control this turn"; + } } class EowynFearlessKnightEffect extends OneShotEffect { diff --git a/Mage.Sets/src/mage/cards/e/EowynShieldmaiden.java b/Mage.Sets/src/mage/cards/e/EowynShieldmaiden.java index 0f0b388d636..a8a82a056ab 100644 --- a/Mage.Sets/src/mage/cards/e/EowynShieldmaiden.java +++ b/Mage.Sets/src/mage/cards/e/EowynShieldmaiden.java @@ -79,6 +79,11 @@ enum EowynShieldmaidenCondition implements Condition { source.getSourcePermanentOrLKI(game), source.getControllerId()); } + + @Override + public String toString() { + return "another Human entered the battlefield under your control this turn"; + } } class EowynShieldmaidenWatcher extends Watcher { diff --git a/Mage.Sets/src/mage/cards/e/EpharasWarden.java b/Mage.Sets/src/mage/cards/e/EpharasWarden.java index 8a6e7db8638..c87b71857bf 100644 --- a/Mage.Sets/src/mage/cards/e/EpharasWarden.java +++ b/Mage.Sets/src/mage/cards/e/EpharasWarden.java @@ -16,6 +16,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -39,7 +40,7 @@ public final class EpharasWarden extends CardImpl { // {T}: Tap target creature with power 3 or less. Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new TapSourceCost()); - Target target = new TargetCreaturePermanent(filter); + Target target = new TargetPermanent(filter); ability.addTarget(target); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/EpicConfrontation.java b/Mage.Sets/src/mage/cards/e/EpicConfrontation.java index a4588b71687..788a6f57317 100644 --- a/Mage.Sets/src/mage/cards/e/EpicConfrontation.java +++ b/Mage.Sets/src/mage/cards/e/EpicConfrontation.java @@ -9,11 +9,14 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.filter.StaticFilters; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author fireshoes */ @@ -30,7 +33,7 @@ public final class EpicConfrontation extends CardImpl { "(Each deals damage equal to its power to the other.)"); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - Target target = new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL); + Target target = new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL); this.getSpellAbility().addTarget(target); } diff --git a/Mage.Sets/src/mage/cards/e/Eradicate.java b/Mage.Sets/src/mage/cards/e/Eradicate.java index 6f28647789a..6f078df9f2c 100644 --- a/Mage.Sets/src/mage/cards/e/Eradicate.java +++ b/Mage.Sets/src/mage/cards/e/Eradicate.java @@ -6,8 +6,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author LevelX2 @@ -19,7 +22,7 @@ public final class Eradicate extends CardImpl { // Exile target nonblack creature. Search its controller's graveyard, hand, and library for all cards // with the same name as that creature and exile them. Then that player shuffles their library. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.getSpellAbility().addEffect(new ExileTargetAndSearchGraveyardHandLibraryEffect(false, "its controller's","all cards with the same name as that creature")); } diff --git a/Mage.Sets/src/mage/cards/e/ErebossEmissary.java b/Mage.Sets/src/mage/cards/e/ErebossEmissary.java index a82cd83dfd6..3df3fec89b8 100644 --- a/Mage.Sets/src/mage/cards/e/ErebossEmissary.java +++ b/Mage.Sets/src/mage/cards/e/ErebossEmissary.java @@ -1,6 +1,5 @@ package mage.cards.e; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; @@ -15,10 +14,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.StaticFilters; import mage.target.common.TargetCardInHand; +import java.util.UUID; + /** * * @author LevelX2 @@ -39,7 +39,7 @@ public final class ErebossEmissary extends CardImpl { new BoostEnchantedEffect(2, 2, Duration.EndOfTurn), new BoostSourceEffect(2, 2, Duration.EndOfTurn), new SourceHasSubtypeCondition(SubType.AURA), - "{this} gets +2/+2 until end of turn. If Erebos's Emissary is an Aura, enchanted creature gets +2/+2 until end of turn instead"), + "{this} gets +2/+2 until end of turn. If {this} is an Aura, enchanted creature gets +2/+2 until end of turn instead"), new DiscardTargetCost(new TargetCardInHand(StaticFilters.FILTER_CARD_CREATURE)))); // Enchanted creature gets +3/+3 diff --git a/Mage.Sets/src/mage/cards/e/ErgRaiders.java b/Mage.Sets/src/mage/cards/e/ErgRaiders.java index f4a6bf72b5a..8530d6fdf75 100644 --- a/Mage.Sets/src/mage/cards/e/ErgRaiders.java +++ b/Mage.Sets/src/mage/cards/e/ErgRaiders.java @@ -35,7 +35,7 @@ public final class ErgRaiders extends CardImpl { // At the beginning of your end step, if Erg Raiders didn't attack this turn, Erg Raiders deals 2 damage to you unless it came under your control this turn. this.addAbility(new BeginningOfEndStepTriggeredAbility(new ConditionalOneShotEffect( new DamageControllerEffect(2), ErgRaidersCondition.instance, - "{this} deals 2 damage to you unless it came under your control this turn" + "it deals 2 damage to you unless it came under your control this turn" )).withInterveningIf(condition)); } diff --git a/Mage.Sets/src/mage/cards/e/ErhnamDjinn.java b/Mage.Sets/src/mage/cards/e/ErhnamDjinn.java index 6ce01e21cc9..fd4e4eb02e9 100644 --- a/Mage.Sets/src/mage/cards/e/ErhnamDjinn.java +++ b/Mage.Sets/src/mage/cards/e/ErhnamDjinn.java @@ -11,6 +11,7 @@ import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -39,7 +40,7 @@ public final class ErhnamDjinn extends CardImpl { GainAbilityTargetEffect effect = new GainAbilityTargetEffect(new ForestwalkAbility(false), Duration.UntilYourNextUpkeepStep, "target non-Wall creature an opponent controls gains forestwalk until your next upkeep"); Ability ability = new BeginningOfUpkeepTriggeredAbility(effect); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/Erithizon.java b/Mage.Sets/src/mage/cards/e/Erithizon.java index c06e46173a9..74035a4b6a3 100644 --- a/Mage.Sets/src/mage/cards/e/Erithizon.java +++ b/Mage.Sets/src/mage/cards/e/Erithizon.java @@ -12,6 +12,7 @@ import mage.constants.SubType; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetadjustment.TargetAdjuster; @@ -32,7 +33,7 @@ public final class Erithizon extends CardImpl { // Whenever Erithizon attacks, put a +1/+1 counter on target creature of defending player's choice. Ability ability = new AttacksTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance())); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); ability.setTargetAdjuster(ErithizonAdjuster.instance); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/ErrantDoomsayers.java b/Mage.Sets/src/mage/cards/e/ErrantDoomsayers.java index b4b98352cc1..a7781452dc7 100644 --- a/Mage.Sets/src/mage/cards/e/ErrantDoomsayers.java +++ b/Mage.Sets/src/mage/cards/e/ErrantDoomsayers.java @@ -16,6 +16,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ToughnessPredicate; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,7 +39,7 @@ public final class ErrantDoomsayers extends CardImpl { // {tap}: Tap target creature with toughness 2 or less. Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new TapSourceCost()); - Target target = new TargetCreaturePermanent(filter); + Target target = new TargetPermanent(filter); ability.addTarget(target); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/ErrantMinion.java b/Mage.Sets/src/mage/cards/e/ErrantMinion.java index f0f8a0d1f4b..850ad33d59a 100644 --- a/Mage.Sets/src/mage/cards/e/ErrantMinion.java +++ b/Mage.Sets/src/mage/cards/e/ErrantMinion.java @@ -58,7 +58,7 @@ class ErrantMinionEffect extends OneShotEffect { ErrantMinionEffect() { super(Outcome.Damage); - this.staticText = "that player may pay any amount of mana. Errant Minion deals 2 damage to that player. Prevent X of that damage, where X is the amount of mana that player paid this way"; + this.staticText = "that player may pay any amount of mana. {this} deals 2 damage to that player. Prevent X of that damage, where X is the amount of mana that player paid this way"; } private ErrantMinionEffect(final ErrantMinionEffect effect) { diff --git a/Mage.Sets/src/mage/cards/e/EscapeDetection.java b/Mage.Sets/src/mage/cards/e/EscapeDetection.java index ff81d39f7c4..b18be14ef75 100644 --- a/Mage.Sets/src/mage/cards/e/EscapeDetection.java +++ b/Mage.Sets/src/mage/cards/e/EscapeDetection.java @@ -1,13 +1,8 @@ package mage.cards.e; -import java.util.UUID; - import mage.ObjectColor; -import mage.abilities.Ability; -import mage.abilities.costs.Cost; import mage.abilities.costs.common.ReturnToHandChosenControlledPermanentCost; import mage.abilities.effects.common.DrawCardSourceControllerEffect; -import mage.abilities.effects.common.ReturnToHandChosenControlledPermanentEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.abilities.keyword.FreerunningAbility; import mage.cards.CardImpl; @@ -16,16 +11,17 @@ import mage.constants.CardType; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.ColorPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author grimreap124 */ public final class EscapeDetection extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("blue creature you control"); + private static final FilterControlledPermanent filter = new FilterControlledCreaturePermanent("blue creature you control"); static { filter.add(new ColorPredicate(ObjectColor.BLUE)); @@ -33,16 +29,14 @@ public final class EscapeDetection extends CardImpl { public EscapeDetection(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}{U}"); - // Freerunning--Return a blue creature you control to its owner's hand. - Cost cost = new ReturnToHandChosenControlledPermanentCost( - new TargetControlledCreaturePermanent(1, 1, filter, true)); - this.addAbility(new FreerunningAbility(cost)); + this.addAbility(new FreerunningAbility(new ReturnToHandChosenControlledPermanentCost(new TargetControlledPermanent(filter)))); // Return target creature to its owner's hand. this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("
")); } diff --git a/Mage.Sets/src/mage/cards/e/EscapeRoutes.java b/Mage.Sets/src/mage/cards/e/EscapeRoutes.java index 3e4636beb1d..23f30a75c3a 100644 --- a/Mage.Sets/src/mage/cards/e/EscapeRoutes.java +++ b/Mage.Sets/src/mage/cards/e/EscapeRoutes.java @@ -15,6 +15,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -35,7 +36,7 @@ public final class EscapeRoutes extends CardImpl { // {2}{U}: Return target white or black creature you control to its owner's hand. Ability ability = new SimpleActivatedAbility(new ReturnToHandTargetEffect(), new ManaCostsImpl<>("{2}{U}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/EsperSentinel.java b/Mage.Sets/src/mage/cards/e/EsperSentinel.java index 694961f5376..dd8228b7573 100644 --- a/Mage.Sets/src/mage/cards/e/EsperSentinel.java +++ b/Mage.Sets/src/mage/cards/e/EsperSentinel.java @@ -1,17 +1,16 @@ package mage.cards.e; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.costs.Cost; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.constants.Outcome; -import mage.constants.SubType; 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.GameEvent; @@ -22,6 +21,8 @@ import mage.target.targetpointer.FixedTarget; import mage.util.ManaUtil; import mage.watchers.common.SpellsCastWatcher; +import java.util.UUID; + /** * * @author weirddan455 @@ -94,7 +95,7 @@ class EsperSentinelTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever an opponent casts their first noncreature spell each turn, draw a card unless that player pays {X}, where X is Esper Sentinel's power."; + return "Whenever an opponent casts their first noncreature spell each turn, draw a card unless that player pays {X}, where X is {this}'s power."; } } diff --git a/Mage.Sets/src/mage/cards/e/EssenceFracture.java b/Mage.Sets/src/mage/cards/e/EssenceFracture.java index 520d5342653..b7036199c89 100644 --- a/Mage.Sets/src/mage/cards/e/EssenceFracture.java +++ b/Mage.Sets/src/mage/cards/e/EssenceFracture.java @@ -1,7 +1,5 @@ - package mage.cards.e; -import java.util.UUID; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.Effect; import mage.abilities.effects.common.ReturnToHandTargetEffect; @@ -11,21 +9,22 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class EssenceFracture extends CardImpl { public EssenceFracture(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{U}{U}"); // Return two target creatures to their owners' hands. Effect effect = new ReturnToHandTargetEffect(); effect.setText("Return two target creatures to their owners' hands"); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetCreaturePermanent(2)); - + // Cycling {2}{U} this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{2}{U}"))); } diff --git a/Mage.Sets/src/mage/cards/e/EternalDragon.java b/Mage.Sets/src/mage/cards/e/EternalDragon.java index 8ff895e6631..5b5b663e85a 100644 --- a/Mage.Sets/src/mage/cards/e/EternalDragon.java +++ b/Mage.Sets/src/mage/cards/e/EternalDragon.java @@ -1,31 +1,27 @@ - package mage.cards.e; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect; -import mage.abilities.effects.common.ReturnToHandSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.PlainscyclingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.PhaseStep; import mage.constants.Zone; +import java.util.UUID; + /** - * * @author Loki */ public final class EternalDragon extends CardImpl { public EternalDragon(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{W}{W}"); this.subtype.add(SubType.DRAGON); this.subtype.add(SubType.SPIRIT); @@ -36,13 +32,11 @@ public final class EternalDragon extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // {3}{W}{W}: Return Eternal Dragon from your graveyard to your hand. Activate this ability only during your upkeep. - Ability ability = new ConditionalActivatedAbility(Zone.GRAVEYARD, - new ReturnSourceFromGraveyardToHandEffect(), - new ManaCostsImpl<>("{3}{W}{W}"), - new IsStepCondition(PhaseStep.UPKEEP), - null - ); - this.addAbility(ability); + this.addAbility(new ActivateIfConditionActivatedAbility( + Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(), + new ManaCostsImpl<>("{3}{W}{W}"), IsStepCondition.getMyUpkeep() + )); + // PlainscyclingAbility {2} this.addAbility(new PlainscyclingAbility(new ManaCostsImpl<>("{2}"))); } diff --git a/Mage.Sets/src/mage/cards/e/EvergloveCourier.java b/Mage.Sets/src/mage/cards/e/EvergloveCourier.java index 38456e9dcef..a8df4ec0d4f 100644 --- a/Mage.Sets/src/mage/cards/e/EvergloveCourier.java +++ b/Mage.Sets/src/mage/cards/e/EvergloveCourier.java @@ -20,6 +20,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -49,7 +50,7 @@ public final class EvergloveCourier extends CardImpl { ability.addEffect(new ConditionalContinuousEffect(new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.Custom), SourceTappedCondition.TAPPED,"and has trample for as long as {this} remains tapped")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/EverythingamajigB.java b/Mage.Sets/src/mage/cards/e/EverythingamajigB.java index 172c34ab2ad..c072b0ab592 100644 --- a/Mage.Sets/src/mage/cards/e/EverythingamajigB.java +++ b/Mage.Sets/src/mage/cards/e/EverythingamajigB.java @@ -1,15 +1,12 @@ - package mage.cards.e; -import java.util.UUID; - import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.HellbentCondition; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.PutCardFromHandOntoBattlefieldEffect; @@ -17,14 +14,14 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SuperType; -import mage.constants.Zone; import mage.filter.common.FilterPermanentCard; import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.NamePredicate; import mage.filter.predicate.card.ExpansionSetPredicate; +import mage.filter.predicate.mageobject.NamePredicate; + +import java.util.UUID; /** - * * @author Ketsuban */ public final class EverythingamajigB extends CardImpl { @@ -40,14 +37,16 @@ public final class EverythingamajigB extends CardImpl { } public EverythingamajigB(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{5}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}"); // Fool's Tome // 2, T: Draw a card. Activate this ability only if you have no cards in hand. - Ability ability1 = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), new GenericManaCost(2), HellbentCondition.instance); + Ability ability1 = new ActivateIfConditionActivatedAbility( + new DrawCardSourceControllerEffect(1), new GenericManaCost(2), HellbentCondition.instance + ); ability1.addCost(new TapSourceCost()); this.addAbility(ability1); - + // Tower of Eons // 8, T: You gain 10 life. Ability ability2 = new SimpleActivatedAbility(new GainLifeEffect(10), new GenericManaCost(8)); diff --git a/Mage.Sets/src/mage/cards/e/EverythingamajigC.java b/Mage.Sets/src/mage/cards/e/EverythingamajigC.java index 52e90c7f894..b6034e21773 100644 --- a/Mage.Sets/src/mage/cards/e/EverythingamajigC.java +++ b/Mage.Sets/src/mage/cards/e/EverythingamajigC.java @@ -41,11 +41,12 @@ public final class EverythingamajigC extends CardImpl { // Disrupting Scepter // 3, {T}: Target player discards a card. Activate this ability only during your turn. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new DiscardTargetEffect(1), new GenericManaCost(3), MyTurnCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new DiscardTargetEffect(1), new GenericManaCost(3), MyTurnCondition.instance + ); ability.addTarget(new TargetPlayer()); ability.addCost(new TapSourceCost()); - ability.addHint(MyTurnHint.instance); - this.addAbility(ability); + this.addAbility(ability.addHint(MyTurnHint.instance)); // Chimeric Staff // X: Everythingamajig becomes an X/X Construct artifact creature until end of turn. diff --git a/Mage.Sets/src/mage/cards/e/EvilTwin.java b/Mage.Sets/src/mage/cards/e/EvilTwin.java index 0297e1150bc..21fa0417286 100644 --- a/Mage.Sets/src/mage/cards/e/EvilTwin.java +++ b/Mage.Sets/src/mage/cards/e/EvilTwin.java @@ -21,6 +21,7 @@ import mage.filter.predicate.ObjectSourcePlayer; import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.util.CardUtil; import mage.util.functions.CopyApplier; @@ -68,7 +69,7 @@ class EvilTwinCopyApplier extends CopyApplier { public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new ManaCostsImpl<>("{U}{B}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); blueprint.getAbilities().add(ability); return true; } diff --git a/Mage.Sets/src/mage/cards/e/EvolutionaryEscalation.java b/Mage.Sets/src/mage/cards/e/EvolutionaryEscalation.java index 4ee0cf28ca4..6732ef8f741 100644 --- a/Mage.Sets/src/mage/cards/e/EvolutionaryEscalation.java +++ b/Mage.Sets/src/mage/cards/e/EvolutionaryEscalation.java @@ -15,9 +15,12 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author spjspj @@ -31,7 +34,7 @@ public final class EvolutionaryEscalation extends CardImpl { EvolutionaryEscalationEffect effect = new EvolutionaryEscalationEffect(); Ability ability = new BeginningOfUpkeepTriggeredAbility(effect); ability.addTarget(new TargetControlledCreaturePermanent()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/ExcaliburSwordOfEden.java b/Mage.Sets/src/mage/cards/e/ExcaliburSwordOfEden.java index 40a00e27ba1..a9e1f68ac46 100644 --- a/Mage.Sets/src/mage/cards/e/ExcaliburSwordOfEden.java +++ b/Mage.Sets/src/mage/cards/e/ExcaliburSwordOfEden.java @@ -1,7 +1,5 @@ package mage.cards.e; -import java.util.UUID; - import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; @@ -11,18 +9,17 @@ import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect; import mage.abilities.keyword.EquipAbility; import mage.abilities.keyword.VigilanceAbility; -import mage.constants.*; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.filter.FilterPermanent; -import mage.filter.StaticFilters; +import mage.constants.*; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.HistoricPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author grimreap124 */ public final class ExcaliburSwordOfEden extends CardImpl { @@ -35,12 +32,12 @@ public final class ExcaliburSwordOfEden extends CardImpl { filterLegendary.add(SuperType.LEGENDARY.getPredicate()); historicFilter.add(HistoricPredicate.instance); } - + private static final TotalPermanentsManaValue xValue = new TotalPermanentsManaValue(historicFilter); public ExcaliburSwordOfEden(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{12}"); - + this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.EQUIPMENT); @@ -57,7 +54,7 @@ public final class ExcaliburSwordOfEden extends CardImpl { this.addAbility(ability); // Equip legendary creature {2} - this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2), new TargetControlledCreaturePermanent(filterLegendary), false)); + this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2), new TargetPermanent(filterLegendary), false)); } diff --git a/Mage.Sets/src/mage/cards/e/ExcavationElephant.java b/Mage.Sets/src/mage/cards/e/ExcavationElephant.java index c823d084b20..d21f4f50d3f 100644 --- a/Mage.Sets/src/mage/cards/e/ExcavationElephant.java +++ b/Mage.Sets/src/mage/cards/e/ExcavationElephant.java @@ -4,7 +4,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -31,9 +31,7 @@ public final class ExcavationElephant extends CardImpl { this.addAbility(new KickerAbility("{1}{W}")); // When Excavation Elephant enters the battlefield, if it was kicked, return target artifact card from your graveyard to your hand. - Ability ability = new EntersBattlefieldTriggeredAbility( - new ReturnToHandTargetEffect(), false - ).withInterveningIf(KickedCondition.ONCE); + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect()).withInterveningIf(KickedCondition.ONCE); ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_ARTIFACT_FROM_YOUR_GRAVEYARD)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/Excise.java b/Mage.Sets/src/mage/cards/e/Excise.java index 6835e169b00..a4f8f1981ed 100644 --- a/Mage.Sets/src/mage/cards/e/Excise.java +++ b/Mage.Sets/src/mage/cards/e/Excise.java @@ -10,6 +10,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.AttackingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -27,7 +28,7 @@ public final class Excise extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{W}"); // Excise target nonwhite attacking creature unless its controller pays {X}. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DoUnlessTargetPlayerOrTargetsControllerPaysEffect(new ExileTargetEffect(), GetXValue.instance)); } diff --git a/Mage.Sets/src/mage/cards/e/ExclusionMage.java b/Mage.Sets/src/mage/cards/e/ExclusionMage.java index c1a4131f51f..00f1c8a2121 100644 --- a/Mage.Sets/src/mage/cards/e/ExclusionMage.java +++ b/Mage.Sets/src/mage/cards/e/ExclusionMage.java @@ -10,8 +10,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author TheElk801 @@ -28,7 +31,7 @@ public final class ExclusionMage extends CardImpl { // When Exclusion Mage enters the battlefield, return target creature an opponent controls to its owner's hand. Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/Excoriate.java b/Mage.Sets/src/mage/cards/e/Excoriate.java index 38be8444c5e..edda09c0155 100644 --- a/Mage.Sets/src/mage/cards/e/Excoriate.java +++ b/Mage.Sets/src/mage/cards/e/Excoriate.java @@ -8,6 +8,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -28,7 +29,7 @@ public final class Excoriate extends CardImpl { // Exile target tapped creature. this.getSpellAbility().addEffect(new ExileTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private Excoriate(final Excoriate card) { diff --git a/Mage.Sets/src/mage/cards/e/Execute.java b/Mage.Sets/src/mage/cards/e/Execute.java index bf6d2c3b1f0..a5171e8da13 100644 --- a/Mage.Sets/src/mage/cards/e/Execute.java +++ b/Mage.Sets/src/mage/cards/e/Execute.java @@ -10,6 +10,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -28,7 +29,7 @@ public final class Execute extends CardImpl { // Destroy target white creature. It can't be regenerated. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("
")); diff --git a/Mage.Sets/src/mage/cards/e/ExecutionersCapsule.java b/Mage.Sets/src/mage/cards/e/ExecutionersCapsule.java index be66a2ff068..0294badd5aa 100644 --- a/Mage.Sets/src/mage/cards/e/ExecutionersCapsule.java +++ b/Mage.Sets/src/mage/cards/e/ExecutionersCapsule.java @@ -11,8 +11,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author North @@ -25,7 +28,7 @@ public final class ExecutionersCapsule extends CardImpl { SimpleActivatedAbility ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new ManaCostsImpl<>("{1}{B}")); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + ability.addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/Exile.java b/Mage.Sets/src/mage/cards/e/Exile.java index 91802f519f4..ed76065c392 100644 --- a/Mage.Sets/src/mage/cards/e/Exile.java +++ b/Mage.Sets/src/mage/cards/e/Exile.java @@ -18,6 +18,7 @@ import mage.filter.predicate.permanent.AttackingPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -37,7 +38,7 @@ public final class Exile extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{W}"); // Exile target nonwhite attacking creature. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new ExileTargetEffect()); // You gain life equal to its toughness. this.getSpellAbility().addEffect(new ExileEffect()); diff --git a/Mage.Sets/src/mage/cards/e/Exorcist.java b/Mage.Sets/src/mage/cards/e/Exorcist.java index be5ead24428..499e8010b48 100644 --- a/Mage.Sets/src/mage/cards/e/Exorcist.java +++ b/Mage.Sets/src/mage/cards/e/Exorcist.java @@ -16,6 +16,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -41,7 +42,7 @@ public final class Exorcist extends CardImpl { new DestroyTargetEffect(), new ManaCostsImpl<>("{1}{W}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/ExoticPets.java b/Mage.Sets/src/mage/cards/e/ExoticPets.java index 441ed8c7749..0c51f90744c 100644 --- a/Mage.Sets/src/mage/cards/e/ExoticPets.java +++ b/Mage.Sets/src/mage/cards/e/ExoticPets.java @@ -1,6 +1,5 @@ package mage.cards.e; -import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; @@ -10,8 +9,7 @@ import mage.constants.Outcome; import mage.counters.CounterType; import mage.filter.FilterPermanent; import mage.filter.StaticFilters; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.permanent.PermanentIdPredicate; +import mage.filter.predicate.permanent.PermanentReferenceInCollectionPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.FishToken; @@ -102,11 +100,7 @@ class ExoticPetsEffect extends OneShotEffect { return true; } FilterPermanent filter = new FilterPermanent("creature"); - filter.add(Predicates.or(permanents - .stream() - .map(MageItem::getId) - .map(PermanentIdPredicate::new) - .collect(Collectors.toSet()))); + filter.add(new PermanentReferenceInCollectionPredicate(permanents, game)); TargetPermanent target = new TargetPermanent(filter); target.withNotTarget(true); for (CounterType counterType : counterTypes) { diff --git a/Mage.Sets/src/mage/cards/e/ExpelTheUnworthy.java b/Mage.Sets/src/mage/cards/e/ExpelTheUnworthy.java index c087d318889..5131200e499 100644 --- a/Mage.Sets/src/mage/cards/e/ExpelTheUnworthy.java +++ b/Mage.Sets/src/mage/cards/e/ExpelTheUnworthy.java @@ -16,11 +16,14 @@ import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetadjustment.ConditionalTargetAdjuster; import java.util.UUID; +import static mage.abilities.condition.common.KickedCondition.ONCE; + /** * @author Susucr */ @@ -44,8 +47,8 @@ public final class ExpelTheUnworthy extends CardImpl { this.getSpellAbility().addEffect(new ExileTargetEffect().setText("Exile the chosen creature")); this.getSpellAbility().addEffect(new ExpelTheUnworthyEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - this.getSpellAbility().setTargetAdjuster(new ConditionalTargetAdjuster(KickedCondition.ONCE, - new TargetCreaturePermanent(filter), new TargetCreaturePermanent())); + this.getSpellAbility().setTargetAdjuster(new ConditionalTargetAdjuster(ONCE, + new TargetPermanent(filter), new TargetCreaturePermanent())); } private ExpelTheUnworthy(final ExpelTheUnworthy card) { diff --git a/Mage.Sets/src/mage/cards/e/ExpendableTroops.java b/Mage.Sets/src/mage/cards/e/ExpendableTroops.java index 4974710688c..d66072bba4e 100644 --- a/Mage.Sets/src/mage/cards/e/ExpendableTroops.java +++ b/Mage.Sets/src/mage/cards/e/ExpendableTroops.java @@ -14,6 +14,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterAttackingOrBlockingCreature; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -33,7 +34,7 @@ public final class ExpendableTroops extends CardImpl { // {tap}, Sacrifice Expendable Troops: Expendable Troops deals 2 damage to target attacking or blocking creature. Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(2, "it"), new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(new FilterAttackingOrBlockingCreature())); + ability.addTarget(new TargetPermanent(new FilterAttackingOrBlockingCreature())); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/ExposeTheCulprit.java b/Mage.Sets/src/mage/cards/e/ExposeTheCulprit.java index 067b28df715..db51939cf8d 100644 --- a/Mage.Sets/src/mage/cards/e/ExposeTheCulprit.java +++ b/Mage.Sets/src/mage/cards/e/ExposeTheCulprit.java @@ -46,7 +46,7 @@ public final class ExposeTheCulprit extends CardImpl { // * Turn target face-down creature face up. this.getSpellAbility().addEffect(new TurnFaceUpTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // * Exile any number of face-up creatures you control with disguise in a face-down pile, shuffle that pile, then cloak them. Mode mode = new Mode(new ExposeTheCulpritEffect()); diff --git a/Mage.Sets/src/mage/cards/e/Expunge.java b/Mage.Sets/src/mage/cards/e/Expunge.java index eb89c44253f..f63805c17f0 100644 --- a/Mage.Sets/src/mage/cards/e/Expunge.java +++ b/Mage.Sets/src/mage/cards/e/Expunge.java @@ -12,6 +12,7 @@ import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -32,7 +33,7 @@ public final class Expunge extends CardImpl { // Destroy target nonartifact, nonblack creature. It can't be regenerated. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); // Cycling {2} ({2}, Discard this card: Draw a card.) diff --git a/Mage.Sets/src/mage/cards/e/EyeblightAssassin.java b/Mage.Sets/src/mage/cards/e/EyeblightAssassin.java index a4e9edb5c25..5c59e42ad94 100644 --- a/Mage.Sets/src/mage/cards/e/EyeblightAssassin.java +++ b/Mage.Sets/src/mage/cards/e/EyeblightAssassin.java @@ -12,8 +12,11 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Duration; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author fireshoes @@ -29,7 +32,7 @@ public final class EyeblightAssassin extends CardImpl { // When Eyeblight Assassin enters the battlefield, target creature an opponent controls gets -1/-1 until end of turn. Ability ability = new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(-1,-1, Duration.EndOfTurn)); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/e/EyeblightsEnding.java b/Mage.Sets/src/mage/cards/e/EyeblightsEnding.java index ce39d520ebe..d4917999126 100644 --- a/Mage.Sets/src/mage/cards/e/EyeblightsEnding.java +++ b/Mage.Sets/src/mage/cards/e/EyeblightsEnding.java @@ -9,6 +9,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -28,7 +29,7 @@ public final class EyeblightsEnding extends CardImpl { this.subtype.add(SubType.ELF); this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private EyeblightsEnding(final EyeblightsEnding card) { diff --git a/Mage.Sets/src/mage/cards/e/EzuriClawOfProgress.java b/Mage.Sets/src/mage/cards/e/EzuriClawOfProgress.java index f5905104315..dfd49b0ef2c 100644 --- a/Mage.Sets/src/mage/cards/e/EzuriClawOfProgress.java +++ b/Mage.Sets/src/mage/cards/e/EzuriClawOfProgress.java @@ -2,21 +2,21 @@ package mage.cards.e; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.CountersControllerCount; import mage.abilities.effects.common.counter.AddCountersPlayersEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.counters.CounterType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.mageobject.PowerPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -25,15 +25,18 @@ import java.util.UUID; */ public final class EzuriClawOfProgress extends CardImpl { - final private static FilterControlledCreaturePermanent filter - = new FilterControlledCreaturePermanent("a creature with power 2 or less"); - final private static FilterControlledCreaturePermanent filter2 = new FilterControlledCreaturePermanent(); + final private static FilterPermanent filter + = new FilterControlledCreaturePermanent("a creature you control with power 2 or less"); + final private static FilterPermanent filter2 + = new FilterControlledCreaturePermanent("another target creature you control"); static { filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 3)); filter2.add(AnotherPredicate.instance); } + private static final DynamicValue xValue = new CountersControllerCount(CounterType.EXPERIENCE); + public EzuriClawOfProgress(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{U}"); this.supertype.add(SuperType.LEGENDARY); @@ -44,13 +47,17 @@ public final class EzuriClawOfProgress extends CardImpl { this.toughness = new MageInt(3); // Whenever a creature with power 2 or less you control enters, you get an experience counter. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility(new AddCountersPlayersEffect( - CounterType.EXPERIENCE.createInstance(), TargetController.YOU - ), filter)); + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + new AddCountersPlayersEffect(CounterType.EXPERIENCE.createInstance(), TargetController.YOU), filter + )); // At the beginning of combat on your turn, put X +1/+1 counters on another target creature you control, where X is the number of experience counters you have. - Ability ability = new BeginningOfCombatTriggeredAbility(new EzuriClawOfProgressEffect()); - ability.addTarget(new TargetControlledCreaturePermanent(filter2)); + Ability ability = new BeginningOfCombatTriggeredAbility( + new AddCountersTargetEffect(CounterType.P1P1.createInstance(), xValue) + .setText("put X +1/+1 counters on another target creature you control, " + + "where X is the number of experience counters you have") + ); + ability.addTarget(new TargetPermanent(filter2)); this.addAbility(ability); } @@ -63,34 +70,3 @@ public final class EzuriClawOfProgress extends CardImpl { return new EzuriClawOfProgress(this); } } - -class EzuriClawOfProgressEffect extends OneShotEffect { - - EzuriClawOfProgressEffect() { - super(Outcome.Benefit); - this.staticText = "put X +1/+1 counters on another target creature you control, where X is the number of experience counters you have"; - } - - private EzuriClawOfProgressEffect(final EzuriClawOfProgressEffect effect) { - super(effect); - } - - @Override - public EzuriClawOfProgressEffect copy() { - return new EzuriClawOfProgressEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Permanent target = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (target != null) { - int amount = controller.getCountersCount(CounterType.EXPERIENCE); - target.addCounters(CounterType.P1P1.createInstance(amount), source.getControllerId(), source, game); - } - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/f/FaeOffering.java b/Mage.Sets/src/mage/cards/f/FaeOffering.java index 9bde1f335e5..3b5afcea5ce 100644 --- a/Mage.Sets/src/mage/cards/f/FaeOffering.java +++ b/Mage.Sets/src/mage/cards/f/FaeOffering.java @@ -1,11 +1,10 @@ package mage.cards.f; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.hint.Hint; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -31,13 +30,10 @@ public final class FaeOffering extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); // At the beginning of each end step, if you've cast both a creature spell and a noncreature spell this turn, create a Clue token, a Food token, and a Treasure token. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - TargetController.ANY, new CreateTokenEffect(new ClueArtifactToken()).withAdditionalTokens(new FoodToken(), new TreasureToken()), - false - ), FaeOfferingCondition.instance, "At the beginning of each end step, " + - "if you've cast both a creature spell and a noncreature spell this turn, " + - "create a Clue token, a Food token, and a Treasure token." + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.ANY, new CreateTokenEffect(new ClueArtifactToken()) + .withAdditionalTokens(new FoodToken(), new TreasureToken()), + false, FaeOfferingCondition.instance ).addHint(FaeOfferingHint.instance)); } @@ -68,6 +64,11 @@ enum FaeOfferingCondition implements Condition { .distinct() .count() == 2; } + + @Override + public String toString() { + return "you've cast both a creature spell and a noncreature spell this turn"; + } } enum FaeOfferingHint implements Hint { diff --git a/Mage.Sets/src/mage/cards/f/FaerieMiscreant.java b/Mage.Sets/src/mage/cards/f/FaerieMiscreant.java index 420ad7e05e1..e94401382b3 100644 --- a/Mage.Sets/src/mage/cards/f/FaerieMiscreant.java +++ b/Mage.Sets/src/mage/cards/f/FaerieMiscreant.java @@ -4,17 +4,16 @@ import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; 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.constants.TargetController; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.predicate.mageobject.NamePredicate; import java.util.UUID; @@ -23,12 +22,12 @@ import java.util.UUID; */ public final class FaerieMiscreant extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + private static final FilterPermanent filter + = new FilterControlledCreaturePermanent("you control another creature named Faerie Miscreant"); static { filter.add(new NamePredicate("Faerie Miscreant")); filter.add(AnotherPredicate.instance); - filter.add(TargetController.YOU.getControllerPredicate()); } private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); @@ -44,12 +43,9 @@ public final class FaerieMiscreant extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When Faerie Miscreant enters the battlefield, if you control another creature named Faerie Miscreant, draw a card. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility( - new DrawCardSourceControllerEffect(1), false - ), condition, "When {this} enters, " + - "if you control another creature named Faerie Miscreant, draw a card." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new DrawCardSourceControllerEffect(1), false + ).withInterveningIf(condition)); } private FaerieMiscreant(final FaerieMiscreant card) { diff --git a/Mage.Sets/src/mage/cards/f/FairgroundsTrumpeter.java b/Mage.Sets/src/mage/cards/f/FairgroundsTrumpeter.java index 7af99a34ab5..1d76e291772 100644 --- a/Mage.Sets/src/mage/cards/f/FairgroundsTrumpeter.java +++ b/Mage.Sets/src/mage/cards/f/FairgroundsTrumpeter.java @@ -1,15 +1,10 @@ - package mage.cards.f; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -22,6 +17,10 @@ import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.watchers.Watcher; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + /** * @author spjspj */ @@ -34,11 +33,10 @@ public final class FairgroundsTrumpeter extends CardImpl { this.toughness = new MageInt(2); // At the beginning of each end step, if a +1/+1 counter was put on a permanent under your control this turn, put a +1/+1 counter on Fairgrounds Trumpeter. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfEndStepTriggeredAbility( - TargetController.ANY, new AddCountersSourceEffect(CounterType.P1P1.createInstance()), - false), FairgroundsTrumpeterCondition.instance, - "At the beginning of each end step, if a +1/+1 counter was put on a permanent under your control this turn, put a +1/+1 counter on {this}."), - new FairgroundsTrumpeterWatcher()); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.ANY, new AddCountersSourceEffect(CounterType.P1P1.createInstance()), + false, FairgroundsTrumpeterCondition.instance + ), new FairgroundsTrumpeterWatcher()); } private FairgroundsTrumpeter(final FairgroundsTrumpeter card) { @@ -52,7 +50,6 @@ public final class FairgroundsTrumpeter extends CardImpl { } enum FairgroundsTrumpeterCondition implements Condition { - instance; @Override @@ -63,7 +60,7 @@ enum FairgroundsTrumpeterCondition implements Condition { @Override public String toString() { - return "if a +1/+1 counter was put on a permanent under your control this turn"; + return "a +1/+1 counter was put on a permanent under your control this turn"; } } @@ -97,5 +94,4 @@ class FairgroundsTrumpeterWatcher extends Watcher { public boolean p1p1AddedToPermanent(UUID playerId) { return players.contains(playerId); } - } diff --git a/Mage.Sets/src/mage/cards/f/FalkenrathPitFighter.java b/Mage.Sets/src/mage/cards/f/FalkenrathPitFighter.java index 00b329f6310..65ce6db2c6b 100644 --- a/Mage.Sets/src/mage/cards/f/FalkenrathPitFighter.java +++ b/Mage.Sets/src/mage/cards/f/FalkenrathPitFighter.java @@ -13,9 +13,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.common.FilterControlledPermanent; -import mage.target.common.TargetControlledPermanent; import java.util.UUID; @@ -36,7 +34,7 @@ public final class FalkenrathPitFighter extends CardImpl { // {1}{R}, Discard a card, Sacrifice a Vampire: Draw two cards. Activate only if an opponent lost life this turn. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(2), + new DrawCardSourceControllerEffect(2), new ManaCostsImpl<>("{1}{R}"), OpponentsLostLifeCondition.instance ); ability.addCost(new DiscardCardCost()); diff --git a/Mage.Sets/src/mage/cards/f/FallOfTheFirstCivilization.java b/Mage.Sets/src/mage/cards/f/FallOfTheFirstCivilization.java index ca51988dc54..fd4a87acacb 100644 --- a/Mage.Sets/src/mage/cards/f/FallOfTheFirstCivilization.java +++ b/Mage.Sets/src/mage/cards/f/FallOfTheFirstCivilization.java @@ -19,7 +19,6 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPermanent; -import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetOpponent; import mage.util.CardUtil; @@ -46,7 +45,7 @@ public final class FallOfTheFirstCivilization extends CardImpl { sagaAbility.addChapterEffect( this, SagaChapter.CHAPTER_I, new Effects( - new DrawCardSourceControllerEffect(1).setText("you"), + new DrawCardSourceControllerEffect(2).setText("you"), new DrawCardTargetEffect(2).setText("and target opponent each draw two cards") ), new TargetOpponent() ); @@ -114,7 +113,7 @@ class FallOfTheFirstCivilizationEffect extends OneShotEffect { )); break; default: - TargetPermanent target = new TargetControlledCreaturePermanent(3); + TargetPermanent target = new TargetPermanent(3, StaticFilters.FILTER_CONTROLLED_PERMANENT_NON_LAND); target.withNotTarget(true); target.withChooseHint("to prevent being destroyed"); player.choose(outcome, target, source, game); diff --git a/Mage.Sets/src/mage/cards/f/FallOfTheHammer.java b/Mage.Sets/src/mage/cards/f/FallOfTheHammer.java index bbb08650196..0211ca6618b 100644 --- a/Mage.Sets/src/mage/cards/f/FallOfTheHammer.java +++ b/Mage.Sets/src/mage/cards/f/FallOfTheHammer.java @@ -1,52 +1,34 @@ - package mage.cards.f; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageWithPowerFromOneToAnotherTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.other.AnotherTargetPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; /** - * - * * As Fall of the Hammer tries to resolve, if only one of the targets is legal, * Fall of the Hammer will still resolve but will have no effect: If the first * target creature is illegal, it can't deal damage to anything. If the second * target creature is illegal, it can't be dealt damage. - * + *

* The amount of damage dealt is based on the first target creature's power as Fall of the Hammer resolves. - - + * * @author LevelX2 */ public final class FallOfTheHammer extends CardImpl { public FallOfTheHammer(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{R}"); - + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}"); // Target creature you control deals damage equal to its power to another target creature. - this.getSpellAbility().addEffect(new FallOfTheHammerDamageEffect()); - TargetControlledCreaturePermanent target = - new TargetControlledCreaturePermanent(new FilterControlledCreaturePermanent("Target creature: deals damage")); - target.setTargetTag(1); - this.getSpellAbility().addTarget(target); - - FilterCreaturePermanent filter = new FilterCreaturePermanent("Another creature: damage dealt to"); - filter.add(new AnotherTargetPredicate(2)); - TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter); - target2.setTargetTag(2); - this.getSpellAbility().addTarget(target2); + this.getSpellAbility().addEffect(new DamageWithPowerFromOneToAnotherTargetEffect()); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent().withChooseHint("to deal damage").setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2).withChooseHint("to receive damage").setTargetTag(2)); } private FallOfTheHammer(final FallOfTheHammer card) { @@ -58,34 +40,3 @@ public final class FallOfTheHammer extends CardImpl { return new FallOfTheHammer(this); } } - -class FallOfTheHammerDamageEffect extends OneShotEffect { - - FallOfTheHammerDamageEffect() { - super(Outcome.Damage); - this.staticText = "Target creature you control deals damage equal to its power to another target creature"; - } - - private FallOfTheHammerDamageEffect(final FallOfTheHammerDamageEffect effect) { - super(effect); - } - - @Override - public FallOfTheHammerDamageEffect copy() { - return new FallOfTheHammerDamageEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent ownCreature = game.getPermanent(source.getFirstTarget()); - if (ownCreature != null) { - int damage = ownCreature.getPower().getValue(); - Permanent targetCreature = game.getPermanent(source.getTargets().get(1).getFirstTarget()); - if (targetCreature != null) { - targetCreature.damage(damage, ownCreature.getId(), source, game, false, true); - return true; - } - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/f/FallOfTheImpostor.java b/Mage.Sets/src/mage/cards/f/FallOfTheImpostor.java index 03896538e0a..b99c4a83d8e 100644 --- a/Mage.Sets/src/mage/cards/f/FallOfTheImpostor.java +++ b/Mage.Sets/src/mage/cards/f/FallOfTheImpostor.java @@ -1,16 +1,16 @@ package mage.cards.f; -import java.util.List; -import java.util.UUID; - +import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SagaAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; -import mage.constants.*; 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.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; @@ -18,11 +18,14 @@ import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetOpponent; +import java.util.List; +import java.util.UUID; + /** - * * @author weirddan455 */ public final class FallOfTheImpostor extends CardImpl { @@ -77,33 +80,35 @@ class FallOfTheImpostorEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - Player opponent = game.getPlayer(source.getFirstTarget()); - if (controller != null && opponent != null) { - List permanents = game.getBattlefield().getAllActivePermanents( - StaticFilters.FILTER_PERMANENT_CREATURE, opponent.getId(), game - ); - Integer maxPower = null; - for (Permanent permanent : permanents) { - if (permanent != null) { - int power = permanent.getPower().getValue(); - if (maxPower == null || power > maxPower) { - maxPower = power; - } - } - } - if (maxPower != null) { - FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(new ControllerIdPredicate(opponent.getId())); - filter.add(new PowerPredicate(ComparisonType.EQUAL_TO, maxPower)); - TargetCreaturePermanent target = new TargetCreaturePermanent(1, 1, filter, true); - controller.chooseTarget(outcome, target, source, game); - Permanent permanent = game.getPermanent(target.getFirstTarget()); - if (permanent != null) { - controller.moveCardsToExile(permanent, source, game, true, null, null); - return true; - } - } + Player opponent = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (controller == null || opponent == null) { + return false; } - return false; + List permanents = game.getBattlefield().getActivePermanents( + StaticFilters.FILTER_CONTROLLED_CREATURE, opponent.getId(), game + ); + Permanent permanent; + switch (permanents.size()) { + case 0: + return false; + case 1: + permanent = permanents.get(0); + break; + default: + int power = permanents + .stream() + .map(MageObject::getPower) + .mapToInt(MageInt::getValue) + .max() + .orElse(Integer.MIN_VALUE); + FilterPermanent filter = new FilterCreaturePermanent(); + filter.add(new ControllerIdPredicate(opponent.getId())); + filter.add(new PowerPredicate(ComparisonType.OR_GREATER, power)); + TargetPermanent target = new TargetPermanent(filter); + target.withNotTarget(true); + controller.chooseTarget(outcome, target, source, game); + permanent = game.getPermanent(target.getFirstTarget()); + } + return permanent != null && controller.moveCards(permanent, Zone.EXILED, source, game); } } diff --git a/Mage.Sets/src/mage/cards/f/FallingTimber.java b/Mage.Sets/src/mage/cards/f/FallingTimber.java index 388938cccfa..8871740caec 100644 --- a/Mage.Sets/src/mage/cards/f/FallingTimber.java +++ b/Mage.Sets/src/mage/cards/f/FallingTimber.java @@ -1,6 +1,5 @@ package mage.cards.f; -import mage.abilities.condition.common.KickedCondition; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.effects.Effect; import mage.abilities.effects.common.PreventDamageByTargetEffect; @@ -15,6 +14,8 @@ import mage.target.targetadjustment.ConditionalTargetAdjuster; import java.util.UUID; +import static mage.abilities.condition.common.KickedCondition.ONCE; + /** * @author LoneFox */ @@ -33,8 +34,7 @@ public final class FallingTimber extends CardImpl { "prevent all combat damage another target creature would deal this turn."); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - this.getSpellAbility().setTargetAdjuster(new ConditionalTargetAdjuster(KickedCondition.ONCE, - new TargetCreaturePermanent(2))); + this.getSpellAbility().setTargetAdjuster(new ConditionalTargetAdjuster(ONCE, new TargetCreaturePermanent(2))); } private FallingTimber(final FallingTimber card) { diff --git a/Mage.Sets/src/mage/cards/f/FamiliarsRuse.java b/Mage.Sets/src/mage/cards/f/FamiliarsRuse.java index 7a5bf7a937c..320219f4ee2 100644 --- a/Mage.Sets/src/mage/cards/f/FamiliarsRuse.java +++ b/Mage.Sets/src/mage/cards/f/FamiliarsRuse.java @@ -1,28 +1,26 @@ - package mage.cards.f; -import java.util.UUID; import mage.abilities.costs.common.ReturnToHandChosenControlledPermanentCost; import mage.abilities.effects.common.CounterTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.common.FilterControlledCreaturePermanent; import mage.target.TargetSpell; import mage.target.common.TargetControlledCreaturePermanent; +import java.util.UUID; + /** - * * @author Loki */ public final class FamiliarsRuse extends CardImpl { public FamiliarsRuse(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}{U}"); // As an additional cost to cast Familiar's Ruse, return a creature you control to its owner's hand. - this.getSpellAbility().addCost(new ReturnToHandChosenControlledPermanentCost( - new TargetControlledCreaturePermanent(1, 1, new FilterControlledCreaturePermanent("creature"), true))); + this.getSpellAbility().addCost(new ReturnToHandChosenControlledPermanentCost(new TargetControlledCreaturePermanent())); + // Counter target spell. this.getSpellAbility().addEffect(new CounterTargetEffect()); this.getSpellAbility().addTarget(new TargetSpell()); diff --git a/Mage.Sets/src/mage/cards/f/FamishedForagers.java b/Mage.Sets/src/mage/cards/f/FamishedForagers.java index 0caf83609e8..63a0547c5f1 100644 --- a/Mage.Sets/src/mage/cards/f/FamishedForagers.java +++ b/Mage.Sets/src/mage/cards/f/FamishedForagers.java @@ -8,7 +8,6 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.OpponentsLostLifeCondition; import mage.abilities.costs.common.DiscardCardCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.mana.BasicManaEffect; import mage.abilities.hint.common.OpponentsLostLifeHint; @@ -32,11 +31,8 @@ public final class FamishedForagers extends CardImpl { this.toughness = new MageInt(3); // When Famished Foragers enters the battlefield, if an opponent lost life this turn, add {R}{R}{R}. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new BasicManaEffect(Mana.RedMana(3))), - OpponentsLostLifeCondition.instance, "When {this} enters, " + - "if an opponent lost life this turn, add {R}{R}{R}." - ).addHint(OpponentsLostLifeHint.instance)); + this.addAbility(new EntersBattlefieldTriggeredAbility(new BasicManaEffect(Mana.RedMana(3))) + .withInterveningIf(OpponentsLostLifeCondition.instance).addHint(OpponentsLostLifeHint.instance)); // {2}{R}, Discard a card: Draw a card. Ability ability = new SimpleActivatedAbility( diff --git a/Mage.Sets/src/mage/cards/f/FanaticOfXenagos.java b/Mage.Sets/src/mage/cards/f/FanaticOfXenagos.java index c46bc90550b..8644f5854a2 100644 --- a/Mage.Sets/src/mage/cards/f/FanaticOfXenagos.java +++ b/Mage.Sets/src/mage/cards/f/FanaticOfXenagos.java @@ -1,11 +1,9 @@ - package mage.cards.f; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TributeNotPaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.HasteAbility; @@ -34,13 +32,18 @@ public final class FanaticOfXenagos extends CardImpl { // Trample this.addAbility(TrampleAbility.getInstance()); + // Tribute 1 this.addAbility(new TributeAbility(1)); + // When Fanatic of Xenagos enters the battlefield, if tribute wasn't paid, it gets +1/+1 and gains haste until end of turn. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new BoostSourceEffect(1, 1, Duration.EndOfTurn)); - ability.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.EndOfTurn)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TributeNotPaidCondition.instance, - "When {this} enters, if tribute wasn't paid, it gets +1/+1 and gains haste until end of turn.")); + Ability ability = new EntersBattlefieldTriggeredAbility( + new BoostSourceEffect(1, 1, Duration.EndOfTurn).setText("it gets +1/+1") + ).withInterveningIf(TributeNotPaidCondition.instance); + ability.addEffect(new GainAbilitySourceEffect( + HasteAbility.getInstance(), Duration.EndOfTurn + ).setText("and gains haste until end of turn")); + this.addAbility(ability); } private FanaticOfXenagos(final FanaticOfXenagos card) { diff --git a/Mage.Sets/src/mage/cards/f/FangOfThePack.java b/Mage.Sets/src/mage/cards/f/FangOfThePack.java index 3f5c064dfba..9f7e2b608ef 100644 --- a/Mage.Sets/src/mage/cards/f/FangOfThePack.java +++ b/Mage.Sets/src/mage/cards/f/FangOfThePack.java @@ -1,21 +1,21 @@ package mage.cards.f; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.MeleeAbility; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; 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.filter.StaticFilters; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author Styxo */ public final class FangOfThePack extends CardImpl { @@ -32,7 +32,7 @@ public final class FangOfThePack extends CardImpl { // At the beginning of combat on your turn, another target creature you control gains melee until end of turn. Ability ability = new BeginningOfCombatTriggeredAbility(new GainAbilityTargetEffect(new MeleeAbility(), Duration.EndOfTurn)); - ability.addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/FangSkulkin.java b/Mage.Sets/src/mage/cards/f/FangSkulkin.java index 0ed4a8ead57..334fdf1b3cb 100644 --- a/Mage.Sets/src/mage/cards/f/FangSkulkin.java +++ b/Mage.Sets/src/mage/cards/f/FangSkulkin.java @@ -17,6 +17,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -36,7 +37,7 @@ public final class FangSkulkin extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(WitherAbility.getInstance(), Duration.EndOfTurn), new GenericManaCost(2)); - ability.addTarget(new TargetCreaturePermanent(filterBlackCreature)); + ability.addTarget(new TargetPermanent(filterBlackCreature)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/FaramirStewardOfGondor.java b/Mage.Sets/src/mage/cards/f/FaramirStewardOfGondor.java index 252036d6c90..5144ca7f5d8 100644 --- a/Mage.Sets/src/mage/cards/f/FaramirStewardOfGondor.java +++ b/Mage.Sets/src/mage/cards/f/FaramirStewardOfGondor.java @@ -1,12 +1,12 @@ package mage.cards.f; import mage.MageInt; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.condition.common.MonarchIsSourceControllerCondition; import mage.abilities.effects.common.BecomesMonarchSourceEffect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.hint.common.MonarchHint; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -23,7 +23,7 @@ import java.util.UUID; public final class FaramirStewardOfGondor extends CardImpl { private static final FilterPermanent filter - = new FilterControlledCreaturePermanent("a legendary creature with mana value 4 or greater"); + = new FilterControlledCreaturePermanent("a legendary creature you control with mana value 4 or greater"); static { filter.add(SuperType.LEGENDARY.getPredicate()); @@ -40,7 +40,7 @@ public final class FaramirStewardOfGondor extends CardImpl { this.toughness = new MageInt(2); // Whenever a legendary creature with mana value 4 or greater you control enters, you become the monarch. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility(new BecomesMonarchSourceEffect(), filter).addHint(MonarchHint.instance)); + this.addAbility(new EntersBattlefieldAllTriggeredAbility(new BecomesMonarchSourceEffect(), filter).addHint(MonarchHint.instance)); // At the beginning of your end step, if you're the monarch, create two 1/1 white Human Soldier creature tokens. this.addAbility(new BeginningOfEndStepTriggeredAbility( diff --git a/Mage.Sets/src/mage/cards/f/FarsightMask.java b/Mage.Sets/src/mage/cards/f/FarsightMask.java index 16b3ee4835f..fe103a80d18 100644 --- a/Mage.Sets/src/mage/cards/f/FarsightMask.java +++ b/Mage.Sets/src/mage/cards/f/FarsightMask.java @@ -2,7 +2,6 @@ package mage.cards.f; import mage.abilities.common.SourceDealsDamageToYouTriggeredAbility; import mage.abilities.condition.common.SourceTappedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -15,15 +14,13 @@ import java.util.UUID; */ public final class FarsightMask extends CardImpl { - private static final String rule = "Whenever a source an opponent controls deals damage to you, if {this} is untapped, you may draw a card."; - public FarsightMask(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}"); // Whenever a source an opponent controls deals damage to you, if Farsight Mask is untapped, you may draw a card. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new SourceDealsDamageToYouTriggeredAbility( + this.addAbility(new SourceDealsDamageToYouTriggeredAbility( new DrawCardSourceControllerEffect(1), true - ), SourceTappedCondition.UNTAPPED, rule)); + ).withInterveningIf(SourceTappedCondition.UNTAPPED)); } private FarsightMask(final FarsightMask card) { diff --git a/Mage.Sets/src/mage/cards/f/FateTransfer.java b/Mage.Sets/src/mage/cards/f/FateTransfer.java index 358fcd3c1ed..1e5b0d36d0f 100644 --- a/Mage.Sets/src/mage/cards/f/FateTransfer.java +++ b/Mage.Sets/src/mage/cards/f/FateTransfer.java @@ -1,7 +1,5 @@ - package mage.cards.f; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; @@ -9,36 +7,26 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; import mage.counters.Counter; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.other.AnotherTargetPredicate; +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 jeffwadsworth */ public final class FateTransfer extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("target creature to move all counters from"); - private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("another target creature to move all counters to"); - public FateTransfer(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U/B}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U/B}"); // Move all counters from target creature onto another target creature. this.getSpellAbility().addEffect(new FateTransferEffect()); - - TargetCreaturePermanent fromTarget = new TargetCreaturePermanent(filter); - fromTarget.setTargetTag(1); - this.getSpellAbility().addTarget(fromTarget); - - TargetCreaturePermanent toTarget = new TargetCreaturePermanent(filter2); - filter2.add(new AnotherTargetPredicate(2)); - toTarget.setTargetTag(2); - this.getSpellAbility().addTarget(toTarget); - + this.getSpellAbility().addTarget(new TargetCreaturePermanent().withChooseHint("to remove counters from").setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2).setTargetTag(2)); } private FateTransfer(final FateTransfer card) { diff --git a/Mage.Sets/src/mage/cards/f/FathomFleetCaptain.java b/Mage.Sets/src/mage/cards/f/FathomFleetCaptain.java index b90388e91cf..43ce66c3a56 100644 --- a/Mage.Sets/src/mage/cards/f/FathomFleetCaptain.java +++ b/Mage.Sets/src/mage/cards/f/FathomFleetCaptain.java @@ -1,12 +1,11 @@ package mage.cards.f; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.keyword.MenaceAbility; @@ -15,24 +14,27 @@ 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.mageobject.AnotherPredicate; import mage.filter.predicate.permanent.TokenPredicate; import mage.game.permanent.token.PirateToken; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class FathomFleetCaptain extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("another nontoken Pirate"); + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.PIRATE, "you control another nontoken Pirate"); static { - filter.add(SubType.PIRATE.getPredicate()); filter.add(AnotherPredicate.instance); filter.add(TokenPredicate.FALSE); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); + public FathomFleetCaptain(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); @@ -45,10 +47,9 @@ public final class FathomFleetCaptain extends CardImpl { this.addAbility(new MenaceAbility(false)); // Whenever Fathom Fleet Captain attacks, if you control another nontoken Pirate, you may pay {2}. If you do, creature a 2/2 black Pirate creature token with menace. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new DoIfCostPaid(new CreateTokenEffect(new PirateToken()), new GenericManaCost(2)), false), - new PermanentsOnTheBattlefieldCondition(filter), - "Whenever {this} attacks, if you control another nontoken Pirate, you may pay {2}. If you do, create a 2/2 black Pirate creature token with menace")); + this.addAbility(new AttacksTriggeredAbility( + new DoIfCostPaid(new CreateTokenEffect(new PirateToken()), new GenericManaCost(2)) + ).withInterveningIf(condition)); } private FathomFleetCaptain(final FathomFleetCaptain card) { diff --git a/Mage.Sets/src/mage/cards/f/FearOfAbduction.java b/Mage.Sets/src/mage/cards/f/FearOfAbduction.java index 72792029d78..6deb44b115d 100644 --- a/Mage.Sets/src/mage/cards/f/FearOfAbduction.java +++ b/Mage.Sets/src/mage/cards/f/FearOfAbduction.java @@ -21,10 +21,13 @@ import mage.filter.StaticFilters; import mage.game.ExileZone; import mage.game.Game; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; import mage.util.CardUtil; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * @author Cguy7777 */ @@ -46,7 +49,7 @@ public final class FearOfAbduction extends CardImpl { // When Fear of Abduction enters, exile target creature an opponent controls. Ability ability = new EntersBattlefieldTriggeredAbility(new FearOfAbductionExileEffect()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); // When Fear of Abduction leaves the battlefield, put each card exiled with it into its owner's hand. diff --git a/Mage.Sets/src/mage/cards/f/FearOfBurningAlive.java b/Mage.Sets/src/mage/cards/f/FearOfBurningAlive.java index 0f04e9a404f..a8eb54fb63c 100644 --- a/Mage.Sets/src/mage/cards/f/FearOfBurningAlive.java +++ b/Mage.Sets/src/mage/cards/f/FearOfBurningAlive.java @@ -1,8 +1,9 @@ package mage.cards.f; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SourceDealsNoncombatDamageToOpponentTriggeredAbility; import mage.abilities.condition.common.DeliriumCondition; import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.dynamicvalue.common.SavedDamageValue; @@ -11,13 +12,9 @@ import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.game.events.DamagedEvent; -import mage.game.events.GameEvent; import mage.target.TargetPermanent; +import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster; import java.util.UUID; @@ -39,7 +36,13 @@ public final class FearOfBurningAlive extends CardImpl { )); // Delirium -- Whenever a source you control deals noncombat damage to an opponent, if there are four or more card types among cards in your graveyard, Fear of Burning Alive deals that amount of damage to target creature that player controls. - this.addAbility(new FearOfBurningAliveTriggeredAbility()); + TriggeredAbility ability = new SourceDealsNoncombatDamageToOpponentTriggeredAbility(new DamageTargetEffect(SavedDamageValue.AMOUNT), SetTargetPointer.PLAYER); + ability.addTarget(new TargetPermanent(new FilterCreaturePermanent("creature that player controls"))); + ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster()); + ability.withInterveningIf(DeliriumCondition.instance); + ability.setAbilityWord(AbilityWord.DELIRIUM); + ability.addHint(CardTypesInGraveyardCount.YOU.getHint()); + this.addAbility(ability); } private FearOfBurningAlive(final FearOfBurningAlive card) { @@ -51,49 +54,3 @@ public final class FearOfBurningAlive extends CardImpl { return new FearOfBurningAlive(this); } } - -class FearOfBurningAliveTriggeredAbility extends TriggeredAbilityImpl { - - FearOfBurningAliveTriggeredAbility() { - super(Zone.BATTLEFIELD, new DamageTargetEffect(SavedDamageValue.MANY) - .setText("{this} deals that amount of damage to target creature that player controls")); - this.setTriggerPhrase("Whenever a source you control deals noncombat damage to an opponent, " + - "if there are four or more card types among cards in your graveyard, "); - this.setAbilityWord(AbilityWord.DELIRIUM); - this.addHint(CardTypesInGraveyardCount.YOU.getHint()); - } - - private FearOfBurningAliveTriggeredAbility(final FearOfBurningAliveTriggeredAbility ability) { - super(ability); - } - - @Override - public FearOfBurningAliveTriggeredAbility copy() { - return new FearOfBurningAliveTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (((DamagedEvent) event).isCombatDamage() - || !isControlledBy(game.getControllerId(event.getSourceId())) - || !game.getOpponents(getControllerId()).contains(event.getTargetId())) { - return false; - } - this.getEffects().setValue("damage", event.getAmount()); - FilterPermanent filter = new FilterCreaturePermanent(); - filter.add(new ControllerIdPredicate(event.getTargetId())); - this.getTargets().clear(); - this.addTarget(new TargetPermanent(filter)); - return true; - } - - @Override - public boolean checkInterveningIfClause(Game game) { - return DeliriumCondition.instance.apply(game, this); - } -} diff --git a/Mage.Sets/src/mage/cards/f/FearOfMissingOut.java b/Mage.Sets/src/mage/cards/f/FearOfMissingOut.java index fc56747b5da..7dabdb2455e 100644 --- a/Mage.Sets/src/mage/cards/f/FearOfMissingOut.java +++ b/Mage.Sets/src/mage/cards/f/FearOfMissingOut.java @@ -5,7 +5,6 @@ import mage.abilities.Ability; import mage.abilities.common.AttacksFirstTimeTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.DeliriumCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.effects.common.AdditionalCombatPhaseEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; @@ -13,6 +12,7 @@ import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.effects.common.discard.DiscardControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; import mage.target.common.TargetCreaturePermanent; @@ -37,16 +37,10 @@ public final class FearOfMissingOut extends CardImpl { this.addAbility(ability); // Delirium -- Whenever Fear of Missing Out attacks for the first time each turn, if there are four or more card types among cards in your graveyard, untap target creature. After this phase, there is an additional combat phase. - ability = new ConditionalInterveningIfTriggeredAbility( - new AttacksFirstTimeTriggeredAbility(new UntapTargetEffect(), false), - DeliriumCondition.instance, "Delirium — Whenever {this} attacks for the first time each turn, " - + "if there are four or more card types among cards in your graveyard, untap target creature. " - + "After this phase, there is an additional combat phase." - ); + ability = new AttacksFirstTimeTriggeredAbility(new UntapTargetEffect(), false).withInterveningIf(DeliriumCondition.instance); ability.addTarget(new TargetCreaturePermanent()); ability.addEffect(new AdditionalCombatPhaseEffect()); - ability.addHint(CardTypesInGraveyardCount.YOU.getHint()); - this.addAbility(ability); + this.addAbility(ability.setAbilityWord(AbilityWord.DELIRIUM).addHint(CardTypesInGraveyardCount.YOU.getHint())); } private FearOfMissingOut(final FearOfMissingOut card) { diff --git a/Mage.Sets/src/mage/cards/f/FearOfTheDark.java b/Mage.Sets/src/mage/cards/f/FearOfTheDark.java index f316b1b50a2..f7af03b0178 100644 --- a/Mage.Sets/src/mage/cards/f/FearOfTheDark.java +++ b/Mage.Sets/src/mage/cards/f/FearOfTheDark.java @@ -5,7 +5,6 @@ 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.GainAbilitySourceEffect; import mage.abilities.keyword.DeathtouchAbility; import mage.abilities.keyword.MenaceAbility; @@ -26,7 +25,7 @@ import java.util.UUID; */ public final class FearOfTheDark extends CardImpl { - private static final FilterPermanent filter = new FilterCreaturePermanent(SubType.GLIMMER, ""); + private static final FilterPermanent filter = new FilterCreaturePermanent(SubType.GLIMMER, "defending player controls no Glimmer creatures"); static { filter.add(DefendingPlayerControlsSourceAttackingPredicate.instance); @@ -44,12 +43,12 @@ public final class FearOfTheDark extends CardImpl { this.toughness = new MageInt(5); // Whenever Fear of the Dark attacks, if defending player controls no Glimmer creatures, it gains menace and deathtouch until end of turn. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new GainAbilitySourceEffect(new MenaceAbility(), Duration.EndOfTurn)), - condition, "Whenever {this} attacks, if defending player controls no Glimmer " + - "creatures, it gains menace and deathtouch until end of turn." - ); - ability.addEffect(new GainAbilitySourceEffect(DeathtouchAbility.getInstance(), Duration.EndOfTurn)); + Ability ability = new AttacksTriggeredAbility(new GainAbilitySourceEffect( + new MenaceAbility(), Duration.EndOfTurn + ).setText("it gains menace")).withInterveningIf(condition); + ability.addEffect(new GainAbilitySourceEffect( + DeathtouchAbility.getInstance(), Duration.EndOfTurn + ).setText("and deathtouch until end of turn")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/FeastOfDreams.java b/Mage.Sets/src/mage/cards/f/FeastOfDreams.java index 366b3cd190d..5ccda8f8ddb 100644 --- a/Mage.Sets/src/mage/cards/f/FeastOfDreams.java +++ b/Mage.Sets/src/mage/cards/f/FeastOfDreams.java @@ -9,6 +9,7 @@ import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.EnchantedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -32,7 +33,7 @@ public final class FeastOfDreams extends CardImpl { // Destroy target enchanted creature or enchantment creature. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private FeastOfDreams(final FeastOfDreams card) { diff --git a/Mage.Sets/src/mage/cards/f/FeastOfFlesh.java b/Mage.Sets/src/mage/cards/f/FeastOfFlesh.java index 51c979518c8..bed772ebc9a 100644 --- a/Mage.Sets/src/mage/cards/f/FeastOfFlesh.java +++ b/Mage.Sets/src/mage/cards/f/FeastOfFlesh.java @@ -1,7 +1,6 @@ package mage.cards.f; -import java.util.UUID; import mage.abilities.dynamicvalue.IntPlusDynamicValue; import mage.abilities.dynamicvalue.common.CardsInAllGraveyardsCount; import mage.abilities.effects.Effect; @@ -14,8 +13,9 @@ import mage.filter.FilterCard; import mage.filter.predicate.mageobject.NamePredicate; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author L_J */ public final class FeastOfFlesh extends CardImpl { @@ -27,14 +27,14 @@ public final class FeastOfFlesh extends CardImpl { } public FeastOfFlesh(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{B}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{B}"); // Feast of Flesh deals X damage to target creature and you gain X life, where X is 1 plus the number of cards named Feast of Flesh in all graveyards. IntPlusDynamicValue value = new IntPlusDynamicValue(1, new CardsInAllGraveyardsCount(filter)); Effect effect1 = new DamageTargetEffect(value); effect1.setText("Feast of Flesh deals X damage to target creature"); Effect effect2 = new GainLifeEffect(value); - effect2.setText("and you gain X life, where X is 1 plus the number of cards named {this} in all graveyards"); + effect2.setText("and you gain X life, where X is 1 plus the number of cards named Feast of Flesh in all graveyards"); this.getSpellAbility().addEffect(effect1); this.getSpellAbility().addEffect(effect2); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); diff --git a/Mage.Sets/src/mage/cards/f/FeastOnTheFallen.java b/Mage.Sets/src/mage/cards/f/FeastOnTheFallen.java index 01cd22fba5c..8a1c24b7920 100644 --- a/Mage.Sets/src/mage/cards/f/FeastOnTheFallen.java +++ b/Mage.Sets/src/mage/cards/f/FeastOnTheFallen.java @@ -1,12 +1,9 @@ - package mage.cards.f; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -16,23 +13,20 @@ import mage.game.Game; import mage.target.common.TargetControlledCreaturePermanent; import mage.watchers.common.PlayerLostLifeWatcher; +import java.util.UUID; + /** - * * @author emerald000 */ public final class FeastOnTheFallen extends CardImpl { public FeastOnTheFallen(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{B}"); - + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}"); // At the beginning of each upkeep, if an opponent lost life last turn, put a +1/+1 counter on target creature you control. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility( - TargetController.ANY, new AddCountersTargetEffect(CounterType.P1P1.createInstance()), - false), - FeastOnTheFallenCondition.instance, - "At the beginning of each upkeep, if an opponent lost life last turn, put a +1/+1 counter on target creature you control."); + Ability ability = new BeginningOfUpkeepTriggeredAbility( + TargetController.ANY, new AddCountersTargetEffect(CounterType.P1P1.createInstance()), false + ).withInterveningIf(FeastOnTheFallenCondition.instance); ability.addTarget(new TargetControlledCreaturePermanent()); this.addAbility(ability); } @@ -54,13 +48,16 @@ enum FeastOnTheFallenCondition implements Condition { @Override public boolean apply(Game game, Ability source) { PlayerLostLifeWatcher watcher = game.getState().getWatcher(PlayerLostLifeWatcher.class); - if (watcher != null) { - for (UUID opponentId : game.getOpponents(source.getControllerId())) { - if (watcher.getLifeLostLastTurn(opponentId) > 0) { - return true; - } - } - } - return false; + return watcher != null + && game + .getOpponents(source.getControllerId()) + .stream() + .mapToInt(watcher::getLifeLostLastTurn) + .anyMatch(x -> x > 0); + } + + @Override + public String toString() { + return "an opponent lost life last turn"; } } diff --git a/Mage.Sets/src/mage/cards/f/FeastOrFamine.java b/Mage.Sets/src/mage/cards/f/FeastOrFamine.java index 05aa80ebf49..89916b379b0 100644 --- a/Mage.Sets/src/mage/cards/f/FeastOrFamine.java +++ b/Mage.Sets/src/mage/cards/f/FeastOrFamine.java @@ -13,6 +13,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; import mage.game.permanent.token.ZombieToken; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -36,7 +37,7 @@ public final class FeastOrFamine extends CardImpl { // or destroy target nonartifact, nonblack creature and it can't be regenerated. Mode mode = new Mode(new DestroyTargetEffect(true)); - mode.addTarget(new TargetCreaturePermanent(filter)); + mode.addTarget(new TargetPermanent(filter)); this.getSpellAbility().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/f/FeastingTrollKing.java b/Mage.Sets/src/mage/cards/f/FeastingTrollKing.java index 8000de84d1c..29aa0be0ed2 100644 --- a/Mage.Sets/src/mage/cards/f/FeastingTrollKing.java +++ b/Mage.Sets/src/mage/cards/f/FeastingTrollKing.java @@ -6,7 +6,6 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromHandSourcePermanentCondition; import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.costs.common.SacrificeTargetCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; import mage.abilities.hint.common.MyTurnHint; @@ -19,7 +18,6 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterControlledPermanent; import mage.game.permanent.token.FoodToken; -import mage.target.common.TargetControlledPermanent; import mage.watchers.common.CastFromHandWatcher; import java.util.UUID; @@ -46,11 +44,8 @@ public final class FeastingTrollKing extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // 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)), - CastFromHandSourcePermanentCondition.instance, "When {this} enters, " + - "if you cast it from your hand, create three Food tokens." - ), new CastFromHandWatcher()); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new FoodToken(), 3)) + .withInterveningIf(CastFromHandSourcePermanentCondition.instance), new CastFromHandWatcher()); // Sacrifice three Foods: Return Feasting Troll King from your graveyard to the battlefield. Activate this ability only during your turn. this.addAbility(new ActivateIfConditionActivatedAbility( diff --git a/Mage.Sets/src/mage/cards/f/FelhideSpiritbinder.java b/Mage.Sets/src/mage/cards/f/FelhideSpiritbinder.java index 7cdd4a7a6ca..b694442608c 100644 --- a/Mage.Sets/src/mage/cards/f/FelhideSpiritbinder.java +++ b/Mage.Sets/src/mage/cards/f/FelhideSpiritbinder.java @@ -20,9 +20,12 @@ import mage.constants.Outcome; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * * @author Quercitron @@ -39,7 +42,7 @@ public final class FelhideSpiritbinder extends CardImpl { // Inspired — Whenever Felhide Spiritbinder becomes untapped, you may pay {1}{R}. If you do, create a token that's a copy of another target creature except it's an enchantment in addition to its other types. It gains haste. Exile it at the beginning of the next end step. Ability ability = new InspiredAbility(new DoIfCostPaid(new FelhideSpiritbinderEffect(), new ManaCostsImpl<>("{1}{R}"), "Use effect of {this}?")); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/FelineSovereign.java b/Mage.Sets/src/mage/cards/f/FelineSovereign.java index c682dac3761..399d4700c04 100644 --- a/Mage.Sets/src/mage/cards/f/FelineSovereign.java +++ b/Mage.Sets/src/mage/cards/f/FelineSovereign.java @@ -15,10 +15,8 @@ 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.GameEvent; import mage.target.TargetPermanent; +import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster; import java.util.UUID; @@ -52,7 +50,10 @@ public final class FelineSovereign extends CardImpl { 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()); + Ability ability2 = new OneOrMoreCombatDamagePlayerTriggeredAbility(new DestroyTargetEffect(), SetTargetPointer.PLAYER, filterCat, false); + ability2.addTarget(new TargetPermanent(0, 1, new FilterArtifactOrEnchantmentPermanent("artifact or enchantment that player controls"))); + ability2.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster()); + this.addAbility(ability2); } private FelineSovereign(final FelineSovereign card) { @@ -64,34 +65,3 @@ public final class FelineSovereign extends CardImpl { return new FelineSovereign(this); } } - -class FelineSovereignTriggeredAbility extends OneOrMoreCombatDamagePlayerTriggeredAbility { - - private static final FilterCreaturePermanent catFilter = new FilterCreaturePermanent(SubType.CAT, "Cats"); - - FelineSovereignTriggeredAbility() { - super(new DestroyTargetEffect().setText("destroy up to one target artifact or enchantment that player controls"), catFilter); - } - - private FelineSovereignTriggeredAbility(final FelineSovereignTriggeredAbility ability) { - super(ability); - } - - @Override - public FelineSovereignTriggeredAbility copy() { - return new FelineSovereignTriggeredAbility(this); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (!super.checkTrigger(event, game)) { - return false; - } - this.getTargets().clear(); - FilterArtifactOrEnchantmentPermanent filter = new FilterArtifactOrEnchantmentPermanent(); - filter.add(new ControllerIdPredicate(event.getTargetId())); - this.addTarget(new TargetPermanent(0, 1, filter, false)); - return true; - } - -} diff --git a/Mage.Sets/src/mage/cards/f/FemerefArchers.java b/Mage.Sets/src/mage/cards/f/FemerefArchers.java index 1bbe77a4ca2..404f855dee4 100644 --- a/Mage.Sets/src/mage/cards/f/FemerefArchers.java +++ b/Mage.Sets/src/mage/cards/f/FemerefArchers.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterAttackingCreature; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -37,7 +38,7 @@ public final class FemerefArchers extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(4), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/FeralContest.java b/Mage.Sets/src/mage/cards/f/FeralContest.java index 354c34eec8a..ad741759504 100644 --- a/Mage.Sets/src/mage/cards/f/FeralContest.java +++ b/Mage.Sets/src/mage/cards/f/FeralContest.java @@ -1,7 +1,5 @@ - package mage.cards.f; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.RequirementEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; @@ -10,36 +8,29 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.counters.CounterType; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.other.AnotherTargetPredicate; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class FeralContest extends CardImpl { public FeralContest(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}"); // Put a +1/+1 counter on target creature you control. this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance())); - - TargetControlledCreaturePermanent target1 = new TargetControlledCreaturePermanent(); - target1.setTargetTag(1); - this.getSpellAbility().addTarget(target1); - + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent().setTargetTag(1)); + // Another target creature blocks it this turn if able. this.getSpellAbility().addEffect(new FeralContestEffect()); - FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature (must block this turn)"); - filter.add(new AnotherTargetPredicate(2)); - TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter); - target2.setTargetTag(2); - this.getSpellAbility().addTarget(target2); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2).withChooseHint("to force to block").setTargetTag(2)); } private FeralContest(final FeralContest card) { diff --git a/Mage.Sets/src/mage/cards/f/FeralEncounter.java b/Mage.Sets/src/mage/cards/f/FeralEncounter.java index 26c9885fb88..fc5c85bc6fe 100644 --- a/Mage.Sets/src/mage/cards/f/FeralEncounter.java +++ b/Mage.Sets/src/mage/cards/f/FeralEncounter.java @@ -17,8 +17,8 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; import mage.util.CardUtil; import java.util.UUID; @@ -36,7 +36,7 @@ public final class FeralEncounter extends CardImpl { DelayedTriggeredAbility delayed = new FeralEncounterDelayedTriggeredAbility(); delayed.addTarget(new TargetControlledCreaturePermanent()); - delayed.addTarget(new TargetCreaturePermanent(0, 1, StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL, false)); + delayed.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(delayed)); } diff --git a/Mage.Sets/src/mage/cards/f/FesteringNewt.java b/Mage.Sets/src/mage/cards/f/FesteringNewt.java index 323b1267474..1e30b621dfc 100644 --- a/Mage.Sets/src/mage/cards/f/FesteringNewt.java +++ b/Mage.Sets/src/mage/cards/f/FesteringNewt.java @@ -18,8 +18,11 @@ import mage.constants.Duration; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.NamePredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -46,7 +49,7 @@ public final class FesteringNewt extends CardImpl { 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 DiesSourceTriggeredAbility(effect); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/FeverCharm.java b/Mage.Sets/src/mage/cards/f/FeverCharm.java index 7921e494ded..fb08d418f01 100644 --- a/Mage.Sets/src/mage/cards/f/FeverCharm.java +++ b/Mage.Sets/src/mage/cards/f/FeverCharm.java @@ -13,6 +13,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -39,7 +40,7 @@ public final class FeverCharm extends CardImpl { this.getSpellAbility().addMode(mode); // or Fever Charm deals 3 damage to target Wizard creature. mode = new Mode(new DamageTargetEffect(3)); - mode.addTarget(new TargetCreaturePermanent(filter)); + mode.addTarget(new TargetPermanent(filter)); this.getSpellAbility().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/f/FeySteed.java b/Mage.Sets/src/mage/cards/f/FeySteed.java index beaecd6abeb..df32f25e7e5 100644 --- a/Mage.Sets/src/mage/cards/f/FeySteed.java +++ b/Mage.Sets/src/mage/cards/f/FeySteed.java @@ -16,6 +16,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.permanent.AttackingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -50,7 +51,7 @@ public final class FeySteed extends CardImpl { // Whenever Fey Steed attacks, another target attacking creature you control gains indestructible until end of turn. Ability ability = new AttacksTriggeredAbility( new GainAbilityTargetEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn), false); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // Whenever a creature or planeswalker you control becomes the target of a spell or ability an opponent controls, you may draw a card. diff --git a/Mage.Sets/src/mage/cards/f/FieldOfTheDead.java b/Mage.Sets/src/mage/cards/f/FieldOfTheDead.java index 92c7fdadf5c..448e161a1ad 100644 --- a/Mage.Sets/src/mage/cards/f/FieldOfTheDead.java +++ b/Mage.Sets/src/mage/cards/f/FieldOfTheDead.java @@ -4,7 +4,6 @@ import mage.abilities.Ability; 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; import mage.abilities.mana.ColorlessManaAbility; import mage.cards.CardImpl; @@ -32,13 +31,9 @@ public final class FieldOfTheDead extends CardImpl { this.addAbility(new ColorlessManaAbility()); // Whenever Field of the Dead or another land you control enters, if you control seven or more lands with different names, create a 2/2 black Zombie creature token. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldThisOrAnotherTriggeredAbility( - new CreateTokenEffect(new ZombieToken()), StaticFilters.FILTER_LAND, false, true - ), FieldOfTheDeadCondition.instance, "Whenever {this} or another land " + - "you control enters, if you control seven or more lands with different names, " + - "create a 2/2 black Zombie creature token." - )); + this.addAbility(new EntersBattlefieldThisOrAnotherTriggeredAbility( + new CreateTokenEffect(new ZombieToken()), StaticFilters.FILTER_LAND, false, true + ).withInterveningIf(FieldOfTheDeadCondition.instance)); } private FieldOfTheDead(final FieldOfTheDead card) { @@ -69,4 +64,9 @@ enum FieldOfTheDeadCondition implements Condition { .distinct() .count() > 6; } + + @Override + public String toString() { + return "you control seven or more lands with different names"; + } } diff --git a/Mage.Sets/src/mage/cards/f/FieldSurgeon.java b/Mage.Sets/src/mage/cards/f/FieldSurgeon.java index 32e91858a89..11a8dceb448 100644 --- a/Mage.Sets/src/mage/cards/f/FieldSurgeon.java +++ b/Mage.Sets/src/mage/cards/f/FieldSurgeon.java @@ -1,4 +1,3 @@ - package mage.cards.f; import mage.MageInt; @@ -11,10 +10,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.filter.StaticFilters; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -24,12 +20,6 @@ import java.util.UUID; */ public final class FieldSurgeon extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("an untapped creature you control"); - - static { - filter.add(TappedPredicate.UNTAPPED); - } - public FieldSurgeon(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); this.subtype.add(SubType.HUMAN); @@ -38,8 +28,10 @@ public final class FieldSurgeon extends CardImpl { this.toughness = new MageInt(1); // Tap an untapped creature you control: Prevent the next 1 damage that would be dealt to target creature this turn. - Ability ability = new SimpleActivatedAbility(new PreventDamageToTargetEffect(Duration.EndOfTurn, 1), - new TapTargetCost(new TargetControlledCreaturePermanent(filter))); + Ability ability = new SimpleActivatedAbility( + new PreventDamageToTargetEffect(Duration.EndOfTurn, 1), + new TapTargetCost(StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURE) + ); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/FiendBinder.java b/Mage.Sets/src/mage/cards/f/FiendBinder.java index 5059619cdc4..34ac77e08a6 100644 --- a/Mage.Sets/src/mage/cards/f/FiendBinder.java +++ b/Mage.Sets/src/mage/cards/f/FiendBinder.java @@ -12,6 +12,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.DefendingPlayerControlsSourceAttackingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -34,7 +35,7 @@ public final class FiendBinder extends CardImpl { // Whenever Fiend Binder attacks, tap target creature defending player controls. Ability ability = new AttacksTriggeredAbility(new TapTargetEffect(), false); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/FieryGambit.java b/Mage.Sets/src/mage/cards/f/FieryGambit.java index 2b7283c329e..f4adba73023 100644 --- a/Mage.Sets/src/mage/cards/f/FieryGambit.java +++ b/Mage.Sets/src/mage/cards/f/FieryGambit.java @@ -44,7 +44,7 @@ class FieryGambitEffect extends OneShotEffect { FieryGambitEffect() { super(Outcome.Benefit); - this.staticText = "Flip a coin until you lose a flip or choose to stop flipping. If you lose a flip, Fiery Gambit has no effect. If you win one or more flips, Fiery Gambit deals 3 damage to target creature. If you win two or more flips, Fiery Gambit deals 6 damage to each opponent. If you win three or more flips, draw nine cards and untap all lands you control"; + this.staticText = "Flip a coin until you lose a flip or choose to stop flipping. If you lose a flip, {this} has no effect. If you win one or more flips, {this} deals 3 damage to target creature. If you win two or more flips, {this} deals 6 damage to each opponent. If you win three or more flips, draw nine cards and untap all lands you control"; } private FieryGambitEffect(final FieryGambitEffect effect) { diff --git a/Mage.Sets/src/mage/cards/f/FightOrFlight.java b/Mage.Sets/src/mage/cards/f/FightOrFlight.java index 55a1bcd9a6a..2a1a4f5ed9d 100644 --- a/Mage.Sets/src/mage/cards/f/FightOrFlight.java +++ b/Mage.Sets/src/mage/cards/f/FightOrFlight.java @@ -1,9 +1,9 @@ package mage.cards.f; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.combat.CantAttackAllEffect; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -18,7 +18,7 @@ import mage.filter.predicate.permanent.PermanentReferenceInCollectionPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import java.util.ArrayList; import java.util.List; @@ -26,13 +26,12 @@ import java.util.UUID; import java.util.stream.Collectors; /** - * * @author LevelX2 & L_J */ public final class FightOrFlight extends CardImpl { public FightOrFlight(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}"); // At the beginning of combat on each opponent’s turn, separate all creatures that player controls into two piles. Only creatures in the pile of their choice can attack this turn. this.addAbility(new BeginningOfCombatTriggeredAbility(TargetController.OPPONENT, new FightOrFlightEffect(), false)); @@ -73,7 +72,7 @@ class FightOrFlightEffect extends OneShotEffect { } FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures to put in the first pile"); filter.add(new ControllerIdPredicate(targetPlayer.getId())); - TargetCreaturePermanent creatures = new TargetCreaturePermanent(0, Integer.MAX_VALUE, filter, true); + TargetPermanent creatures = new TargetPermanent(0, Integer.MAX_VALUE, filter, true); List pile1 = new ArrayList<>(); if (player.choose(Outcome.Neutral, creatures, source, game)) { List targets = creatures.getTargets(); diff --git a/Mage.Sets/src/mage/cards/f/FinestHour.java b/Mage.Sets/src/mage/cards/f/FinestHour.java index b594c923a25..6b000b1adad 100644 --- a/Mage.Sets/src/mage/cards/f/FinestHour.java +++ b/Mage.Sets/src/mage/cards/f/FinestHour.java @@ -1,19 +1,18 @@ package mage.cards.f; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.AttacksAloneControlledTriggeredAbility; import mage.abilities.condition.common.FirstCombatPhaseCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.effects.common.AdditionalCombatPhaseEffect; +import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.keyword.ExaltedAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import java.util.UUID; + /** - * * @author awjackson */ public final class FinestHour extends CardImpl { @@ -26,12 +25,9 @@ public final class FinestHour extends CardImpl { // Whenever a creature you control attacks alone, if it's the first combat phase of the turn, untap that // creature. After this phase, there is an additional combat phase. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new AttacksAloneControlledTriggeredAbility(new UntapTargetEffect("untap that creature"), true, false), - FirstCombatPhaseCondition.instance, - "Whenever a creature you control attacks alone, if it's the first combat phase of the turn, " + - "untap that creature. After this phase, there is an additional combat phase." - ); + Ability ability = new AttacksAloneControlledTriggeredAbility( + new UntapTargetEffect("untap that creature"), true, false + ).withInterveningIf(FirstCombatPhaseCondition.instance); ability.addEffect(new AdditionalCombatPhaseEffect()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/FirbolgFlutist.java b/Mage.Sets/src/mage/cards/f/FirbolgFlutist.java index ad9f3e92b5d..7a45290f3a3 100644 --- a/Mage.Sets/src/mage/cards/f/FirbolgFlutist.java +++ b/Mage.Sets/src/mage/cards/f/FirbolgFlutist.java @@ -14,10 +14,13 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author TheElk801 */ @@ -42,7 +45,7 @@ public final class FirbolgFlutist extends CardImpl { ability.addEffect(new GainAbilityTargetEffect( new MyriadAbility(), Duration.EndOfTurn ).setText("and myriad until end of turn")); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + ability.addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.addAbility(ability.withFlavorWord("Enthralling Performance")); } diff --git a/Mage.Sets/src/mage/cards/f/FireBowman.java b/Mage.Sets/src/mage/cards/f/FireBowman.java index 7b98f5f4d38..b545be81e67 100644 --- a/Mage.Sets/src/mage/cards/f/FireBowman.java +++ b/Mage.Sets/src/mage/cards/f/FireBowman.java @@ -10,7 +10,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.target.common.TargetAnyTarget; import java.util.UUID; @@ -30,7 +29,7 @@ public final class FireBowman extends CardImpl { // Sacrifice Fire Bowman: Fire Bowman deals 1 damage to any target. Activate this ability only during your turn, before attackers are declared. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new DamageTargetEffect(1, "it"), + new DamageTargetEffect(1, "it"), new SacrificeSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance ); ability.addTarget(new TargetAnyTarget()); diff --git a/Mage.Sets/src/mage/cards/f/FiremaneAngel.java b/Mage.Sets/src/mage/cards/f/FiremaneAngel.java index 4a290c38a90..b61e49d77b5 100644 --- a/Mage.Sets/src/mage/cards/f/FiremaneAngel.java +++ b/Mage.Sets/src/mage/cards/f/FiremaneAngel.java @@ -1,36 +1,33 @@ - package mage.cards.f; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.FlyingAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.PhaseStep; import mage.constants.TargetController; import mage.constants.Zone; import mage.game.Game; +import java.util.UUID; + /** - * * @author Loki */ public final class FiremaneAngel extends CardImpl { public FiremaneAngel(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{R}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{W}{W}"); this.subtype.add(SubType.ANGEL); this.power = new MageInt(4); @@ -38,17 +35,20 @@ public final class FiremaneAngel extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); + // Firststrike this.addAbility(FirstStrikeAbility.getInstance()); + // At the beginning of your upkeep, if Firemane Angel is in your graveyard or on the battlefield, you may gain 1 life. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(Zone.ALL, TargetController.YOU, new GainLifeEffect(1), true), - SourceOnBattlefieldOrGraveyardCondition.instance, - "At the beginning of your upkeep, if {this} is in your graveyard or on the battlefield, you may gain 1 life."); - this.addAbility(ability); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + Zone.ALL, TargetController.YOU, new GainLifeEffect(1), true + ).withInterveningIf(FiremaneAngelCondition.instance)); + // {6}{R}{R}{W}{W}: Return Firemane Angel from your graveyard to the battlefield. Activate this ability only during your upkeep. - this.addAbility(new ConditionalActivatedAbility(Zone.GRAVEYARD, - new ReturnSourceFromGraveyardToBattlefieldEffect(false, false), new ManaCostsImpl<>("{6}{R}{R}{W}{W}"), new IsStepCondition(PhaseStep.UPKEEP), null)); + this.addAbility(new ActivateIfConditionActivatedAbility( + Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldEffect(false, false), + new ManaCostsImpl<>("{6}{R}{R}{W}{W}"), IsStepCondition.getMyUpkeep() + )); } private FiremaneAngel(final FiremaneAngel card) { @@ -61,8 +61,7 @@ public final class FiremaneAngel extends CardImpl { } } -enum SourceOnBattlefieldOrGraveyardCondition implements Condition { - +enum FiremaneAngelCondition implements Condition { instance; @Override @@ -73,7 +72,6 @@ enum SourceOnBattlefieldOrGraveyardCondition implements Condition { @Override public String toString() { - return "if {this} is in your graveyard or on the battlefield"; + return "{this} is in your graveyard or on the battlefield"; } - } diff --git a/Mage.Sets/src/mage/cards/f/FirestormPhoenix.java b/Mage.Sets/src/mage/cards/f/FirestormPhoenix.java index 18608d7ade1..ab89248d8f7 100644 --- a/Mage.Sets/src/mage/cards/f/FirestormPhoenix.java +++ b/Mage.Sets/src/mage/cards/f/FirestormPhoenix.java @@ -58,7 +58,7 @@ class FirestormPhoenixEffect extends ReplacementEffectImpl { FirestormPhoenixEffect() { super(Duration.Custom, Outcome.ReturnToHand); - staticText = "If {this} would die, return {this} to its owner's hand instead. " + + staticText = "If {this} would die, return it to its owner's hand instead. " + "Until that player's next turn, that player plays with that card revealed in their hand and can't play it"; } diff --git a/Mage.Sets/src/mage/cards/f/FirewakeSliver.java b/Mage.Sets/src/mage/cards/f/FirewakeSliver.java index 421eea7ad80..a6ca4f9908d 100644 --- a/Mage.Sets/src/mage/cards/f/FirewakeSliver.java +++ b/Mage.Sets/src/mage/cards/f/FirewakeSliver.java @@ -18,6 +18,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -47,7 +48,7 @@ public final class FirewakeSliver extends CardImpl { // All Slivers have "{1}, Sacrifice this permanent: Target Sliver creature gets +2/+2 until end of turn." Ability gainedAbility = new SimpleActivatedAbility(new BoostTargetEffect(2, 2, Duration.EndOfTurn), new GenericManaCost(1)); gainedAbility.addCost(new SacrificeSourceCost()); - gainedAbility.addTarget(new TargetCreaturePermanent(targetSliverFilter)); + gainedAbility.addTarget(new TargetPermanent(targetSliverFilter)); this.addAbility(new SimpleStaticAbility(new GainAbilityAllEffect( gainedAbility, Duration.WhileOnBattlefield, filter, "All Slivers have \"{1}, Sacrifice this permanent: Target Sliver creature gets +2/+2 until end of turn.\""))); diff --git a/Mage.Sets/src/mage/cards/f/FirjasRetribution.java b/Mage.Sets/src/mage/cards/f/FirjasRetribution.java index 5b9fde1d43c..a221f46eb32 100644 --- a/Mage.Sets/src/mage/cards/f/FirjasRetribution.java +++ b/Mage.Sets/src/mage/cards/f/FirjasRetribution.java @@ -23,6 +23,7 @@ import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.AngelWarriorVigilanceToken; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -53,7 +54,7 @@ public final class FirjasRetribution extends CardImpl { // II — Until end of turn, Angels you control gain "{T}: Destroy target creature with less power than this creature." Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_II, new GainAbilityAllEffect( ability, Duration.EndOfTurn, filter2 ).setText("until end of turn, Angels you control gain \"{T}: Destroy target creature with power less than this creature's power.\"")); diff --git a/Mage.Sets/src/mage/cards/f/FirkraagCunningInstigator.java b/Mage.Sets/src/mage/cards/f/FirkraagCunningInstigator.java index 3ca9c31a2d8..df63aa6c02e 100644 --- a/Mage.Sets/src/mage/cards/f/FirkraagCunningInstigator.java +++ b/Mage.Sets/src/mage/cards/f/FirkraagCunningInstigator.java @@ -2,7 +2,7 @@ package mage.cards.f; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility; import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.combat.GoadTargetEffect; @@ -14,14 +14,13 @@ import mage.cards.CardSetInfo; import mage.constants.*; import mage.counters.CounterType; import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicate; -import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; -import mage.game.events.DefenderAttackedEvent; -import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; +import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster; import java.util.UUID; @@ -30,10 +29,11 @@ import java.util.UUID; */ public final class FirkraagCunningInstigator extends CardImpl { - private static final FilterPermanent filter = new FilterCreaturePermanent(); + private static final FilterPermanent filterHadToAttack = new FilterCreaturePermanent(); + private static final FilterPermanent filterDragons = new FilterControlledPermanent(SubType.DRAGON, "Dragons you control"); static { - filter.add(FirkraagCunningInstigatorPredicate.instance); + filterHadToAttack.add(FirkraagCunningInstigatorPredicate.instance); } public FirkraagCunningInstigator(UUID ownerId, CardSetInfo setInfo) { @@ -51,13 +51,16 @@ public final class FirkraagCunningInstigator extends CardImpl { this.addAbility(HasteAbility.getInstance()); // Whenever one or more Dragons you control attack an opponent, goad target creature that player controls. - this.addAbility(new FirkraagCunningInstigatorTriggeredAbility()); + Ability abilityGoad = new AttacksPlayerWithCreaturesTriggeredAbility(new GoadTargetEffect(), 1, filterDragons, SetTargetPointer.PLAYER, true); + abilityGoad.addTarget(new TargetPermanent(new FilterCreaturePermanent("target creature that player controls"))); + abilityGoad.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster()); + this.addAbility(abilityGoad); // Whenever a creature deals combat damage to one of your opponents, if that creature had to attack this combat, you put a +1/+1 counter on Firkraag, Cunning Instigator and you draw a card. Ability ability = new DealsDamageToAPlayerAllTriggeredAbility( new AddCountersSourceEffect(CounterType.P1P1.createInstance()) .setText("you put a +1/+1 counter on {this}"), - filter, false, SetTargetPointer.NONE, + filterHadToAttack, false, SetTargetPointer.NONE, true, false, TargetController.OPPONENT ).setTriggerPhrase("Whenever a creature deals combat damage to one of your opponents, " + "if that creature had to attack this combat, "); @@ -88,48 +91,3 @@ enum FirkraagCunningInstigatorPredicate implements Predicate { .anyMatch(input.getId()::equals); } } - -class FirkraagCunningInstigatorTriggeredAbility extends TriggeredAbilityImpl { - - FirkraagCunningInstigatorTriggeredAbility() { - super(Zone.BATTLEFIELD, new GoadTargetEffect()); - } - - private FirkraagCunningInstigatorTriggeredAbility(final FirkraagCunningInstigatorTriggeredAbility ability) { - super(ability); - } - - @Override - public FirkraagCunningInstigatorTriggeredAbility copy() { - return new FirkraagCunningInstigatorTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DEFENDER_ATTACKED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (this.isControlledBy(event.getPlayerId()) - && game.getOpponents(this.getControllerId()).contains(event.getTargetId()) - && ((DefenderAttackedEvent) event) - .getAttackers(game) - .stream() - .anyMatch(permanent -> permanent.hasSubtype(SubType.DRAGON, game))) { - this.getTargets().clear(); - FilterPermanent filter = new FilterCreaturePermanent( - "creature controlled by " + game.getPlayer(event.getTargetId()).getName() - ); - filter.add(new ControllerIdPredicate(event.getTargetId())); - this.addTarget(new TargetPermanent(filter)); - return true; - } - return false; - } - - @Override - public String getRule() { - return "Whenever one or more Dragons you control attack an opponent, goad target creature that player controls."; - } -} diff --git a/Mage.Sets/src/mage/cards/f/FirstResponse.java b/Mage.Sets/src/mage/cards/f/FirstResponse.java index 593558d1870..90dc5d591dd 100644 --- a/Mage.Sets/src/mage/cards/f/FirstResponse.java +++ b/Mage.Sets/src/mage/cards/f/FirstResponse.java @@ -1,19 +1,17 @@ - package mage.cards.f; -import java.util.UUID; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.LiveLostLastTurnCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.TargetController; import mage.game.permanent.token.SoldierToken; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class FirstResponse extends CardImpl { @@ -22,10 +20,9 @@ public final class FirstResponse extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}"); // At the beginning of each upkeep, if you lost life last turn, create a 1/1 white Soldier creature token. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(TargetController.ANY, new CreateTokenEffect(new SoldierToken()), false), - LiveLostLastTurnCondition.instance, - "At the beginning of each upkeep, if you lost life last turn, create a 1/1 white Soldier creature token.")); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + TargetController.ANY, new CreateTokenEffect(new SoldierToken()), false + ).withInterveningIf(LiveLostLastTurnCondition.instance)); } private FirstResponse(final FirstResponse card) { diff --git a/Mage.Sets/src/mage/cards/f/FlameWreathedPhoenix.java b/Mage.Sets/src/mage/cards/f/FlameWreathedPhoenix.java index 7dc266963c0..869683d3ddc 100644 --- a/Mage.Sets/src/mage/cards/f/FlameWreathedPhoenix.java +++ b/Mage.Sets/src/mage/cards/f/FlameWreathedPhoenix.java @@ -1,14 +1,10 @@ - package mage.cards.f; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TributeNotPaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.ReturnToHandSourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.FlyingAbility; @@ -17,17 +13,18 @@ import mage.abilities.keyword.TributeAbility; 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 java.util.UUID; /** - * * @author LevelX2 */ public final class FlameWreathedPhoenix extends CardImpl { public FlameWreathedPhoenix(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.PHOENIX); this.power = new MageInt(3); @@ -35,15 +32,18 @@ public final class FlameWreathedPhoenix extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); + // Tribute 2 (As this creature enters the battlefield, an opponent of your choice may put 2 +1/+1 counter on it.) this.addAbility(new TributeAbility(2)); - // When Flame-Wreathed Phoenix enters the battlefield, if 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 DiesSourceTriggeredAbility(new ReturnToHandSourceEffect())); - ability.addEffect(effect); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TributeNotPaidCondition.instance, - "When {this} enters, if tribute wasn't paid, it gains haste and \"When this creature dies, return it to its owner's hand.\"")); + // When Flame-Wreathed Phoenix enters the battlefield, if tribute wasn't paid, it gains haste and "When this creature dies, return it to its owner's hand." + Ability ability = new EntersBattlefieldTriggeredAbility( + new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield).setText("it gains haste") + ).withInterveningIf(TributeNotPaidCondition.instance); + ability.addEffect(new GainAbilitySourceEffect( + new DiesSourceTriggeredAbility(new ReturnToHandSourceEffect()) + ).setText("and \"When this creature dies, return it to its owner's hand.\"")); + this.addAbility(ability); } private FlameWreathedPhoenix(final FlameWreathedPhoenix card) { diff --git a/Mage.Sets/src/mage/cards/f/FlamecacheGecko.java b/Mage.Sets/src/mage/cards/f/FlamecacheGecko.java index e1557767dfb..8b46cdf87ef 100644 --- a/Mage.Sets/src/mage/cards/f/FlamecacheGecko.java +++ b/Mage.Sets/src/mage/cards/f/FlamecacheGecko.java @@ -8,7 +8,6 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.OpponentsLostLifeCondition; import mage.abilities.costs.common.DiscardCardCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.mana.BasicManaEffect; import mage.cards.CardImpl; @@ -32,14 +31,9 @@ public final class FlamecacheGecko extends CardImpl { this.toughness = new MageInt(2); // When Flamecache Gecko enters, if an opponent lost life this turn, add {B}{R}. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility( - new BasicManaEffect(new Mana( - 0, 0, 1, 1, 0, 0, 0, 0 - )) - ), OpponentsLostLifeCondition.instance, "When {this} enters, " + - "if an opponent lost life this turn, add {B}{R}." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new BasicManaEffect(new Mana(0, 0, 1, 1, 0, 0, 0, 0)) + ).withInterveningIf(OpponentsLostLifeCondition.instance)); // {1}{R}, Discard a card: Draw a card. Ability ability = new SimpleActivatedAbility( diff --git a/Mage.Sets/src/mage/cards/f/FlamestickCourier.java b/Mage.Sets/src/mage/cards/f/FlamestickCourier.java index 7ef97f22936..620ce4cdd3a 100644 --- a/Mage.Sets/src/mage/cards/f/FlamestickCourier.java +++ b/Mage.Sets/src/mage/cards/f/FlamestickCourier.java @@ -20,6 +20,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -49,7 +50,7 @@ public final class FlamestickCourier extends CardImpl { ability.addEffect(new ConditionalContinuousEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.Custom), SourceTappedCondition.TAPPED,"and has haste for as long as {this} remains tapped")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/FlashFoliage.java b/Mage.Sets/src/mage/cards/f/FlashFoliage.java index 6730fc8a77c..a3874a07191 100644 --- a/Mage.Sets/src/mage/cards/f/FlashFoliage.java +++ b/Mage.Sets/src/mage/cards/f/FlashFoliage.java @@ -17,6 +17,7 @@ import mage.game.permanent.Permanent; import mage.game.permanent.token.SaprolingToken; import mage.game.permanent.token.Token; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -35,7 +36,7 @@ public final class FlashFoliage extends CardImpl { // Create a 1/1 green Saproling creature token that’s blocking target creature attacking you. this.getSpellAbility().addEffect(new FlashFoliageEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreatureAttackingYou())); + this.getSpellAbility().addTarget(new TargetPermanent(new FilterCreatureAttackingYou())); // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("
")); diff --git a/Mage.Sets/src/mage/cards/f/FleetingReflection.java b/Mage.Sets/src/mage/cards/f/FleetingReflection.java index 6f0fa97ed61..406ecddfbae 100644 --- a/Mage.Sets/src/mage/cards/f/FleetingReflection.java +++ b/Mage.Sets/src/mage/cards/f/FleetingReflection.java @@ -10,12 +10,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.other.AnotherTargetPredicate; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; import mage.util.functions.EmptyCopyApplier; import java.util.UUID; @@ -25,18 +24,14 @@ import java.util.UUID; */ public final class FleetingReflection extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other target creature"); - - static { - filter.add(new AnotherTargetPredicate(2)); - } - public FleetingReflection(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); // Target creature you control gains hexproof until end of turn. Untap that creature. Until end of turn, it becomes a copy of up to one other target creature. this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent().setTargetTag(1)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 1, filter, false).setTargetTag(2)); + this.getSpellAbility().addTarget(new TargetPermanent( + 0, 1, StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2 + ).setTargetTag(2)); this.getSpellAbility().addEffect(new GainAbilityTargetEffect(HexproofAbility.getInstance(), Duration.EndOfTurn)); this.getSpellAbility().addEffect(new UntapTargetEffect().setText("Untap that creature")); this.getSpellAbility().addEffect(new FleetingReflectionEffect()); diff --git a/Mage.Sets/src/mage/cards/f/FleshCarver.java b/Mage.Sets/src/mage/cards/f/FleshCarver.java index 7ba5d59fdcd..83a490fd4b2 100644 --- a/Mage.Sets/src/mage/cards/f/FleshCarver.java +++ b/Mage.Sets/src/mage/cards/f/FleshCarver.java @@ -1,7 +1,6 @@ package mage.cards.f; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DiesSourceTriggeredAbility; @@ -16,8 +15,8 @@ import mage.abilities.keyword.IntimidateAbility; 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.filter.StaticFilters; @@ -26,7 +25,8 @@ import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.permanent.token.HorrorXXBlackToken; import mage.players.Player; -import mage.target.common.TargetControlledPermanent; + +import java.util.UUID; /** * @@ -67,7 +67,6 @@ class FleshCarverAbility extends DiesSourceTriggeredAbility { public FleshCarverAbility() { super(new FleshCarverEffect(), false); - setTriggerPhrase("When Flesh Carver dies, "); } private FleshCarverAbility(final FleshCarverAbility ability) { diff --git a/Mage.Sets/src/mage/cards/f/Fleshformer.java b/Mage.Sets/src/mage/cards/f/Fleshformer.java index 0f3ec0e2994..5593c572276 100644 --- a/Mage.Sets/src/mage/cards/f/Fleshformer.java +++ b/Mage.Sets/src/mage/cards/f/Fleshformer.java @@ -5,18 +5,15 @@ import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; -import mage.abilities.hint.common.MyTurnHint; import mage.abilities.keyword.FearAbility; 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.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -35,17 +32,15 @@ public final class Fleshformer extends CardImpl { this.toughness = new MageInt(2); // {W}{U}{B}{R}{G}: Fleshformer gets +2/+2 and gains fear until end of turn. Target creature gets -2/-2 until end of turn. Activate this ability only during your turn. - Effect effect = new BoostSourceEffect(2, 2, Duration.EndOfTurn); - effect.setText("{this} gets +2/+2"); - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl<>("{W}{U}{B}{R}{G}"), MyTurnCondition.instance); - effect = new GainAbilitySourceEffect(FearAbility.getInstance(), Duration.EndOfTurn); - effect.setText("and gains fear until end of turn"); - ability.addEffect(effect); + Ability ability = new ActivateIfConditionActivatedAbility( + new BoostSourceEffect(2, 2, Duration.EndOfTurn) + .setText("{this} gets +2/+2"), + new ManaCostsImpl<>("{W}{U}{B}{R}{G}"), MyTurnCondition.instance + ); + ability.addEffect(new GainAbilitySourceEffect(FearAbility.getInstance(), Duration.EndOfTurn).setText("and gains fear until end of turn")); ability.addEffect(new BoostTargetEffect(-2, -2, Duration.EndOfTurn)); ability.addTarget(new TargetCreaturePermanent()); - ability.addHint(MyTurnHint.instance); this.addAbility(ability); - } private Fleshformer(final Fleshformer card) { diff --git a/Mage.Sets/src/mage/cards/f/FleshlessGladiator.java b/Mage.Sets/src/mage/cards/f/FleshlessGladiator.java index 4677f02dad8..7a909084c51 100644 --- a/Mage.Sets/src/mage/cards/f/FleshlessGladiator.java +++ b/Mage.Sets/src/mage/cards/f/FleshlessGladiator.java @@ -4,7 +4,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.condition.common.CorruptedCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.LoseLifeSourceControllerEffect; import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; import mage.cards.CardImpl; @@ -30,7 +30,7 @@ public final class FleshlessGladiator extends CardImpl { this.toughness = new MageInt(2); // Corrupted -- {2}{B}: Return Fleshless Gladiator from your graveyard to the battlefield tapped. You lose 1 life. Activate only if an opponent has three or more poison counters. - Ability ability = new ConditionalActivatedAbility( + Ability ability = new ActivateIfConditionActivatedAbility( Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldEffect(true, false), new ManaCostsImpl<>("{2}{B}"), CorruptedCondition.instance ); diff --git a/Mage.Sets/src/mage/cards/f/FleshpulperGiant.java b/Mage.Sets/src/mage/cards/f/FleshpulperGiant.java index ae1354019a3..a18ce8ee871 100644 --- a/Mage.Sets/src/mage/cards/f/FleshpulperGiant.java +++ b/Mage.Sets/src/mage/cards/f/FleshpulperGiant.java @@ -13,6 +13,7 @@ import mage.constants.SubType; import mage.constants.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ToughnessPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -36,7 +37,7 @@ public final class FleshpulperGiant extends CardImpl { // When Fleshpulper Giant enters the battlefield, you may destroy target creature with toughness 2 or less. Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), true); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/Flood.java b/Mage.Sets/src/mage/cards/f/Flood.java index da0062f8b25..9493e460098 100644 --- a/Mage.Sets/src/mage/cards/f/Flood.java +++ b/Mage.Sets/src/mage/cards/f/Flood.java @@ -14,6 +14,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -33,7 +34,7 @@ public final class Flood extends CardImpl { // {U}{U}: Tap target creature without flying. Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new ManaCostsImpl<>("{U}{U}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/FoeRazerRegent.java b/Mage.Sets/src/mage/cards/f/FoeRazerRegent.java index 1f2b30ccf9d..1976254a805 100644 --- a/Mage.Sets/src/mage/cards/f/FoeRazerRegent.java +++ b/Mage.Sets/src/mage/cards/f/FoeRazerRegent.java @@ -20,11 +20,14 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author LevelX2 */ @@ -41,7 +44,7 @@ public final class FoeRazerRegent extends CardImpl { // When Foe-Razer Regent enters the battlefield, you may have it fight target creature you don't control. Ability ability = new EntersBattlefieldTriggeredAbility(new FightTargetSourceEffect().setText("you may have it fight target creature you don't control"), true); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + ability.addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.addAbility(ability); // Whenever a creature you control fights, put two +1/+1 counters on it at the beginning of the next end step. diff --git a/Mage.Sets/src/mage/cards/f/Fogwalker.java b/Mage.Sets/src/mage/cards/f/Fogwalker.java index 2a89e279241..99ef23892b5 100644 --- a/Mage.Sets/src/mage/cards/f/Fogwalker.java +++ b/Mage.Sets/src/mage/cards/f/Fogwalker.java @@ -10,10 +10,13 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -30,7 +33,7 @@ public final class Fogwalker extends CardImpl { this.addAbility(new SkulkAbility()); // When Fogwalker enters the battlefield, target creature an opponent controls doesn't untap during its controller's next untap step. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DontUntapInControllersNextUntapStepTargetEffect()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/FollowedFootsteps.java b/Mage.Sets/src/mage/cards/f/FollowedFootsteps.java index f74dfae2f0e..7dba248429a 100644 --- a/Mage.Sets/src/mage/cards/f/FollowedFootsteps.java +++ b/Mage.Sets/src/mage/cards/f/FollowedFootsteps.java @@ -1,29 +1,27 @@ package mage.cards.f; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.CreateTokenCopyTargetEffect; import mage.abilities.keyword.EnchantAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author LoneFox - * */ public final class FollowedFootsteps extends CardImpl { @@ -35,11 +33,10 @@ public final class FollowedFootsteps extends CardImpl { TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.Copy)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // At the beginning of your upkeep, create a token that's a copy of enchanted creature. - this.addAbility(new OnEventTriggeredAbility(GameEvent.EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", new FollowedFootstepsEffect(), false)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new FollowedFootstepsEffect())); } private FollowedFootsteps(final FollowedFootsteps card) { diff --git a/Mage.Sets/src/mage/cards/f/FoodChain.java b/Mage.Sets/src/mage/cards/f/FoodChain.java index b7d07f21a25..70e19426fdd 100644 --- a/Mage.Sets/src/mage/cards/f/FoodChain.java +++ b/Mage.Sets/src/mage/cards/f/FoodChain.java @@ -15,12 +15,11 @@ import mage.cards.CardSetInfo; import mage.choices.ChoiceColor; import mage.constants.CardType; 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.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; import java.util.ArrayList; import java.util.List; @@ -35,9 +34,10 @@ public final class FoodChain extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); // Exile a creature you control: Add X mana of any one color, where X is the exiled creature's converted mana cost plus one. Spend this mana only to cast creature spells. - Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, new FoodChainManaEffect(), - new ExileTargetCost(new TargetControlledCreaturePermanent(StaticFilters.FILTER_CONTROLLED_A_CREATURE))); - this.addAbility(ability); + this.addAbility(new SimpleManaAbility( + new FoodChainManaEffect(), + new ExileTargetCost(new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_A_CREATURE)) + )); } private FoodChain(final FoodChain card) { diff --git a/Mage.Sets/src/mage/cards/f/FoolsTome.java b/Mage.Sets/src/mage/cards/f/FoolsTome.java index f0af4a58904..044d905ebd7 100644 --- a/Mage.Sets/src/mage/cards/f/FoolsTome.java +++ b/Mage.Sets/src/mage/cards/f/FoolsTome.java @@ -1,30 +1,29 @@ - package mage.cards.f; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.condition.common.HellbentCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; + +import java.util.UUID; /** - * * @author LoneFox */ public final class FoolsTome extends CardImpl { public FoolsTome(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); // {2}, {tap}: Draw a card. Activate this ability only if you have no cards in hand. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), - new ManaCostsImpl<>("{2}"), HellbentCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new DrawCardSourceControllerEffect(1), new GenericManaCost(2), HellbentCondition.instance + ); ability.addCost(new TapSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/ForcePull.java b/Mage.Sets/src/mage/cards/f/ForcePull.java index ec89792c393..4a9b00a41cb 100644 --- a/Mage.Sets/src/mage/cards/f/ForcePull.java +++ b/Mage.Sets/src/mage/cards/f/ForcePull.java @@ -10,6 +10,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -29,7 +30,7 @@ public final class ForcePull extends CardImpl { // Destroy targer creature with spaceflight. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // Scry 3 this.getSpellAbility().addEffect(new ScryEffect(3)); diff --git a/Mage.Sets/src/mage/cards/f/Forcefield.java b/Mage.Sets/src/mage/cards/f/Forcefield.java index 598a204c83b..8ef14e236d8 100644 --- a/Mage.Sets/src/mage/cards/f/Forcefield.java +++ b/Mage.Sets/src/mage/cards/f/Forcefield.java @@ -1,6 +1,5 @@ package mage.cards.f; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -13,7 +12,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; -import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.UnblockedPredicate; import mage.game.Game; @@ -21,11 +19,12 @@ import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author emerald000 */ public final class Forcefield extends CardImpl { @@ -74,7 +73,7 @@ class ForcefieldEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = source.getSourceObject(game); if (controller != null && sourceObject != null) { - Target target = new TargetCreaturePermanent(1, 1, filter, true); + Target target = new TargetPermanent(1, 1, filter, true); if (controller.choose(Outcome.PreventDamage, target, source, game)) { Permanent creature = game.getPermanent(target.getFirstTarget()); if (creature != null) { diff --git a/Mage.Sets/src/mage/cards/f/ForebodingSteamboat.java b/Mage.Sets/src/mage/cards/f/ForebodingSteamboat.java new file mode 100644 index 00000000000..cf4068fceeb --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/ForebodingSteamboat.java @@ -0,0 +1,173 @@ +package mage.cards.f; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ExileUntilSourceLeavesEffect; +import mage.abilities.effects.keyword.InvestigateEffect; +import mage.abilities.keyword.CrewAbility; +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.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.ExileZone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.TargetPermanent; +import mage.target.common.TargetCardInExile; +import mage.target.targetpointer.FixedTargets; +import mage.util.CardUtil; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author TheElk801 + */ +public final class ForebodingSteamboat extends CardImpl { + + public ForebodingSteamboat(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}{B}{B}"); + + this.subtype.add(SubType.VEHICLE); + this.power = new MageInt(5); + this.toughness = new MageInt(7); + + // When Foreboding Steamboat enters, each player chooses two nontoken, non-Vehicle creatures they control. Exile them until Foreboding Steamboat leaves the battlefield. + this.addAbility(new EntersBattlefieldTriggeredAbility(new ForebodingSteamboatExileEffect())); + + // Whenever Foreboding Steamboat attacks, put a card exiled with it into its owner's graveyard. If you do, investigate. + this.addAbility(new AttacksTriggeredAbility(new ForebodingSteamboatInvestigateEffect())); + + // Crew 2 + this.addAbility(new CrewAbility(2)); + } + + private ForebodingSteamboat(final ForebodingSteamboat card) { + super(card); + } + + @Override + public ForebodingSteamboat copy() { + return new ForebodingSteamboat(this); + } +} + +class ForebodingSteamboatExileEffect extends OneShotEffect { + + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("nontoken, non-Vehicle creatures you control"); + + static { + filter.add(TokenPredicate.FALSE); + filter.add(Predicates.not(SubType.VEHICLE.getPredicate())); + } + + ForebodingSteamboatExileEffect() { + super(Outcome.Benefit); + staticText = "each player chooses two nontoken, non-Vehicle creatures they control. " + + "Exile them until {this} leaves the battlefield"; + } + + private ForebodingSteamboatExileEffect(final ForebodingSteamboatExileEffect effect) { + super(effect); + } + + @Override + public ForebodingSteamboatExileEffect copy() { + return new ForebodingSteamboatExileEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + if (source.getSourcePermanentIfItStillExists(game) == null) { + // if source permanent is already gone then nothing gets exiled in the first place + return false; + } + Set toExile = new HashSet<>(); + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { + Player player = game.getPlayer(playerId); + if (player == null) { + continue; + } + List permanents = game.getBattlefield().getActivePermanents(filter, playerId, source, game); + if (permanents.size() <= 2) { + toExile.addAll(permanents); + continue; + } + TargetPermanent target = new TargetPermanent(2, filter); + target.withNotTarget(true); + player.choose(outcome, target, source, game); + toExile.addAll( + target.getTargets() + .stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .collect(Collectors.toList()) + ); + } + if (toExile.isEmpty()) { + return false; + } + return !toExile.isEmpty() + && new ExileUntilSourceLeavesEffect() + .setTargetPointer(new FixedTargets(toExile, game)) + .apply(game, source); + } +} + +class ForebodingSteamboatInvestigateEffect extends OneShotEffect { + + ForebodingSteamboatInvestigateEffect() { + super(Outcome.Benefit); + staticText = "put a card exiled with it into its owner's graveyard. If you do, investigate"; + } + + private ForebodingSteamboatInvestigateEffect(final ForebodingSteamboatInvestigateEffect effect) { + super(effect); + } + + @Override + public ForebodingSteamboatInvestigateEffect copy() { + return new ForebodingSteamboatInvestigateEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + ExileZone exileZone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source)); + if (player == null || exileZone == null) { + return false; + } + Card card; + switch (exileZone.size()) { + case 0: + return false; + case 1: + card = exileZone.getRandom(game); + break; + default: + TargetCard target = new TargetCardInExile(StaticFilters.FILTER_CARD, exileZone.getId()); + target.withChooseHint("to put into its owner's graveyard"); + player.choose(outcome, target, source, game); + card = game.getCard(target.getFirstTarget()); + } + if (card == null) { + return false; + } + player.moveCards(card, Zone.GRAVEYARD, source, game); + InvestigateEffect.doInvestigate(player.getId(), 1, game, source); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/f/ForerunnerOfSlaughter.java b/Mage.Sets/src/mage/cards/f/ForerunnerOfSlaughter.java index 4fa8e818dcb..a14c3497683 100644 --- a/Mage.Sets/src/mage/cards/f/ForerunnerOfSlaughter.java +++ b/Mage.Sets/src/mage/cards/f/ForerunnerOfSlaughter.java @@ -17,6 +17,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorlessPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -43,7 +44,7 @@ public final class ForerunnerOfSlaughter extends CardImpl { // {1}: Target colorless creature gains haste until end of turn. Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn), new GenericManaCost(1)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/ForgestokerDragon.java b/Mage.Sets/src/mage/cards/f/ForgestokerDragon.java index a9250517cca..30881f1df2f 100644 --- a/Mage.Sets/src/mage/cards/f/ForgestokerDragon.java +++ b/Mage.Sets/src/mage/cards/f/ForgestokerDragon.java @@ -1,32 +1,29 @@ - package mage.cards.f; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.common.SourceAttackingCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.combat.CantBlockTargetEffect; 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.Zone; +import mage.constants.SubType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class ForgestokerDragon extends CardImpl { public ForgestokerDragon(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}{R}"); this.subtype.add(SubType.DRAGON); this.power = new MageInt(5); @@ -34,14 +31,15 @@ public final class ForgestokerDragon extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); - // {1}{R}: Forgestoker Dragon deals 1 damage to target creature. That creature can't block this combat. Activate this ability only if Forgestoker Dragon is attacking. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new ManaCostsImpl<>("{1}{R}"), SourceAttackingCondition.instance); - ability.addTarget(new TargetCreaturePermanent()); - Effect effect = new CantBlockTargetEffect(Duration.EndOfCombat); - effect.setText("That creature can't block this combat"); - ability.addEffect(effect); - this.addAbility(ability); + // {1}{R}: Forgestoker Dragon deals 1 damage to target creature. That creature can't block this combat. Activate this ability only if Forgestoker Dragon is attacking. + Ability ability = new ActivateIfConditionActivatedAbility( + new DamageTargetEffect(1), new ManaCostsImpl<>("{1}{R}"), SourceAttackingCondition.instance + ); + ability.addEffect(new CantBlockTargetEffect(Duration.EndOfCombat) + .setText("That creature can't block this combat")); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); } private ForgestokerDragon(final ForgestokerDragon card) { diff --git a/Mage.Sets/src/mage/cards/f/ForgottenAncient.java b/Mage.Sets/src/mage/cards/f/ForgottenAncient.java index 748b0db0823..6256a3ffe3c 100644 --- a/Mage.Sets/src/mage/cards/f/ForgottenAncient.java +++ b/Mage.Sets/src/mage/cards/f/ForgottenAncient.java @@ -2,22 +2,24 @@ package mage.cards.f; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SpellCastAllTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; import mage.counters.CounterType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import java.util.ArrayList; import java.util.List; @@ -35,9 +37,9 @@ public final class ForgottenAncient extends CardImpl { this.toughness = new MageInt(3); // Whenever a player casts a spell, you may put a +1/+1 counter on Forgotten Ancient. - Effect effect = new AddCountersSourceEffect(CounterType.P1P1.createInstance()); - Ability ability = new SpellCastAllTriggeredAbility(effect, true); - this.addAbility(ability); + this.addAbility(new SpellCastAllTriggeredAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance()), true + )); // At the beginning of your upkeep, you may move any number of +1/+1 counters from Forgotten Ancient onto other creatures. this.addAbility(new BeginningOfUpkeepTriggeredAbility(new ForgottenAncientEffect(), true)); @@ -56,7 +58,7 @@ public final class ForgottenAncient extends CardImpl { class ForgottenAncientEffect extends OneShotEffect { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); + private static final FilterPermanent filter = new FilterCreaturePermanent("another creature"); static { filter.add(AnotherPredicate.instance); @@ -98,7 +100,7 @@ class ForgottenAncientEffect extends OneShotEffect { List counterMovements = new ArrayList<>(); do { - Target target = new TargetCreaturePermanent(1, 1, filter, true); + Target target = new TargetPermanent(1, 1, filter, true); if (!target.canChoose(controller.getId(), source, game)) { break; } diff --git a/Mage.Sets/src/mage/cards/f/FoundryHornet.java b/Mage.Sets/src/mage/cards/f/FoundryHornet.java index df6e2b9cccf..2ee71b649b2 100644 --- a/Mage.Sets/src/mage/cards/f/FoundryHornet.java +++ b/Mage.Sets/src/mage/cards/f/FoundryHornet.java @@ -1,28 +1,36 @@ package mage.cards.f; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; 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.SubType; import mage.constants.Duration; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledCreaturePermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class FoundryHornet extends CardImpl { - private static final String rule = "When {this} enters, if you control a creature with a +1/+1 counter on it, creatures your opponents control get -1/-1 until end of turn."; + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("you control a creature with a +1/+1 counter on it"); + + static { + filter.add(CounterType.P1P1.getPredicate()); + } + + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); public FoundryHornet(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); @@ -35,8 +43,10 @@ public final class FoundryHornet extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When Foundry Hornet enters the battlefield, if you control a creature with a +1/+1 counter on it, creatures your opponents control get -1/-1 until end of turn. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new BoostAllEffect(-1, -1, Duration.EndOfTurn, StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE, false), false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_A_CREATURE_P1P1), rule)); + this.addAbility(new EntersBattlefieldTriggeredAbility(new BoostAllEffect( + -1, -1, Duration.EndOfTurn, + StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURES, false + ), false).withInterveningIf(condition)); } private FoundryHornet(final FoundryHornet card) { diff --git a/Mage.Sets/src/mage/cards/f/FowlStrike.java b/Mage.Sets/src/mage/cards/f/FowlStrike.java index 92ae669dcb9..ce423d2a787 100644 --- a/Mage.Sets/src/mage/cards/f/FowlStrike.java +++ b/Mage.Sets/src/mage/cards/f/FowlStrike.java @@ -9,6 +9,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -29,7 +30,7 @@ public final class FowlStrike extends CardImpl { // Destroy target creature with flying. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // Reinforce 2--{2}{G} this.addAbility(new ReinforceAbility(2, new ManaCostsImpl<>("{2}{G}"))); diff --git a/Mage.Sets/src/mage/cards/f/FracturedPowerstone.java b/Mage.Sets/src/mage/cards/f/FracturedPowerstone.java index 844b5135367..33882c5b5c8 100644 --- a/Mage.Sets/src/mage/cards/f/FracturedPowerstone.java +++ b/Mage.Sets/src/mage/cards/f/FracturedPowerstone.java @@ -46,7 +46,7 @@ class FracturedPowerstoneEffect extends OneShotEffect { FracturedPowerstoneEffect() { super(Outcome.Benefit); - staticText = "Roll the planar"; + staticText = "Roll the planar die"; } private FracturedPowerstoneEffect(final FracturedPowerstoneEffect effect) { diff --git a/Mage.Sets/src/mage/cards/f/FreeRangeChicken.java b/Mage.Sets/src/mage/cards/f/FreeRangeChicken.java index 1895348acc8..d2cd14ad8d3 100644 --- a/Mage.Sets/src/mage/cards/f/FreeRangeChicken.java +++ b/Mage.Sets/src/mage/cards/f/FreeRangeChicken.java @@ -49,7 +49,7 @@ class FreeRangeChickenEffect extends OneShotEffect { FreeRangeChickenEffect() { super(Outcome.BoostCreature); - this.staticText = "Roll two six-sided dice. If both results are the same, Free-Range Chicken gets +X/+X until end of turn, where X is that result. If the total of those results is equal to any other total you have rolled this turn for Free-Range Chicken, sacrifice it"; + this.staticText = "Roll two six-sided dice. If both results are the same, {this} gets +X/+X until end of turn, where X is that result. If the total of those results is equal to any other total you have rolled this turn for {this}, sacrifice it"; } private FreeRangeChickenEffect(final FreeRangeChickenEffect effect) { diff --git a/Mage.Sets/src/mage/cards/f/FreewindEquenaut.java b/Mage.Sets/src/mage/cards/f/FreewindEquenaut.java index a656674ee8e..1d68fd6e959 100644 --- a/Mage.Sets/src/mage/cards/f/FreewindEquenaut.java +++ b/Mage.Sets/src/mage/cards/f/FreewindEquenaut.java @@ -18,6 +18,7 @@ import mage.constants.SubType; import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterAttackingOrBlockingCreature; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,7 +39,7 @@ public final class FreewindEquenaut extends CardImpl { SimpleActivatedAbility ability = new SimpleActivatedAbility( new DamageTargetEffect(2), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(new FilterAttackingOrBlockingCreature())); + ability.addTarget(new TargetPermanent(new FilterAttackingOrBlockingCreature())); this.addAbility(new SimpleStaticAbility( new ConditionalContinuousEffect( new GainAbilitySourceEffect(ability, Duration.WhileOnBattlefield), diff --git a/Mage.Sets/src/mage/cards/f/FriendlyRivalry.java b/Mage.Sets/src/mage/cards/f/FriendlyRivalry.java index 892eed11554..c9748da9aaf 100644 --- a/Mage.Sets/src/mage/cards/f/FriendlyRivalry.java +++ b/Mage.Sets/src/mage/cards/f/FriendlyRivalry.java @@ -7,13 +7,14 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SuperType; +import mage.filter.FilterPermanent; import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.other.AnotherTargetPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; import java.util.ArrayList; import java.util.List; @@ -25,7 +26,7 @@ import java.util.UUID; */ public final class FriendlyRivalry extends CardImpl { - private static final FilterControlledCreaturePermanent filter2 = new FilterControlledCreaturePermanent("other target legendary creature you control"); + private static final FilterPermanent filter2 = new FilterControlledCreaturePermanent("other target legendary creature you control"); static { filter2.add(new AnotherTargetPredicate(2)); @@ -37,15 +38,9 @@ public final class FriendlyRivalry extends CardImpl { // Target creature you control and up to one other target legendary creature you control each deal damage equal to their power to target creature you don't control. this.getSpellAbility().addEffect(new FriendlyRivalryEffect()); - - TargetControlledCreaturePermanent target1 = new TargetControlledCreaturePermanent(); - this.getSpellAbility().addTarget(target1.setTargetTag(1).withChooseHint("to deal damage")); - - TargetControlledCreaturePermanent target2 = new TargetControlledCreaturePermanent(0, 1, filter2, false); - this.getSpellAbility().addTarget(target2.setTargetTag(2).withChooseHint("to deal damage")); - - TargetCreaturePermanent target3 = new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL); - this.getSpellAbility().addTarget(target3.setTargetTag(3).withChooseHint("to take damage")); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent().setTargetTag(1).withChooseHint("to deal damage")); + this.getSpellAbility().addTarget(new TargetPermanent(0, 1, filter2).setTargetTag(2).withChooseHint("to deal damage")); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL).setTargetTag(3).withChooseHint("to take damage")); } private FriendlyRivalry(final FriendlyRivalry card) { diff --git a/Mage.Sets/src/mage/cards/f/FrightshroudCourier.java b/Mage.Sets/src/mage/cards/f/FrightshroudCourier.java index a19bf49df6a..87c5824ffbd 100644 --- a/Mage.Sets/src/mage/cards/f/FrightshroudCourier.java +++ b/Mage.Sets/src/mage/cards/f/FrightshroudCourier.java @@ -20,6 +20,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -49,7 +50,7 @@ public final class FrightshroudCourier extends CardImpl { ability.addEffect(new ConditionalContinuousEffect(new GainAbilityTargetEffect(FearAbility.getInstance(), Duration.Custom), SourceTappedCondition.TAPPED,"and has fear for as long as {this} remains tapped")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/FrodoAdventurousHobbit.java b/Mage.Sets/src/mage/cards/f/FrodoAdventurousHobbit.java index 09d3789d3a9..13541c46e6e 100644 --- a/Mage.Sets/src/mage/cards/f/FrodoAdventurousHobbit.java +++ b/Mage.Sets/src/mage/cards/f/FrodoAdventurousHobbit.java @@ -6,7 +6,6 @@ import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.SourceIsRingBearerCondition; import mage.abilities.condition.common.YouGainedLifeCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.dynamicvalue.common.ControllerGainedLifeCount; import mage.abilities.effects.common.DrawCardSourceControllerEffect; @@ -48,15 +47,10 @@ public final class FrodoAdventurousHobbit extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // Whenever Frodo, Adventurous Hobbit attacks, if you gained 3 or more life this turn, the Ring tempts you. Then if Frodo is your Ring-bearer and the Ring has tempted you two or more times this game, draw a card. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new TheRingTemptsYouEffect()), - condition, "Whenever {this} attacks, if you gained 3 or more life this turn, " + - "the Ring tempts you. Then if {this} is your Ring-bearer and the Ring " + - "has tempted you two or more times this game, draw a card." - ); + Ability ability = new AttacksTriggeredAbility(new TheRingTemptsYouEffect()).withInterveningIf(condition); ability.addEffect(new ConditionalOneShotEffect( - new DrawCardSourceControllerEffect(1), - FrodoAdventurousHobbitCondition.instance + new DrawCardSourceControllerEffect(1), FrodoAdventurousHobbitCondition.instance, + "Then if {this} is your Ring-bearer and the Ring has tempted you two or more times this game, draw a card." )); this.addAbility(ability.addHint(ControllerGainedLifeCount.getHint()), new PlayerGainedLifeWatcher()); } diff --git a/Mage.Sets/src/mage/cards/f/Froghemoth.java b/Mage.Sets/src/mage/cards/f/Froghemoth.java index 7d64d15ca39..d4824823731 100644 --- a/Mage.Sets/src/mage/cards/f/Froghemoth.java +++ b/Mage.Sets/src/mage/cards/f/Froghemoth.java @@ -1,20 +1,17 @@ package mage.cards.f; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.HasteAbility; +import mage.abilities.keyword.TrampleAbility; 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.abilities.keyword.TrampleAbility; -import mage.abilities.keyword.HasteAbility; -import mage.constants.CardType; import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.FilterCard; @@ -24,6 +21,11 @@ import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCardInGraveyard; +import mage.target.targetadjustment.DefineByTriggerTargetAdjuster; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; /** * @@ -64,6 +66,7 @@ class FroghemothTriggeredAbility extends DealsCombatDamageToAPlayerTriggeredAbil public FroghemothTriggeredAbility() { super(new FroghemothEffect(), false); + setTargetAdjuster(DefineByTriggerTargetAdjuster.instance); } private FroghemothTriggeredAbility(final FroghemothTriggeredAbility ability) { diff --git a/Mage.Sets/src/mage/cards/f/FrontierSiege.java b/Mage.Sets/src/mage/cards/f/FrontierSiege.java index a05e0807877..47aa48ade33 100644 --- a/Mage.Sets/src/mage/cards/f/FrontierSiege.java +++ b/Mage.Sets/src/mage/cards/f/FrontierSiege.java @@ -21,10 +21,13 @@ import mage.filter.predicate.mageobject.AbilityPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author LevelX2 */ @@ -49,7 +52,7 @@ public final class FrontierSiege extends CardImpl { Ability ability = new EntersBattlefieldAllTriggeredAbility( Zone.BATTLEFIELD, new FrontierSiegeFightEffect(), filter, true, SetTargetPointer.PERMANENT ); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + ability.addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.addAbility(new SimpleStaticAbility(new GainAnchorWordAbilitySourceEffect(ability, ModeChoice.DRAGONS))); } diff --git a/Mage.Sets/src/mage/cards/f/FrontlineHeroism.java b/Mage.Sets/src/mage/cards/f/FrontlineHeroism.java index ae262c06221..c204d86fa78 100644 --- a/Mage.Sets/src/mage/cards/f/FrontlineHeroism.java +++ b/Mage.Sets/src/mage/cards/f/FrontlineHeroism.java @@ -1,6 +1,5 @@ package mage.cards.f; -import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; @@ -13,10 +12,9 @@ import mage.constants.Outcome; import mage.filter.FilterPermanent; import mage.filter.FilterSpell; import mage.filter.StaticFilters; -import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.MageObjectReferencePredicate; import mage.filter.predicate.other.HasOnlySingleTargetPermanentPredicate; -import mage.filter.predicate.permanent.PermanentIdPredicate; +import mage.filter.predicate.permanent.PermanentReferenceInCollectionPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.AkroanSoldierToken; @@ -125,13 +123,7 @@ class FrontlineHeroismEffect extends OneShotEffect { break; default: FilterPermanent filter = new FilterPermanent("token to target with the copied spell"); - filter.add(Predicates.or( - permanents - .stream() - .map(MageItem::getId) - .map(PermanentIdPredicate::new) - .collect(Collectors.toSet()) - )); + filter.add(new PermanentReferenceInCollectionPredicate(permanents, game)); TargetPermanent target = new TargetPermanent(filter); target.withNotTarget(true); player.choose(outcome, target, source, game); diff --git a/Mage.Sets/src/mage/cards/f/FulfillContract.java b/Mage.Sets/src/mage/cards/f/FulfillContract.java index b311c455f03..be31b45cd96 100644 --- a/Mage.Sets/src/mage/cards/f/FulfillContract.java +++ b/Mage.Sets/src/mage/cards/f/FulfillContract.java @@ -15,6 +15,7 @@ import mage.filter.predicate.Predicates; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; @@ -37,7 +38,7 @@ public final class FulfillContract extends CardImpl { // Destroy target creature with a bounty counter on it. If that creature is destroyed this way, you may put a +1/+1 counter on target Rogue or Hunter you control. this.getSpellAbility().addEffect(new FulfillContractEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filterBountyCreature)); + this.getSpellAbility().addTarget(new TargetPermanent(filterBountyCreature)); this.getSpellAbility().addTarget(new TargetControlledPermanent(filterRogueOrHunter)); } diff --git a/Mage.Sets/src/mage/cards/f/FulgentDistraction.java b/Mage.Sets/src/mage/cards/f/FulgentDistraction.java index a4209b808e8..f0a853840ed 100644 --- a/Mage.Sets/src/mage/cards/f/FulgentDistraction.java +++ b/Mage.Sets/src/mage/cards/f/FulgentDistraction.java @@ -1,28 +1,30 @@ package mage.cards.f; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; +import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.abilities.keyword.EquipAbility; 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.target.common.TargetCreaturePermanent; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + /** - * * @author maurer.it_at_gmail.com */ public final class FulgentDistraction extends CardImpl { - public FulgentDistraction (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{W}"); - + public FulgentDistraction(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}"); this.getSpellAbility().addEffect(new FulgentDistractionEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent(2)); @@ -51,27 +53,30 @@ class FulgentDistractionEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - for ( UUID target : getTargetPointer().getTargets(game, source) ) { - Permanent creature = game.getPermanent(target); - - List copiedAttachments = new ArrayList<>(creature.getAttachments()); - for ( UUID equipmentId : copiedAttachments ) { - Permanent equipment = game.getPermanent(equipmentId); - boolean isEquipment = false; - - for (Ability ability : equipment.getAbilities()) { - if (ability instanceof EquipAbility) { - isEquipment = true; - break; - } - } - - if (isEquipment) { - creature.removeAttachment(equipmentId, source, game); - } + List permanents = this + .getTargetPointer() + .getTargets(game, source) + .stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + if (permanents.isEmpty()) { + return false; + } + for (Permanent permanent : permanents) { + permanent.tap(source, game); + } + for (Permanent permanent : permanents) { + Set attachments = permanent + .getAttachments() + .stream() + .map(game::getPermanent) + .filter(attachment -> attachment.hasSubtype(SubType.EQUIPMENT, game)) + .map(MageItem::getId) + .collect(Collectors.toSet()); + for (UUID attachmentId : attachments) { + permanent.removeAttachment(attachmentId, source, game); } - - creature.tap(source, game); } return true; } diff --git a/Mage.Sets/src/mage/cards/f/Fumble.java b/Mage.Sets/src/mage/cards/f/Fumble.java index e53fb2e3d89..b0ddcaa6973 100644 --- a/Mage.Sets/src/mage/cards/f/Fumble.java +++ b/Mage.Sets/src/mage/cards/f/Fumble.java @@ -1,8 +1,5 @@ package mage.cards.f; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; @@ -14,7 +11,6 @@ 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.permanent.Permanent; import mage.players.Player; @@ -22,8 +18,11 @@ import mage.target.Target; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class Fumble extends CardImpl { @@ -80,11 +79,12 @@ class FumbleEffect extends OneShotEffect { } } } - + new ReturnToHandTargetEffect().apply(game, source); if (!attachments.isEmpty()) { - Target target = new TargetCreaturePermanent(1, 1, StaticFilters.FILTER_PERMANENT_CREATURE, true); + Target target = new TargetCreaturePermanent(); + target.withNotTarget(true); Permanent newCreature = null; if (player.choose(Outcome.BoostCreature, target, source, game)) { newCreature = game.getPermanent(target.getFirstTarget()); diff --git a/Mage.Sets/src/mage/cards/f/FungusElemental.java b/Mage.Sets/src/mage/cards/f/FungusElemental.java index 19dd31405ec..3af0437c734 100644 --- a/Mage.Sets/src/mage/cards/f/FungusElemental.java +++ b/Mage.Sets/src/mage/cards/f/FungusElemental.java @@ -1,32 +1,27 @@ package mage.cards.f; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.condition.common.SourceEnteredThisTurnCondition; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; +import mage.constants.SubType; import mage.counters.CounterType; import mage.filter.common.FilterControlledPermanent; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class FungusElemental extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent("Forest"); - - static { - filter.add(SubType.FOREST.getPredicate()); - } + private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.FOREST, "Forest"); public FungusElemental(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); @@ -37,11 +32,9 @@ public final class FungusElemental extends CardImpl { this.toughness = new MageInt(3); // {G}, Sacrifice a Forest: Put a +2/+2 counter on Fungus Elemental. Activate this ability only if Fungus Elemental entered the battlefield this turn. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, + Ability ability = new ActivateIfConditionActivatedAbility( new AddCountersSourceEffect(CounterType.P2P2.createInstance()), - new ManaCostsImpl<>("{G}"), - SourceEnteredThisTurnCondition.DID + new ManaCostsImpl<>("{G}"), SourceEnteredThisTurnCondition.DID ); ability.addCost(new SacrificeTargetCost(filter)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/f/FunnelWebRecluse.java b/Mage.Sets/src/mage/cards/f/FunnelWebRecluse.java index 30d29cc8ed1..196b73abc90 100644 --- a/Mage.Sets/src/mage/cards/f/FunnelWebRecluse.java +++ b/Mage.Sets/src/mage/cards/f/FunnelWebRecluse.java @@ -3,12 +3,12 @@ package mage.cards.f; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.MorbidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.keyword.InvestigateEffect; import mage.abilities.hint.common.MorbidHint; import mage.abilities.keyword.ReachAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; @@ -30,12 +30,8 @@ public final class FunnelWebRecluse extends CardImpl { this.addAbility(ReachAbility.getInstance()); // Morbid — When Funnel-Web Recluse enters the battlefield, if a creature died this turn, investigate. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new InvestigateEffect()), - MorbidCondition.instance, "Morbid — When {this} enters, " + - "if a creature died this turn, investigate. (Create a colorless Clue artifact token " + - "with \"{2}, Sacrifice this artifact: Draw a card.\")" - ).addHint(MorbidHint.instance)); + this.addAbility(new EntersBattlefieldTriggeredAbility(new InvestigateEffect()) + .withInterveningIf(MorbidCondition.instance).setAbilityWord(AbilityWord.MORBID).addHint(MorbidHint.instance)); } private FunnelWebRecluse(final FunnelWebRecluse card) { diff --git a/Mage.Sets/src/mage/cards/f/FuriousResistance.java b/Mage.Sets/src/mage/cards/f/FuriousResistance.java index f56a4387d0e..1b399b95b25 100644 --- a/Mage.Sets/src/mage/cards/f/FuriousResistance.java +++ b/Mage.Sets/src/mage/cards/f/FuriousResistance.java @@ -16,6 +16,7 @@ import mage.filter.common.FilterBlockingCreature; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; @@ -32,7 +33,7 @@ public final class FuriousResistance extends CardImpl { // Target blocking creature gets +3/+0 and gains first strike until end of turn. this.getSpellAbility().addEffect(new FuriousResistanceEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private FuriousResistance(final FuriousResistance card) { diff --git a/Mage.Sets/src/mage/cards/f/FuriousRise.java b/Mage.Sets/src/mage/cards/f/FuriousRise.java index 74e1cb4d663..76265389d70 100644 --- a/Mage.Sets/src/mage/cards/f/FuriousRise.java +++ b/Mage.Sets/src/mage/cards/f/FuriousRise.java @@ -2,17 +2,20 @@ package mage.cards.f; import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.common.FerociousCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.AsThoughEffect; import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.hint.common.FerociousHint; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +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.FixedTarget; @@ -31,9 +34,8 @@ public final class FuriousRise extends CardImpl { // At the beginning of your end step, if you control a creature with power 4 or greater, exile the top card of your library. // You may play that card until you exile another card with Furious Rise. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfEndStepTriggeredAbility( - new FuriousRiseEffect()), FerociousCondition.instance, - "At the beginning of your end step, if you control a creature with power 4 or greater, exile the top card of your library. You may play that card until you exile another card with {this}.")); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new FuriousRiseEffect()) + .withInterveningIf(FerociousCondition.instance).addHint(FerociousHint.instance)); } private FuriousRise(final FuriousRise card) { @@ -50,7 +52,7 @@ class FuriousRiseEffect extends OneShotEffect { FuriousRiseEffect() { super(Outcome.Benefit); - this.staticText = "exile the top card of your library. You may play that card until you exile another card with Furious Rise"; + this.staticText = "exile the top card of your library. You may play that card until you exile another card with {this}"; } private FuriousRiseEffect(final FuriousRiseEffect effect) { diff --git a/Mage.Sets/src/mage/cards/f/FurnaceDragon.java b/Mage.Sets/src/mage/cards/f/FurnaceDragon.java index 7a95df32bb3..126f065c409 100644 --- a/Mage.Sets/src/mage/cards/f/FurnaceDragon.java +++ b/Mage.Sets/src/mage/cards/f/FurnaceDragon.java @@ -1,11 +1,8 @@ - package mage.cards.f; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromHandSourcePermanentCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ExileAllEffect; import mage.abilities.keyword.AffinityForArtifactsAbility; import mage.abilities.keyword.FlyingAbility; @@ -13,23 +10,18 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.watchers.common.CastFromHandWatcher; +import java.util.UUID; + /** - * * @author fireshoes */ public final class FurnaceDragon extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("artifacts"); - - static { - filter.add(CardType.ARTIFACT.getPredicate()); - } - public FurnaceDragon(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{6}{R}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{R}{R}{R}"); this.subtype.add(SubType.DRAGON); this.power = new MageInt(5); this.toughness = new MageInt(5); @@ -41,11 +33,9 @@ public final class FurnaceDragon extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // 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), - CastFromHandSourcePermanentCondition.instance, - "When {this} enters, if you cast it from your hand, exile all artifacts."), - new CastFromHandWatcher()); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new ExileAllEffect(StaticFilters.FILTER_PERMANENT_ARTIFACTS) + ).withInterveningIf(CastFromHandSourcePermanentCondition.instance), new CastFromHandWatcher()); } private FurnaceDragon(final FurnaceDragon card) { diff --git a/Mage.Sets/src/mage/cards/f/FyndhornDruid.java b/Mage.Sets/src/mage/cards/f/FyndhornDruid.java index c02c7dbc05e..89d02d9a0f4 100644 --- a/Mage.Sets/src/mage/cards/f/FyndhornDruid.java +++ b/Mage.Sets/src/mage/cards/f/FyndhornDruid.java @@ -1,13 +1,11 @@ package mage.cards.f; -import java.util.UUID; import mage.MageInt; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -17,22 +15,23 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.watchers.common.WasBlockedThisTurnWatcher; +import java.util.UUID; + /** - * * @author L_J */ public final class FyndhornDruid extends CardImpl { public FyndhornDruid(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}"); + 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 Fyndhorn Druid dies, if it was blocked this turn, you gain 4 life. - 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()); + this.addAbility(new DiesSourceTriggeredAbility(new GainLifeEffect(4)) + .withInterveningIf(FyndhornDruidCondition.instance), new WasBlockedThisTurnWatcher()); } private FyndhornDruid(final FyndhornDruid card) { @@ -45,7 +44,8 @@ public final class FyndhornDruid extends CardImpl { } } -class SourceWasBlockedThisTurnCondition implements Condition { +enum FyndhornDruidCondition implements Condition { + instance; @Override public boolean apply(Game game, Ability source) { @@ -53,4 +53,9 @@ class SourceWasBlockedThisTurnCondition implements Condition { WasBlockedThisTurnWatcher watcher = game.getState().getWatcher(WasBlockedThisTurnWatcher.class); return sourcePermanent != null && watcher != null && watcher.getWasBlockedThisTurnCreatures().contains(new MageObjectReference(sourcePermanent, game)); } + + @Override + public String toString() { + return "it was blocked this turn"; + } } diff --git a/Mage.Sets/src/mage/cards/g/GOTOJAIL.java b/Mage.Sets/src/mage/cards/g/GOTOJAIL.java index 7f4fa3d699f..730b6accdfe 100644 --- a/Mage.Sets/src/mage/cards/g/GOTOJAIL.java +++ b/Mage.Sets/src/mage/cards/g/GOTOJAIL.java @@ -18,12 +18,15 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.util.CardUtil; import java.util.List; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * @author spjspj */ @@ -34,7 +37,7 @@ public final class GOTOJAIL extends CardImpl { // When GO TO JAIL enters the battlefield, exile target creature an opponent controls until GO TO JAIL leaves the battlefield. Ability ability = new EntersBattlefieldTriggeredAbility(new GoToJailExileEffect()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); // At the beginning of the upkeep of the exiled card's owner, that player rolls two six-sided dice. If they roll doubles, sacrifice GO TO JAIL. diff --git a/Mage.Sets/src/mage/cards/g/GaeasCourser.java b/Mage.Sets/src/mage/cards/g/GaeasCourser.java index 977999527ad..d1a4fdde5f8 100644 --- a/Mage.Sets/src/mage/cards/g/GaeasCourser.java +++ b/Mage.Sets/src/mage/cards/g/GaeasCourser.java @@ -1,26 +1,25 @@ package mage.cards.g; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInControllerGraveyardCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SubType; import mage.filter.StaticFilters; +import java.util.UUID; + /** - * * @author weirddan455 */ public final class GaeasCourser extends CardImpl { private static final Condition condition - = new CardsInControllerGraveyardCondition(3, StaticFilters.FILTER_CARD_CREATURE); + = new CardsInControllerGraveyardCondition(3, StaticFilters.FILTER_CARD_CREATURES); public GaeasCourser(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}"); @@ -31,11 +30,7 @@ public final class GaeasCourser extends CardImpl { this.toughness = new MageInt(5); // Whenever Gaea's Courser attacks, if there are three or more creature cards in your graveyard, draw a card. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new DrawCardSourceControllerEffect(1)), - condition, - "Whenever {this} attacks, if there are three or more creature cards in your graveyard, draw a card." - )); + this.addAbility(new AttacksTriggeredAbility(new DrawCardSourceControllerEffect(1)).withInterveningIf(condition)); } private GaeasCourser(final GaeasCourser card) { diff --git a/Mage.Sets/src/mage/cards/g/GaladrielElvenQueen.java b/Mage.Sets/src/mage/cards/g/GaladrielElvenQueen.java index 27298b87bae..eda2d229fa6 100644 --- a/Mage.Sets/src/mage/cards/g/GaladrielElvenQueen.java +++ b/Mage.Sets/src/mage/cards/g/GaladrielElvenQueen.java @@ -3,10 +3,9 @@ package mage.cards.g; import mage.MageInt; import mage.MageObjectReference; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.choices.TwoChoiceVote; @@ -35,18 +34,9 @@ public final class GaladrielElvenQueen extends CardImpl { this.toughness = new MageInt(5); // Will of the council -- At the beginning of combat on your turn, if another Elf entered the battlefield under your control this turn, starting with you, each player votes for dominion or guidance. If dominion gets more votes, the Ring tempts you, then you put a +1/+1 counter on your Ring-bearer. If guidance gets more votes or the vote is tied, draw a card. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility( - Zone.BATTLEFIELD, - TargetController.YOU, new GaladrielElvenQueenEffect(), - false - ), - GaladrielElvenQueenCondition.instance, - "At the beginning of combat on your turn, if another Elf entered the battlefield under " - + "your control this turn, starting with you, each player votes for dominion or guidance. " - + "If dominion gets more votes, the Ring tempts you, then you put a +1/+1 counter on your " - + "Ring-bearer. If guidance gets more votes or the vote is tied, draw a card." - ).setAbilityWord(AbilityWord.WILL_OF_THE_COUNCIL), new GaladrielElvenQueenWatcher()); + this.addAbility(new BeginningOfCombatTriggeredAbility( + Zone.BATTLEFIELD, TargetController.YOU, new GaladrielElvenQueenEffect(), false + ).withInterveningIf(GaladrielElvenQueenCondition.instance).setAbilityWord(AbilityWord.WILL_OF_THE_COUNCIL), new GaladrielElvenQueenWatcher()); } private GaladrielElvenQueen(final GaladrielElvenQueen card) { @@ -73,6 +63,11 @@ enum GaladrielElvenQueenCondition implements Condition { source.getControllerId() ); } + + @Override + public String toString() { + return "another Elf entered the battlefield under your control this turn"; + } } class GaladrielElvenQueenWatcher extends Watcher { diff --git a/Mage.Sets/src/mage/cards/g/GaleWaterdeepProdigy.java b/Mage.Sets/src/mage/cards/g/GaleWaterdeepProdigy.java index c7a50440a70..67471e9fd54 100644 --- a/Mage.Sets/src/mage/cards/g/GaleWaterdeepProdigy.java +++ b/Mage.Sets/src/mage/cards/g/GaleWaterdeepProdigy.java @@ -1,21 +1,20 @@ package mage.cards.g; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.ChooseABackgroundAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.effects.common.MayCastTargetCardEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.SuperType; +import mage.constants.*; import mage.filter.FilterCard; -import mage.filter.common.FilterInstantOrSorcerySpell; +import mage.filter.StaticFilters; import mage.game.Game; -import mage.game.events.GameEvent; import mage.game.stack.Spell; import mage.target.common.TargetCardInYourGraveyard; -import mage.watchers.common.CastFromHandWatcher; +import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetpointer.FirstTargetPointer; import java.util.UUID; @@ -36,7 +35,14 @@ public final class GaleWaterdeepProdigy extends CardImpl { // Whenever you cast an instant or sorcery spell from your hand, // you may cast up to one of the other type from your graveyard. // If a spell cast from your graveyard this way would be put into your graveyard, exile it instead. - this.addAbility(new GaleWaterdeepProdigyTriggeredAbility()); + Ability ability = new SpellCastControllerTriggeredAbility(Zone.BATTLEFIELD, + new MayCastTargetCardEffect(true) + .setText("you may cast up to one target card of the other type from your graveyard. If a spell cast from your graveyard this way would be put into your graveyard, exile it instead."), + StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, + false, SetTargetPointer.SPELL, Zone.HAND + ); + ability.setTargetAdjuster(GaleWaterdeepProdigyAdjuster.instance); + this.addAbility(ability); // Choose a Background this.addAbility(ChooseABackgroundAbility.getInstance()); @@ -52,7 +58,8 @@ public final class GaleWaterdeepProdigy extends CardImpl { } } -class GaleWaterdeepProdigyTriggeredAbility extends SpellCastControllerTriggeredAbility { +enum GaleWaterdeepProdigyAdjuster implements TargetAdjuster { + instance; private static final FilterCard SORCERY_FILTER = new FilterCard("a sorcery card in your graveyard"); private static final FilterCard INSTANT_FILTER = new FilterCard("an instant card in your graveyard"); @@ -61,51 +68,22 @@ class GaleWaterdeepProdigyTriggeredAbility extends SpellCastControllerTriggeredA SORCERY_FILTER.add(CardType.SORCERY.getPredicate()); INSTANT_FILTER.add(CardType.INSTANT.getPredicate()); } - - public GaleWaterdeepProdigyTriggeredAbility() { - super( - new MayCastTargetCardEffect(true) - .setText("you may cast up to one target card of the other type from your graveyard. " - + "If a spell cast from your graveyard this way would be put into your graveyard, exile it instead."), - new FilterInstantOrSorcerySpell("an instant or sorcery spell from your hand"), - false - ); - addWatcher(new CastFromHandWatcher()); - } - - private GaleWaterdeepProdigyTriggeredAbility(final GaleWaterdeepProdigyTriggeredAbility ability) { - super(ability); - } - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (!super.checkTrigger(event, game)) { - return false; - } + public void adjustTargets(Ability ability, Game game) { + UUID spellId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability); + ability.getTargets().clear(); + ability.getAllEffects().setTargetPointer(new FirstTargetPointer()); - CastFromHandWatcher watcher = game.getState().getWatcher(CastFromHandWatcher.class); - if (watcher == null || !watcher.spellWasCastFromHand(event.getSourceId())) { - return false; - } - - Spell spell = game.getState().getStack().getSpell(event.getSourceId()); + Spell spell = game.getSpellOrLKIStack(spellId); if (spell == null) { - return false; + return; } - - FilterCard filterCard; + FilterCard filter; if (spell.isSorcery(game)) { - filterCard = INSTANT_FILTER; + filter = INSTANT_FILTER; } else { - filterCard = SORCERY_FILTER; + filter = SORCERY_FILTER; } - this.getTargets().clear(); - this.getTargets().add(new TargetCardInYourGraveyard(filterCard)); - return true; + ability.addTarget(new TargetCardInYourGraveyard(0, 1, filter)); } - - @Override - public GaleWaterdeepProdigyTriggeredAbility copy() { - return new GaleWaterdeepProdigyTriggeredAbility(this); - } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/g/GalepowderMage.java b/Mage.Sets/src/mage/cards/g/GalepowderMage.java index 91b441fdc4a..ea12ca3153b 100644 --- a/Mage.Sets/src/mage/cards/g/GalepowderMage.java +++ b/Mage.Sets/src/mage/cards/g/GalepowderMage.java @@ -10,10 +10,13 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * @author LevelX2 */ @@ -31,7 +34,7 @@ public final class GalepowderMage extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Whenever Galepowder Mage attacks, exile another target creature. Return that card to the battlefield under its owner's control at the beginning of the next end step. Ability ability = new AttacksTriggeredAbility(new ExileReturnBattlefieldNextEndStepTargetEffect(), false); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/Galestrike.java b/Mage.Sets/src/mage/cards/g/Galestrike.java index d148c224a39..4a050605fee 100644 --- a/Mage.Sets/src/mage/cards/g/Galestrike.java +++ b/Mage.Sets/src/mage/cards/g/Galestrike.java @@ -9,6 +9,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -28,7 +29,7 @@ public final class Galestrike extends CardImpl { // Return target tapped creature to its owner's hand. this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("
")); diff --git a/Mage.Sets/src/mage/cards/g/Gallantry.java b/Mage.Sets/src/mage/cards/g/Gallantry.java index c70f8ccc2b6..2386fe06fe1 100644 --- a/Mage.Sets/src/mage/cards/g/Gallantry.java +++ b/Mage.Sets/src/mage/cards/g/Gallantry.java @@ -10,6 +10,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.filter.common.FilterBlockingCreature; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -26,7 +27,7 @@ public final class Gallantry extends CardImpl { // Target blocking creature gets +4/+4 until end of turn. this.getSpellAbility().addEffect(new BoostTargetEffect(4, 4, Duration.EndOfTurn)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("
")); } diff --git a/Mage.Sets/src/mage/cards/g/GallifreyFallsNoMore.java b/Mage.Sets/src/mage/cards/g/GallifreyFallsNoMore.java index 239abcb8d91..f4c0f6e8631 100644 --- a/Mage.Sets/src/mage/cards/g/GallifreyFallsNoMore.java +++ b/Mage.Sets/src/mage/cards/g/GallifreyFallsNoMore.java @@ -1,11 +1,5 @@ - package mage.cards.g; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.DamageAllEffect; import mage.abilities.effects.common.PhaseOutTargetEffect; import mage.abilities.effects.common.replacement.DealtDamageToCreatureBySourceDies; @@ -13,40 +7,34 @@ import mage.cards.CardSetInfo; import mage.cards.SplitCard; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Outcome; import mage.constants.SpellAbilityType; -import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; -import mage.game.Game; -import mage.game.permanent.token.CentaurToken; -import mage.players.Player; import mage.target.common.TargetControlledCreaturePermanent; import mage.watchers.common.DamagedByWatcher; +import java.util.UUID; + /** - * * @author dragonfyre23 */ public final class GallifreyFallsNoMore extends SplitCard { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("target creatures you control"); public GallifreyFallsNoMore(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{R}{R}", "{2}{W}", SpellAbilityType.SPLIT_FUSED); // Gallifrey Falls // Gallifrey Falls deals 4 damage to each creature. - getLeftHalfCard().getSpellAbility().addEffect(new DamageAllEffect(4, new FilterCreaturePermanent())); + this.getLeftHalfCard().getSpellAbility().addEffect(new DamageAllEffect(4, new FilterCreaturePermanent())); //If a creature dealt damage this way would die this turn, exile it instead. - getLeftHalfCard().getSpellAbility().addEffect(new DealtDamageToCreatureBySourceDies(getLeftHalfCard(), Duration.EndOfTurn)); - getLeftHalfCard().getSpellAbility().addWatcher(new DamagedByWatcher(false)); + this.getLeftHalfCard().getSpellAbility().addEffect(new DealtDamageToCreatureBySourceDies(this.getLeftHalfCard(), Duration.EndOfTurn)); + this.getLeftHalfCard().getSpellAbility().addWatcher(new DamagedByWatcher(false)); // No More // Any number of target creatures you control phase out. - getRightHalfCard().getSpellAbility().addEffect(new PhaseOutTargetEffect()); - getRightHalfCard().getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, filter, false)); - + this.getRightHalfCard().getSpellAbility().addEffect(new PhaseOutTargetEffect()); + this.getRightHalfCard().getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE)); } private GallifreyFallsNoMore(final GallifreyFallsNoMore card) { diff --git a/Mage.Sets/src/mage/cards/g/GalvanicBombardment.java b/Mage.Sets/src/mage/cards/g/GalvanicBombardment.java index 408b6a76962..56987b65038 100644 --- a/Mage.Sets/src/mage/cards/g/GalvanicBombardment.java +++ b/Mage.Sets/src/mage/cards/g/GalvanicBombardment.java @@ -1,7 +1,6 @@ package mage.cards.g; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; @@ -17,8 +16,9 @@ import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes * modified tiera3 - added Hint */ @@ -29,16 +29,17 @@ public final class GalvanicBombardment extends CardImpl { static { filter.add(new NamePredicate("Galvanic Bombardment")); } + private static final Hint hint = new ValueHint( "Cards named Galvanic Bombardment in your graveyard", new GalvanicBombardmentCardsInControllerGraveyardCount(filter) ); public GalvanicBombardment(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{R}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}"); // Galvanic Bombardment deals X damage to target creature, where X is 2 plus the number of cards named Galvanic Bombardment in your graveyard. Effect effect = new DamageTargetEffect(new GalvanicBombardmentCardsInControllerGraveyardCount(filter)); - effect.setText("{this} deals X damage to target creature, where X is 2 plus the number of cards named {this} in your graveyard"); + effect.setText("{this} deals X damage to target creature, where X is 2 plus the number of cards named Galvanic Bombardment in your graveyard"); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addHint(hint); @@ -71,8 +72,8 @@ class GalvanicBombardmentCardsInControllerGraveyardCount implements DynamicValue int amount = 0; Player controller = game.getPlayer(sourceAbility.getControllerId()); if (controller != null) { - amount += controller.getGraveyard().count(filter, sourceAbility.getControllerId(), sourceAbility, game); - } + amount += controller.getGraveyard().count(filter, sourceAbility.getControllerId(), sourceAbility, game); + } return amount + 2; } diff --git a/Mage.Sets/src/mage/cards/g/GangUp.java b/Mage.Sets/src/mage/cards/g/GangUp.java index 12bc2d46121..b63be78de94 100644 --- a/Mage.Sets/src/mage/cards/g/GangUp.java +++ b/Mage.Sets/src/mage/cards/g/GangUp.java @@ -8,11 +8,14 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetadjustment.PowerTargetAdjuster; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE; + /** * @author TheElk801 */ @@ -26,7 +29,7 @@ public final class GangUp extends CardImpl { // Destroy target creature with power X or less. this.getSpellAbility().addEffect(new DestroyTargetEffect("destroy target creature with power X or less")); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE)); this.getSpellAbility().setTargetAdjuster(new PowerTargetAdjuster(ComparisonType.OR_LESS)); } diff --git a/Mage.Sets/src/mage/cards/g/GarbageElementalC.java b/Mage.Sets/src/mage/cards/g/GarbageElementalC.java index d08d8e48842..618280dd5b2 100644 --- a/Mage.Sets/src/mage/cards/g/GarbageElementalC.java +++ b/Mage.Sets/src/mage/cards/g/GarbageElementalC.java @@ -2,7 +2,7 @@ package mage.cards.g; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.BattleCryAbility; import mage.cards.CardImpl; @@ -34,10 +34,7 @@ public final class GarbageElementalC extends CardImpl { this.addAbility(new BattleCryAbility()); // When Garbage Elemental enters the battlefield, roll two six-sided dice. Create a number of 1/1 red Goblin creature tokens equal to the difference between those results. - this.addAbility(new EntersBattlefieldAbility(new GarbageElementalCEffect(), - null, - "When {this} enters, roll two six-sided dice. Create a number of 1/1 red Goblin creature tokens equal to the difference between those results", - null)); + this.addAbility(new EntersBattlefieldTriggeredAbility(new GarbageElementalCEffect())); } diff --git a/Mage.Sets/src/mage/cards/g/GargantuanGorilla.java b/Mage.Sets/src/mage/cards/g/GargantuanGorilla.java index b7f752ece69..92b7d80888d 100644 --- a/Mage.Sets/src/mage/cards/g/GargantuanGorilla.java +++ b/Mage.Sets/src/mage/cards/g/GargantuanGorilla.java @@ -20,6 +20,7 @@ import mage.filter.predicate.mageobject.AnotherPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -42,7 +43,7 @@ public final class GargantuanGorilla extends CardImpl { Ability ability = new SimpleActivatedAbility(new GargantuanGorillaFightEffect(), new TapSourceCost()); FilterCreaturePermanent filter = new FilterCreaturePermanent(); filter.add(AnotherPredicate.instance); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GargosViciousWatcher.java b/Mage.Sets/src/mage/cards/g/GargosViciousWatcher.java index 40e324de19b..abbc020b067 100644 --- a/Mage.Sets/src/mage/cards/g/GargosViciousWatcher.java +++ b/Mage.Sets/src/mage/cards/g/GargosViciousWatcher.java @@ -15,7 +15,7 @@ import mage.constants.SubType; import mage.constants.SuperType; import mage.filter.FilterCard; import mage.filter.StaticFilters; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -45,10 +45,11 @@ public final class GargosViciousWatcher extends CardImpl { this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 4))); // Whenever a creature you control becomes the target of a spell, Gargos, Vicious Watcher fights up to one target creature you don't control. - TriggeredAbility ability = new BecomesTargetAnyTriggeredAbility(new FightTargetSourceEffect(), - StaticFilters.FILTER_CONTROLLED_A_CREATURE, StaticFilters.FILTER_SPELL_A, - SetTargetPointer.NONE, false); - ability.addTarget(new TargetCreaturePermanent(0, 1, StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL, false)); + TriggeredAbility ability = new BecomesTargetAnyTriggeredAbility( + new FightTargetSourceEffect(), StaticFilters.FILTER_CONTROLLED_A_CREATURE, + StaticFilters.FILTER_SPELL_A, SetTargetPointer.NONE, false + ); + ability.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GarzasAssassin.java b/Mage.Sets/src/mage/cards/g/GarzasAssassin.java index d2edccf206b..d57bbbb003d 100644 --- a/Mage.Sets/src/mage/cards/g/GarzasAssassin.java +++ b/Mage.Sets/src/mage/cards/g/GarzasAssassin.java @@ -19,9 +19,12 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.util.CardUtil; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author choiseul11 & L_J @@ -37,7 +40,7 @@ public final class GarzasAssassin extends CardImpl { // Sacrifice Garza's Assassin: Destroy target nonblack creature. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + ability.addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.addAbility(ability); // Recover—Pay half your life, rounded up. diff --git a/Mage.Sets/src/mage/cards/g/GateSmasher.java b/Mage.Sets/src/mage/cards/g/GateSmasher.java index add5d33975e..276d48bc734 100644 --- a/Mage.Sets/src/mage/cards/g/GateSmasher.java +++ b/Mage.Sets/src/mage/cards/g/GateSmasher.java @@ -1,12 +1,8 @@ - package mage.cards.g; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.AttachableToRestrictedAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.keyword.EquipAbility; @@ -15,22 +11,21 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AttachmentType; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.ComparisonType; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ToughnessPredicate; -import mage.target.Target; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class GateSmasher extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature with toughness 4 or greater"); + private static final FilterPermanent filter = new FilterCreaturePermanent("creature with toughness 4 or greater"); static { filter.add(new ToughnessPredicate(ComparisonType.MORE_THAN, 3)); @@ -40,22 +35,18 @@ public final class GateSmasher extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); this.subtype.add(SubType.EQUIPMENT); - Target target = new TargetControlledCreaturePermanent(1, 1, filter, false); // Gate Smasher can be attached only to a creature with toughness 4 or greater. - this.addAbility(new AttachableToRestrictedAbility(target)); + this.addAbility(new AttachableToRestrictedAbility(new TargetPermanent(filter))); // Equipped creature gets +3/+0 and has trample. - Effect effect = new BoostEquippedEffect(3, 0); - effect.setText("Equipped creature gets +3/+0"); - Ability ability = new SimpleStaticAbility(effect); - effect = new GainAbilityAttachedEffect(TrampleAbility.getInstance(), AttachmentType.EQUIPMENT); - effect.setText("and has trample"); - ability.addEffect(effect); + Ability ability = new SimpleStaticAbility(new BoostEquippedEffect(3, 0)); + ability.addEffect(new GainAbilityAttachedEffect( + TrampleAbility.getInstance(), AttachmentType.EQUIPMENT + ).setText("and has trample")); this.addAbility(ability); // Equip {3} - this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(3), target, false)); - + this.addAbility(new EquipAbility(3, false)); } private GateSmasher(final GateSmasher card) { diff --git a/Mage.Sets/src/mage/cards/g/GateToPhyrexia.java b/Mage.Sets/src/mage/cards/g/GateToPhyrexia.java index fee42e3c657..1ac461a9523 100644 --- a/Mage.Sets/src/mage/cards/g/GateToPhyrexia.java +++ b/Mage.Sets/src/mage/cards/g/GateToPhyrexia.java @@ -1,7 +1,5 @@ - package mage.cards.g; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; import mage.abilities.condition.common.IsStepCondition; @@ -10,14 +8,13 @@ import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.PhaseStep; import mage.constants.Zone; import mage.filter.StaticFilters; import mage.target.common.TargetArtifactPermanent; -import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; /** - * * @author fireshoes */ public final class GateToPhyrexia extends CardImpl { @@ -26,9 +23,10 @@ public final class GateToPhyrexia extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{B}{B}"); // Sacrifice a creature: Destroy target artifact. Activate this ability only during your upkeep and only once each turn. - Ability ability = new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), + Ability ability = new LimitedTimesPerTurnActivatedAbility( + Zone.BATTLEFIELD, new DestroyTargetEffect(), new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_CREATURE), - 1, new IsStepCondition(PhaseStep.UPKEEP)); + 1, IsStepCondition.getMyUpkeep()); ability.addTarget(new TargetArtifactPermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GateToTheAfterlife.java b/Mage.Sets/src/mage/cards/g/GateToTheAfterlife.java index 83142c9ee67..ea008ad3afc 100644 --- a/Mage.Sets/src/mage/cards/g/GateToTheAfterlife.java +++ b/Mage.Sets/src/mage/cards/g/GateToTheAfterlife.java @@ -1,14 +1,13 @@ package mage.cards.g; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInControllerGraveyardCondition; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalActivatedAbility; -import mage.abilities.effects.Effect; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DrawDiscardControllerEffect; import mage.abilities.effects.common.GainLifeEffect; @@ -17,38 +16,40 @@ 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.FilterCard; import mage.filter.StaticFilters; -import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.NamePredicate; -import mage.filter.predicate.permanent.TokenPredicate; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInHand; import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetCardInYourGraveyard; +import java.util.UUID; + /** * @author LevelX2 */ public final class GateToTheAfterlife extends CardImpl { + private static final Condition condition = new CardsInControllerGraveyardCondition(6, StaticFilters.FILTER_CARD_CREATURES); + public GateToTheAfterlife(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); // Whenever a nontoken creature you control dies, you gain 1 life. Then you may draw a card. If you do, discard a card. - Ability ability = new DiesCreatureTriggeredAbility(new GainLifeEffect(1), false, StaticFilters.FILTER_CONTROLLED_CREATURE_NON_TOKEN, false); - Effect effect = new DrawDiscardControllerEffect(1, 1, true); - effect.setText("Then you may draw a card. If you do, discard a card"); - ability.addEffect(effect); + Ability ability = new DiesCreatureTriggeredAbility( + new GainLifeEffect(1), false, + StaticFilters.FILTER_CONTROLLED_CREATURE_NON_TOKEN, false + ); + ability.addEffect(new DrawDiscardControllerEffect(1, 1, true) + .setText("Then you may draw a card. If you do, discard a card")); this.addAbility(ability); // {2}, {T}, Sacrifice Gate to the Afterlife: Search your graveyard, hand, and/or library for a card named God-Pharaoh's Gift and put it onto the battlefield. If you seearch your library this way, shuffle it. Activate this ability only if there are six or more creature cards in your graveyard. - ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, new GateToTheAfterlifeEffect(), new GenericManaCost(2), - new CardsInControllerGraveyardCondition(6, StaticFilters.FILTER_CARD_CREATURES) + ability = new ActivateIfConditionActivatedAbility( + new GateToTheAfterlifeEffect(), new GenericManaCost(2), condition ); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); diff --git a/Mage.Sets/src/mage/cards/g/GatebreakerRam.java b/Mage.Sets/src/mage/cards/g/GatebreakerRam.java index 8043d5e2d62..5ada9121c46 100644 --- a/Mage.Sets/src/mage/cards/g/GatebreakerRam.java +++ b/Mage.Sets/src/mage/cards/g/GatebreakerRam.java @@ -3,8 +3,7 @@ package mage.cards.g; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.Condition; -import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.condition.common.YouControlTwoOrMoreGatesCondition; import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; @@ -16,10 +15,8 @@ import mage.abilities.keyword.VigilanceAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.ComparisonType; import mage.constants.Duration; import mage.constants.SubType; -import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledPermanent; import java.util.UUID; @@ -29,16 +26,7 @@ import java.util.UUID; */ public final class GatebreakerRam extends CardImpl { - private static final FilterPermanent filter = new FilterControlledPermanent(); - - static { - filter.add(SubType.GATE.getPredicate()); - } - - private static final DynamicValue xValue - = new PermanentsOnBattlefieldCount(filter); - private static final Condition condition - = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1); + private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.GATE)); public GatebreakerRam(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); @@ -50,17 +38,16 @@ public final class GatebreakerRam extends CardImpl { // Gatebreaker Ram gets +1/+1 for each Gate you control. this.addAbility(new SimpleStaticAbility( new BoostSourceEffect(xValue, xValue, Duration.WhileOnBattlefield) - .setText("{this} gets +1/+1 for each Gate you control.") ).addHint(GatesYouControlHint.instance)); // As long as you control two or more Gates, Gatebreaker Ram has vigilance and trample. Ability ability = new SimpleStaticAbility(new ConditionalContinuousEffect( new GainAbilitySourceEffect(VigilanceAbility.getInstance()), - condition, "As long as you control two or more Gates, {this} has vigilance" + YouControlTwoOrMoreGatesCondition.instance, "As long as you control two or more Gates, {this} has vigilance" )); ability.addEffect(new ConditionalContinuousEffect( new GainAbilitySourceEffect(TrampleAbility.getInstance()), - condition, "and trample" + YouControlTwoOrMoreGatesCondition.instance, "and trample" )); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GatewatchBeacon.java b/Mage.Sets/src/mage/cards/g/GatewatchBeacon.java index d3d4f66a06c..a9b7e1b14f3 100644 --- a/Mage.Sets/src/mage/cards/g/GatewatchBeacon.java +++ b/Mage.Sets/src/mage/cards/g/GatewatchBeacon.java @@ -4,8 +4,6 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.Effects; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.mana.WhiteManaAbility; @@ -40,15 +38,10 @@ public final class GatewatchBeacon extends CardImpl { // Whenever a planeswalker you control enters, if Gatewatch Beacon has loyalty // counters on it, you may move a loyalty counter from Gatewatch Beacon onto that planeswalker. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldControlledTriggeredAbility( - Zone.BATTLEFIELD, - new GatewatchBeaconMoveCounterEffect(), - StaticFilters.FILTER_PERMANENT_PLANESWALKER, - true - ), GatewatchBeaconCondition.instance, "Whenever a planeswalker you control enters, if {this} has " + - "loyalty counters on it, you may move a loyalty counter from {this} onto that planeswalker" - )); + this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + Zone.BATTLEFIELD, new GatewatchBeaconMoveCounterEffect(), + StaticFilters.FILTER_PERMANENT_PLANESWALKER, true + ).withInterveningIf(GatewatchBeaconCondition.instance)); } private GatewatchBeacon(final GatewatchBeacon card) { @@ -67,15 +60,12 @@ enum GatewatchBeaconCondition implements Condition { @Override public boolean apply(Game game, Ability source) { Permanent permanent = source.getSourcePermanentIfItStillExists(game); - if (permanent == null) { - return false; - } - Effects effects = source.getEffects(); - if (effects.isEmpty()) { - return false; - } + return permanent != null && permanent.getCounters(game).getCount(CounterType.LOYALTY) > 0; + } - return permanent.getCounters(game).getCount(CounterType.LOYALTY) > 0; + @Override + public String toString() { + return "{this} has loyalty counters on it"; } } diff --git a/Mage.Sets/src/mage/cards/g/GazeOfJustice.java b/Mage.Sets/src/mage/cards/g/GazeOfJustice.java index eb15c2a56cb..988ddebe374 100644 --- a/Mage.Sets/src/mage/cards/g/GazeOfJustice.java +++ b/Mage.Sets/src/mage/cards/g/GazeOfJustice.java @@ -1,7 +1,5 @@ - package mage.cards.g; -import java.util.UUID; import mage.ObjectColor; import mage.abilities.costs.common.TapTargetCost; import mage.abilities.costs.mana.ManaCostsImpl; @@ -10,20 +8,21 @@ import mage.abilities.keyword.FlashbackAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.TimingRule; import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class GazeOfJustice extends CardImpl { - - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped white creatures you control"); + + private static final FilterControlledPermanent filter = new FilterControlledCreaturePermanent("untapped white creatures you control"); static { filter.add(new ColorPredicate(ObjectColor.WHITE)); @@ -31,15 +30,15 @@ public final class GazeOfJustice extends CardImpl { } public GazeOfJustice(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{W}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{W}"); // As an additional cost to cast Gaze of Justice, tap three untapped white creatures you control. - this.getSpellAbility().addCost(new TapTargetCost(new TargetControlledCreaturePermanent(3, 3, filter, true))); - + this.getSpellAbility().addCost(new TapTargetCost(new TargetControlledPermanent(3, filter))); + // Exile target creature. this.getSpellAbility().addEffect(new ExileTargetEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - + // Flashback {5}{W} this.addAbility(new FlashbackAbility(this, new ManaCostsImpl<>("{5}{W}"))); } diff --git a/Mage.Sets/src/mage/cards/g/GazeOfTheGorgon.java b/Mage.Sets/src/mage/cards/g/GazeOfTheGorgon.java index 176fa182f0c..b0c2e7afb80 100644 --- a/Mage.Sets/src/mage/cards/g/GazeOfTheGorgon.java +++ b/Mage.Sets/src/mage/cards/g/GazeOfTheGorgon.java @@ -102,7 +102,7 @@ class GazeOfTheGorgonEffect extends OneShotEffect { List toDestroy = new ArrayList<>(); for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source, game)) { if (!creature.getId().equals(targetCreature.getSourceId())) { - if (watcher.creatureHasBlockedAttacker(new MageObjectReference(creature, game), targetCreature, game) || watcher.creatureHasBlockedAttacker(targetCreature, new MageObjectReference(creature, game), game)) { + if (watcher.creatureHasBlockedAttacker(new MageObjectReference(creature, game), targetCreature) || watcher.creatureHasBlockedAttacker(targetCreature, new MageObjectReference(creature, game))) { toDestroy.add(creature); } } diff --git a/Mage.Sets/src/mage/cards/g/GeistcatchersRig.java b/Mage.Sets/src/mage/cards/g/GeistcatchersRig.java index 5f468e3b4c1..48ef5dc2ea2 100644 --- a/Mage.Sets/src/mage/cards/g/GeistcatchersRig.java +++ b/Mage.Sets/src/mage/cards/g/GeistcatchersRig.java @@ -13,6 +13,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -35,7 +36,7 @@ public final class GeistcatchersRig extends CardImpl { this.toughness = new MageInt(5); // When Geistcatcher's Rig enters the battlefield, you may have it deal 4 damage to target creature with flying. Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(4), true); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GeneralJarkeld.java b/Mage.Sets/src/mage/cards/g/GeneralJarkeld.java index f05d68a0bf5..7644cc8e9b4 100644 --- a/Mage.Sets/src/mage/cards/g/GeneralJarkeld.java +++ b/Mage.Sets/src/mage/cards/g/GeneralJarkeld.java @@ -1,11 +1,11 @@ - package mage.cards.g; import mage.MageInt; import mage.abilities.Ability; +import mage.abilities.common.ActivateIfConditionActivatedAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -22,11 +22,12 @@ import java.util.Set; import java.util.UUID; /** - * * @author L_J */ public final class GeneralJarkeld extends CardImpl { + private static final Condition condition = new IsStepCondition(PhaseStep.DECLARE_BLOCKERS, false); + public GeneralJarkeld(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); this.supertype.add(SuperType.LEGENDARY); @@ -36,7 +37,9 @@ public final class GeneralJarkeld extends CardImpl { this.toughness = new MageInt(2); // {T}: Switch the blocking creatures of two target attacking creatures. Activate this ability only during the declare blockers step. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new GeneralJarkeldSwitchBlockersEffect(), new TapSourceCost(), new IsStepCondition(PhaseStep.DECLARE_BLOCKERS, false)); + Ability ability = new ActivateIfConditionActivatedAbility( + new GeneralJarkeldSwitchBlockersEffect(), new TapSourceCost(), condition + ); ability.addTarget(new TargetAttackingCreature(2)); this.addAbility(ability); } @@ -56,7 +59,9 @@ class GeneralJarkeldSwitchBlockersEffect extends OneShotEffect { GeneralJarkeldSwitchBlockersEffect() { super(Outcome.Benefit); - this.staticText = "Switch the blocking creatures of two target attacking creatures"; + this.staticText = "choose two target blocked attacking creatures. If each of those creatures could be " + + "blocked by all creatures that the other is blocked by, each creature that's blocking exactly one " + + "of those attacking creatures stops blocking it and is blocking the other attacking creature"; } private GeneralJarkeldSwitchBlockersEffect(final GeneralJarkeldSwitchBlockersEffect effect) { @@ -82,14 +87,14 @@ class GeneralJarkeldSwitchBlockersEffect extends OneShotEffect { Set blockers1 = new HashSet<>(); Set blockers2 = new HashSet<>(); Set multiBlockers = new HashSet<>(); - + blockerSearch1: for (UUID blockerId : chosenGroup1.getBlockers()) { Permanent blocker = game.getPermanent(blockerId); if (blocker != null) { if (game.getCombat().blockingGroupsContains(blocker.getId())) { // if (blocker.getBlocking() > 1) { for (CombatGroup group : game.getCombat().getBlockingGroups()) { - if (group.getBlockers().contains(blocker.getId())) { + if (group.getBlockers().contains(blocker.getId())) { int attackerCount = group.getAttackers().size(); if (attackerCount > 1) { multiBlockers.add(blocker); @@ -104,7 +109,7 @@ class GeneralJarkeldSwitchBlockersEffect extends OneShotEffect { } } } - + blockerSearch2: for (UUID blockerId : chosenGroup2.getBlockers()) { Permanent blocker = game.getPermanent(blockerId); @@ -126,11 +131,11 @@ class GeneralJarkeldSwitchBlockersEffect extends OneShotEffect { } } } - + handleSingleBlockers(blockers1, chosenGroup1, chosenGroup2, controller, game); handleSingleBlockers(blockers2, chosenGroup2, chosenGroup1, controller, game); handleMultiBlockers(multiBlockers, chosenGroup1, chosenGroup2, controller, game); - + // the ability doesn't unblock a group that loses all blockers, however it will newly block a previously unblocked group if it gains a blocker this way if (!(chosenGroup1.getBlockers().isEmpty())) { chosenGroup1.setBlocked(true, game); @@ -179,7 +184,7 @@ class GeneralJarkeldSwitchBlockersEffect extends OneShotEffect { } } } - + if (sameBlocked && chosenGroup != null) { // if none (should not happen) or all the blockers correspond to Jarkeld's targets, the blockers remain the same CombatGroup otherGroup = (chosenGroup.equals(chosenGroup1) ? chosenGroup2 : chosenGroup1); chosenGroup.remove(blocker.getId()); diff --git a/Mage.Sets/src/mage/cards/g/GenesisChamber.java b/Mage.Sets/src/mage/cards/g/GenesisChamber.java index 8a008b95dd0..1f9524e8727 100644 --- a/Mage.Sets/src/mage/cards/g/GenesisChamber.java +++ b/Mage.Sets/src/mage/cards/g/GenesisChamber.java @@ -1,10 +1,8 @@ package mage.cards.g; import mage.abilities.Ability; -import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.condition.common.SourceTappedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -28,12 +26,11 @@ public final class GenesisChamber extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); // Whenever a nontoken creature enters the battlefield, if Genesis Chamber is untapped, that creature's controller creates a 1/1 colorless Myr artifact creature token. - TriggeredAbility ability = new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new GenesisChamberEffect(), StaticFilters.FILTER_CREATURE_NON_TOKEN, false, SetTargetPointer.PERMANENT); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, - SourceTappedCondition.UNTAPPED, - "Whenever a nontoken creature enters, " - + "if {this} is untapped, " - + "that creature's controller creates a 1/1 colorless Myr artifact creature token")); + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + Zone.BATTLEFIELD, new GenesisChamberEffect(), + StaticFilters.FILTER_CREATURE_NON_TOKEN, + false, SetTargetPointer.PERMANENT + ).withInterveningIf(SourceTappedCondition.UNTAPPED)); } private GenesisChamber(final GenesisChamber card) { diff --git a/Mage.Sets/src/mage/cards/g/GeologicalAppraiser.java b/Mage.Sets/src/mage/cards/g/GeologicalAppraiser.java index 14d9e76c83b..d330e3772a9 100644 --- a/Mage.Sets/src/mage/cards/g/GeologicalAppraiser.java +++ b/Mage.Sets/src/mage/cards/g/GeologicalAppraiser.java @@ -3,7 +3,6 @@ package mage.cards.g; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromEverywhereSourceCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.keyword.DiscoverEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -26,11 +25,7 @@ public final class GeologicalAppraiser extends CardImpl { this.toughness = new MageInt(2); // When Geological Appraiser enters the battlefield, if you cast it, discover 3. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DiscoverEffect(3)), - CastFromEverywhereSourceCondition.instance, - "When {this} enters, if you cast it, discover 3." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new DiscoverEffect(3)).withInterveningIf(CastFromEverywhereSourceCondition.instance)); } private GeologicalAppraiser(final GeologicalAppraiser card) { diff --git a/Mage.Sets/src/mage/cards/g/GerrardCapashen.java b/Mage.Sets/src/mage/cards/g/GerrardCapashen.java index ef9083d6696..4de35db4600 100644 --- a/Mage.Sets/src/mage/cards/g/GerrardCapashen.java +++ b/Mage.Sets/src/mage/cards/g/GerrardCapashen.java @@ -1,31 +1,31 @@ - package mage.cards.g; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.SourceAttackingCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.dynamicvalue.common.CardsInTargetHandCount; +import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.SuperType; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetOpponent; +import java.util.UUID; + /** - * * @author FenrisulfrX */ public final class GerrardCapashen extends CardImpl { public GerrardCapashen(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.SOLDIER); @@ -33,16 +33,17 @@ public final class GerrardCapashen extends CardImpl { this.toughness = new MageInt(4); // At the beginning of your upkeep, you gain 1 life for each card in target opponent's hand. - Ability ability1 = new BeginningOfUpkeepTriggeredAbility(new GerrardCapashenEffect() - ); - ability1.addTarget(new TargetOpponent()); - this.addAbility(ability1); + Ability ability = new BeginningOfUpkeepTriggeredAbility(new GainLifeEffect(CardsInTargetHandCount.instance) + .setText("you gain 1 life for each card in target opponent's hand")); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); // {3}{W}: Tap target creature. Activate this ability only if {this} is attacking. - Ability ability2 = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), - new ManaCostsImpl<>("{3}{W}"), SourceAttackingCondition.instance); - ability2.addTarget(new TargetCreaturePermanent()); - this.addAbility(ability2); + ability = new ActivateIfConditionActivatedAbility( + new TapTargetEffect(), new ManaCostsImpl<>("{3}{W}"), SourceAttackingCondition.instance + ); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); } private GerrardCapashen(final GerrardCapashen card) { @@ -54,34 +55,3 @@ public final class GerrardCapashen extends CardImpl { return new GerrardCapashen(this); } } - -class GerrardCapashenEffect extends OneShotEffect { - - GerrardCapashenEffect() { - super(Outcome.GainLife); - staticText = "you gain 1 life for each card in target opponent's hand."; - } - - private GerrardCapashenEffect(final GerrardCapashenEffect effect) { - super(effect); - } - - @Override - public GerrardCapashenEffect copy() { - return new GerrardCapashenEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - Player targetOpponent = game.getPlayer(this.getTargetPointer().getFirst(game, source)); - if (controller != null && targetOpponent != null) { - int cardsInHand = targetOpponent.getHand().size(); - if (cardsInHand > 0) { - controller.gainLife(cardsInHand, game, source); - } - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/g/GetawayGlamer.java b/Mage.Sets/src/mage/cards/g/GetawayGlamer.java index 59b5b92dafa..a6ce3f7a4bd 100644 --- a/Mage.Sets/src/mage/cards/g/GetawayGlamer.java +++ b/Mage.Sets/src/mage/cards/g/GetawayGlamer.java @@ -15,6 +15,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TokenPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.List; @@ -41,7 +42,7 @@ public final class GetawayGlamer extends CardImpl { // + {1} -- Exile target nontoken creature. Return it to the battlefield under its owner's control at the beginning of the next end step. this.getSpellAbility().addEffect(new ExileReturnBattlefieldNextEndStepTargetEffect().withTextThatCard(false)); this.getSpellAbility().addTarget( - new TargetCreaturePermanent(filter).withChooseHint("to exile") + new TargetPermanent(filter).withChooseHint("to exile") ); this.getSpellAbility().withFirstModeCost(new GenericManaCost(1)); diff --git a/Mage.Sets/src/mage/cards/g/GhastlyDemise.java b/Mage.Sets/src/mage/cards/g/GhastlyDemise.java index 325d906c4cc..8159fb3594b 100644 --- a/Mage.Sets/src/mage/cards/g/GhastlyDemise.java +++ b/Mage.Sets/src/mage/cards/g/GhastlyDemise.java @@ -10,10 +10,13 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * @author cbt33 */ @@ -23,7 +26,7 @@ public final class GhastlyDemise extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}"); // Destroy target nonblack creature if its toughness is less than or equal to the number of cards in your graveyard. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.getSpellAbility().addEffect(new GhastlyDemiseEffect()); } diff --git a/Mage.Sets/src/mage/cards/g/GhirapurOrrery.java b/Mage.Sets/src/mage/cards/g/GhirapurOrrery.java index 6236d92407c..e3c02e28f66 100644 --- a/Mage.Sets/src/mage/cards/g/GhirapurOrrery.java +++ b/Mage.Sets/src/mage/cards/g/GhirapurOrrery.java @@ -1,40 +1,36 @@ - package mage.cards.g; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.IntCompareCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.CardsInHandCondition; import mage.abilities.effects.common.DrawCardTargetEffect; import mage.abilities.effects.common.continuous.PlayAdditionalLandsAllEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.TargetController; -import mage.constants.Zone; -import mage.game.Game; -import mage.players.Player; + +import java.util.UUID; /** - * * @author emerald000 */ public final class GhirapurOrrery extends CardImpl { + private static final Condition condition = new CardsInHandCondition(ComparisonType.EQUAL_TO, 0, TargetController.ACTIVE); + public GhirapurOrrery(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); // Each player may play an additional land on each of their turns. this.addAbility(new SimpleStaticAbility(new PlayAdditionalLandsAllEffect())); // At the beginning of each player's upkeep, if that player has no cards in hand, that player draws three cards. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(TargetController.ANY, new DrawCardTargetEffect(3), false), - new GhirapurOrreryCondition(), - "At the beginning of each player's upkeep, if that player has no cards in hand, that player draws three cards.")); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + TargetController.EACH_PLAYER, new DrawCardTargetEffect(3), false + ).withInterveningIf(condition)); } private GhirapurOrrery(final GhirapurOrrery card) { @@ -46,19 +42,3 @@ public final class GhirapurOrrery extends CardImpl { return new GhirapurOrrery(this); } } - -class GhirapurOrreryCondition extends IntCompareCondition { - - GhirapurOrreryCondition() { - super(ComparisonType.EQUAL_TO, 0); - } - - @Override - protected int getInputValue(Game game, Ability source) { - Player activePlayer = game.getPlayer(game.getActivePlayerId()); - if (activePlayer != null) { - return activePlayer.getHand().size(); - } - return 0; - } -} diff --git a/Mage.Sets/src/mage/cards/g/GhituAmplifier.java b/Mage.Sets/src/mage/cards/g/GhituAmplifier.java index 19273d99cb8..5a65b5b9370 100644 --- a/Mage.Sets/src/mage/cards/g/GhituAmplifier.java +++ b/Mage.Sets/src/mage/cards/g/GhituAmplifier.java @@ -5,7 +5,6 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.keyword.KickerAbility; @@ -36,11 +35,7 @@ public final class GhituAmplifier extends CardImpl { this.addAbility(new KickerAbility("{2}{U}")); // When Ghitu Amplifier enters the battlefield, if it was kicked, return target creature an opponent controls to its owner's hand. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()), - KickedCondition.ONCE, "When {this} enters, " + - "if it was kicked, return target creature an opponent controls to its owner's hand." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()).withInterveningIf(KickedCondition.ONCE); ability.addTarget(new TargetOpponentsCreaturePermanent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/g/GhituChronicler.java b/Mage.Sets/src/mage/cards/g/GhituChronicler.java index 3ef095a1821..158eeb7c6c2 100644 --- a/Mage.Sets/src/mage/cards/g/GhituChronicler.java +++ b/Mage.Sets/src/mage/cards/g/GhituChronicler.java @@ -1,19 +1,16 @@ - package mage.cards.g; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; import mage.abilities.keyword.KickerAbility; 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.filter.StaticFilters; import mage.target.common.TargetCardInYourGraveyard; import java.util.UUID; @@ -23,9 +20,6 @@ import java.util.UUID; */ public final class GhituChronicler extends CardImpl { - private static final FilterCard filter - = new FilterInstantOrSorceryCard("instant or sorcery card from your graveyard"); - public GhituChronicler(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); @@ -38,12 +32,8 @@ public final class GhituChronicler extends CardImpl { this.addAbility(new KickerAbility("{3}{R}")); // When Ghitu Chronicler enters the battlefield, if it was kicked, return target instant or sorcery card from your graveyard to your hand. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), false), - KickedCondition.ONCE, "When {this} enters, if it was kicked, " + - "return target instant or sorcery card from your graveyard to your hand." - ); - ability.addTarget(new TargetCardInYourGraveyard(filter)); + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect()).withInterveningIf(KickedCondition.ONCE); + ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY_FROM_YOUR_GRAVEYARD)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GhituJourneymage.java b/Mage.Sets/src/mage/cards/g/GhituJourneymage.java index 14249b36e39..5763d4c75ea 100644 --- a/Mage.Sets/src/mage/cards/g/GhituJourneymage.java +++ b/Mage.Sets/src/mage/cards/g/GhituJourneymage.java @@ -1,34 +1,35 @@ package mage.cards.g; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamagePlayersEffect; -import mage.constants.SubType; 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.FilterControlledPermanent; import mage.filter.predicate.mageobject.AnotherPredicate; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class GhituJourneymage extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent("another Wizard"); + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.WIZARD, "you control another Wizard"); static { filter.add(AnotherPredicate.instance); - filter.add(SubType.WIZARD.getPredicate()); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); + public GhituJourneymage(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); @@ -38,12 +39,7 @@ public final class GhituJourneymage extends CardImpl { this.toughness = new MageInt(2); // When Ghitu Journeymage enters the battlefield, if you control another Wizard, Ghitu Journeymage deals 2 damage to each opponent. - TriggeredAbility triggeredAbility = new EntersBattlefieldTriggeredAbility(new DamagePlayersEffect(2, TargetController.OPPONENT)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - triggeredAbility, - new PermanentsOnTheBattlefieldCondition(filter), - "When {this} enters, if you control another Wizard, {this} deals 2 damage to each opponent." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new DamagePlayersEffect(2, TargetController.OPPONENT)).withInterveningIf(condition)); } private GhituJourneymage(final GhituJourneymage card) { diff --git a/Mage.Sets/src/mage/cards/g/GhostTown.java b/Mage.Sets/src/mage/cards/g/GhostTown.java index 01e430d8539..7a26a8c3868 100644 --- a/Mage.Sets/src/mage/cards/g/GhostTown.java +++ b/Mage.Sets/src/mage/cards/g/GhostTown.java @@ -4,12 +4,10 @@ import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.common.NotMyTurnCondition; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.ReturnToHandSourceEffect; -import mage.abilities.hint.common.NotMyTurnHint; import mage.abilities.mana.ColorlessManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; import java.util.UUID; @@ -25,9 +23,9 @@ public final class GhostTown extends CardImpl { this.addAbility(new ColorlessManaAbility()); // {0}: Return Ghost Town to its owner's hand. Activate this ability only if it's not your turn. - this.addAbility(new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandSourceEffect(true), - new GenericManaCost(0), NotMyTurnCondition.instance) - .addHint(NotMyTurnHint.instance)); + this.addAbility(new ActivateIfConditionActivatedAbility( + new ReturnToHandSourceEffect(true), new GenericManaCost(0), NotMyTurnCondition.instance + )); } private GhostTown(final GhostTown card) { diff --git a/Mage.Sets/src/mage/cards/g/GhosthelmCourier.java b/Mage.Sets/src/mage/cards/g/GhosthelmCourier.java index 444545774e2..07756b42af4 100644 --- a/Mage.Sets/src/mage/cards/g/GhosthelmCourier.java +++ b/Mage.Sets/src/mage/cards/g/GhosthelmCourier.java @@ -20,6 +20,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -50,7 +51,7 @@ public final class GhosthelmCourier extends CardImpl { ability.addEffect(new ConditionalContinuousEffect(new GainAbilityTargetEffect(ShroudAbility.getInstance(), Duration.Custom), SourceTappedCondition.TAPPED,"and has shroud for as long as {this} remains tapped")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GhostlyVisit.java b/Mage.Sets/src/mage/cards/g/GhostlyVisit.java index cfb939434aa..df41330c4d1 100644 --- a/Mage.Sets/src/mage/cards/g/GhostlyVisit.java +++ b/Mage.Sets/src/mage/cards/g/GhostlyVisit.java @@ -6,8 +6,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author LoneFox @@ -19,7 +22,7 @@ public final class GhostlyVisit extends CardImpl { // Destroy target nonblack creature. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); } private GhostlyVisit(final GhostlyVisit card) { diff --git a/Mage.Sets/src/mage/cards/g/GiantOyster.java b/Mage.Sets/src/mage/cards/g/GiantOyster.java index df682ce3765..1311bc09995 100644 --- a/Mage.Sets/src/mage/cards/g/GiantOyster.java +++ b/Mage.Sets/src/mage/cards/g/GiantOyster.java @@ -24,6 +24,7 @@ import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; @@ -55,7 +56,7 @@ public final class GiantOyster extends CardImpl { .setText("For as long as {this} remains tapped, target tapped creature doesn't untap during its controller's untap step"), new TapSourceCost()); ability.addEffect(new GiantOysterCreateDelayedTriggerEffects()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GiantTrapDoorSpider.java b/Mage.Sets/src/mage/cards/g/GiantTrapDoorSpider.java index 5fb28ea8bea..0a608fea718 100644 --- a/Mage.Sets/src/mage/cards/g/GiantTrapDoorSpider.java +++ b/Mage.Sets/src/mage/cards/g/GiantTrapDoorSpider.java @@ -18,6 +18,7 @@ import mage.constants.Zone; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; import mage.filter.common.FilterCreatureAttackingYou; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -43,7 +44,7 @@ public final class GiantTrapDoorSpider extends CardImpl { Ability ability = new SimpleActivatedAbility(new ExileSourceEffect(), new ManaCostsImpl<>("{1}{R}{G}")); ability.addCost(new TapSourceCost()); ability.addEffect(new ExileTargetEffect().setText("and target creature without flying that's attacking you")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GibberingFiend.java b/Mage.Sets/src/mage/cards/g/GibberingFiend.java index 4ff11c3ffdf..0fe87e51653 100644 --- a/Mage.Sets/src/mage/cards/g/GibberingFiend.java +++ b/Mage.Sets/src/mage/cards/g/GibberingFiend.java @@ -1,21 +1,21 @@ package mage.cards.g; -import java.util.UUID; - import mage.MageInt; -import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.DeliriumCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.effects.common.DamagePlayersEffect; import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.TargetController; +import java.util.UUID; + /** * @author fireshoes */ @@ -28,16 +28,15 @@ public final class GibberingFiend extends CardImpl { this.toughness = new MageInt(1); // When Gibbering Fiend enters the battlefield, it deals 1 damage to each opponent. - this.addAbility(new EntersBattlefieldTriggeredAbility(new DamagePlayersEffect(1, TargetController.OPPONENT, "it"), false)); + this.addAbility(new EntersBattlefieldTriggeredAbility(new DamagePlayersEffect( + 1, TargetController.OPPONENT, "it" + ), false)); // Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard, // Gibbering Fiend deals 1 damage to that player. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(TargetController.OPPONENT, new DamageTargetEffect(1), false), - DeliriumCondition.instance, - "Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard, " - + "{this} deals 1 damage to that player.") - .addHint(CardTypesInGraveyardCount.YOU.getHint())); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + TargetController.OPPONENT, new DamageTargetEffect(1, true, "that player"), false + ).withInterveningIf(DeliriumCondition.instance).setAbilityWord(AbilityWord.DELIRIUM).addHint(CardTypesInGraveyardCount.YOU.getHint())); } private GibberingFiend(final GibberingFiend card) { diff --git a/Mage.Sets/src/mage/cards/g/GideonBattleForged.java b/Mage.Sets/src/mage/cards/g/GideonBattleForged.java index dc1422b1aa1..a2adb7e3c1a 100644 --- a/Mage.Sets/src/mage/cards/g/GideonBattleForged.java +++ b/Mage.Sets/src/mage/cards/g/GideonBattleForged.java @@ -18,6 +18,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.TokenImpl; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -46,7 +47,7 @@ public final class GideonBattleForged extends CardImpl { // +2: Up to one target creature an opponent controls attacks Gideon, Battle-Forged during its controller's next turn if able. LoyaltyAbility loyaltyAbility = new LoyaltyAbility(new GideonBattleForgedAttacksIfAbleTargetEffect(Duration.Custom), 2); - loyaltyAbility.addTarget(new TargetCreaturePermanent(0, 1, filter, false)); + loyaltyAbility.addTarget(new TargetPermanent(0, 1, filter)); this.addAbility(loyaltyAbility); // +1: Until your next turn, target creature gains indestructible. Untap that creature. diff --git a/Mage.Sets/src/mage/cards/g/GideonJura.java b/Mage.Sets/src/mage/cards/g/GideonJura.java index f546e9a380b..b679e7c06f0 100644 --- a/Mage.Sets/src/mage/cards/g/GideonJura.java +++ b/Mage.Sets/src/mage/cards/g/GideonJura.java @@ -17,6 +17,7 @@ import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.TokenImpl; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetOpponent; @@ -47,7 +48,7 @@ public final class GideonJura extends CardImpl { // −2: Destroy target tapped creature. LoyaltyAbility ability2 = new LoyaltyAbility(new DestroyTargetEffect(), -2); - ability2.addTarget(new TargetCreaturePermanent(filter)); + ability2.addTarget(new TargetPermanent(filter)); this.addAbility(ability2); // 0: Until end of turn, Gideon Jura becomes a 6/6 Human Soldier creature that's still a planeswalker. Prevent all damage that would be dealt to him this turn. diff --git a/Mage.Sets/src/mage/cards/g/GideonsDefeat.java b/Mage.Sets/src/mage/cards/g/GideonsDefeat.java index e7a8f4e6c83..a930cbc8b52 100644 --- a/Mage.Sets/src/mage/cards/g/GideonsDefeat.java +++ b/Mage.Sets/src/mage/cards/g/GideonsDefeat.java @@ -17,6 +17,7 @@ import mage.filter.predicate.mageobject.ColorPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -36,7 +37,7 @@ public final class GideonsDefeat extends CardImpl { // Exile target white creature that's attacking or blocking. If it was a Gideon planeswalker, you gain 5 life. this.getSpellAbility().addEffect(new GideonsDefeatEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private GideonsDefeat(final GideonsDefeat card) { diff --git a/Mage.Sets/src/mage/cards/g/GiftOfDoom.java b/Mage.Sets/src/mage/cards/g/GiftOfDoom.java index 521ee336c6c..7600c148a41 100644 --- a/Mage.Sets/src/mage/cards/g/GiftOfDoom.java +++ b/Mage.Sets/src/mage/cards/g/GiftOfDoom.java @@ -22,7 +22,6 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPermanent; -import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -102,7 +101,7 @@ class GiftOfDoomEffect extends OneShotEffect { if (player == null || giftOfDoom == null) { return false; } - TargetCreaturePermanent target = new TargetCreaturePermanent(filter); + TargetPermanent target = new TargetPermanent(filter); target.withNotTarget(true); if (player.choose(outcome, target, source, game) && game.getPermanent(target.getFirstTarget()) != null diff --git a/Mage.Sets/src/mage/cards/g/Gigantiform.java b/Mage.Sets/src/mage/cards/g/Gigantiform.java index feb60a03ab0..9cd8967cd05 100644 --- a/Mage.Sets/src/mage/cards/g/Gigantiform.java +++ b/Mage.Sets/src/mage/cards/g/Gigantiform.java @@ -1,40 +1,43 @@ - package mage.cards.g; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.StaticAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; -import mage.abilities.effects.common.continuous.SetBasePowerToughnessSourceEffect; +import mage.abilities.effects.common.continuous.SetBasePowerToughnessAttachedEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; import mage.abilities.keyword.EnchantAbility; import mage.abilities.keyword.KickerAbility; import mage.abilities.keyword.TrampleAbility; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; import mage.filter.FilterCard; import mage.filter.predicate.mageobject.NamePredicate; -import mage.game.Game; -import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author North */ public final class Gigantiform extends CardImpl { + private static final FilterCard filter = new FilterCard("card named Gigantiform"); + + static { + filter.add(new NamePredicate("Gigantiform")); + } + public Gigantiform(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}{G}"); this.subtype.add(SubType.AURA); // Kicker {4} @@ -44,15 +47,21 @@ public final class Gigantiform extends CardImpl { TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); + // Enchanted creature has base power and toughness 8/8 and has trample. - this.addAbility(new GigantiformAbility()); + Ability ability = new SimpleStaticAbility( + new SetBasePowerToughnessAttachedEffect(8, 8, AttachmentType.AURA) + ); + ability.addEffect(new GainAbilityAttachedEffect( + TrampleAbility.getInstance(), AttachmentType.AURA + ).setText("and has trample")); + this.addAbility(ability); + // When Gigantiform enters the battlefield, if it was kicked, you may search your library for a card named Gigantiform, put it onto the battlefield, then shuffle your library. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new GigantiformEffect(), true), - KickedCondition.ONCE, - "When {this} enters, if it was kicked, you may search your library for a card named Gigantiform, put it onto the battlefield, then shuffle.")); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter)), true + ).withInterveningIf(KickedCondition.ONCE)); } private Gigantiform(final Gigantiform card) { @@ -64,65 +73,3 @@ public final class Gigantiform extends CardImpl { return new Gigantiform(this); } } - -class GigantiformAbility extends StaticAbility { - - public GigantiformAbility() { - super(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(TrampleAbility.getInstance(), AttachmentType.AURA)); - Ability ability = new SimpleStaticAbility( - new SetBasePowerToughnessSourceEffect(8, 8, Duration.WhileOnBattlefield) - ); - this.addEffect(new GainAbilityAttachedEffect(ability, AttachmentType.AURA)); - } - - private GigantiformAbility(final GigantiformAbility ability) { - super(ability); - } - - @Override - public GigantiformAbility copy() { - return new GigantiformAbility(this); - } - - @Override - public String getRule() { - return "Enchanted creature has base power and toughness 8/8 and has trample."; - } -} - -class GigantiformEffect extends OneShotEffect { - - private static final FilterCard filter = new FilterCard("card named Gigantiform"); - - static { - filter.add(new NamePredicate("Gigantiform")); - } - - public GigantiformEffect() { - super(Outcome.PutCardInPlay); - } - - private GigantiformEffect(final GigantiformEffect effect) { - super(effect); - } - - @Override - public GigantiformEffect copy() { - return new GigantiformEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - TargetCardInLibrary target = new TargetCardInLibrary(filter); - if (controller != null && controller.searchLibrary(target, source, game)) { - Card card = controller.getLibrary().getCard(target.getFirstTarget(), game); - if (card != null) { - controller.moveCards(card, Zone.BATTLEFIELD, source, game); - } - controller.shuffleLibrary(source, game); - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/g/GildedCerodon.java b/Mage.Sets/src/mage/cards/g/GildedCerodon.java index 40d5fec95c6..e9ca33a3c48 100644 --- a/Mage.Sets/src/mage/cards/g/GildedCerodon.java +++ b/Mage.Sets/src/mage/cards/g/GildedCerodon.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.DesertControlledOrGraveyardCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.combat.CantBlockTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -20,8 +19,6 @@ import java.util.UUID; */ public final class GildedCerodon extends CardImpl { - private static final String rule = "Whenever {this} attacks, if you control a Desert or there is a Desert card in your graveyard, target creature can't block this turn."; - public GildedCerodon(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}"); @@ -31,13 +28,10 @@ public final class GildedCerodon extends CardImpl { this.toughness = new MageInt(4); // Whenever Gilded Cerodon attacks, if you control a Desert or there is a Desert card in your graveyard, target creature can't block this turn. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new CantBlockTargetEffect(Duration.EndOfTurn), false), - DesertControlledOrGraveyardCondition.instance, rule - ); + Ability ability = new AttacksTriggeredAbility(new CantBlockTargetEffect(Duration.EndOfTurn)) + .withInterveningIf(DesertControlledOrGraveyardCondition.instance); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability.addHint(DesertControlledOrGraveyardCondition.getHint())); - } private GildedCerodon(final GildedCerodon card) { diff --git a/Mage.Sets/src/mage/cards/g/GildedDrake.java b/Mage.Sets/src/mage/cards/g/GildedDrake.java index 20c836ec93d..07a9862b066 100644 --- a/Mage.Sets/src/mage/cards/g/GildedDrake.java +++ b/Mage.Sets/src/mage/cards/g/GildedDrake.java @@ -1,7 +1,5 @@ - package mage.cards.g; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -12,17 +10,17 @@ 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.filter.StaticFilters; +import mage.constants.SubType; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.common.TargetCreaturePermanent; +import mage.target.common.TargetOpponentsCreaturePermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class GildedDrake extends CardImpl { @@ -36,11 +34,12 @@ public final class GildedDrake extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); + // When Gilded Drake enters the battlefield, exchange control of Gilded Drake and up to one target creature an opponent controls. If you don't make an exchange, sacrifice Gilded Drake. // This ability can't be countered except by spells and abilities. Ability ability = new EntersBattlefieldTriggeredAbility(new GildedDrakeEffect()); ability.setCanFizzle(false); - ability.addTarget(new TargetCreaturePermanent(0, 1, StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE, false)); + ability.addTarget(new TargetOpponentsCreaturePermanent(0, 1)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GilgameshMasterAtArms.java b/Mage.Sets/src/mage/cards/g/GilgameshMasterAtArms.java index 3deb2f77af6..f4ee4c91e24 100644 --- a/Mage.Sets/src/mage/cards/g/GilgameshMasterAtArms.java +++ b/Mage.Sets/src/mage/cards/g/GilgameshMasterAtArms.java @@ -1,7 +1,6 @@ package mage.cards.g; import mage.MageInt; -import mage.MageItem; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility; import mage.abilities.common.delayed.ReflexiveTriggeredAbility; @@ -14,8 +13,7 @@ import mage.constants.*; import mage.filter.FilterCard; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledPermanent; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.permanent.PermanentIdPredicate; +import mage.filter.predicate.permanent.PermanentReferenceInCollectionPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -165,13 +163,7 @@ class GilgameshMasterAtArmsAttachEffect extends OneShotEffect { break; } FilterPermanent filterPermanent = new FilterPermanent("Equipment"); - Predicates.or( - permanents - .stream() - .map(MageItem::getId) - .map(PermanentIdPredicate::new) - .collect(Collectors.toSet()) - ); + filter.add(new PermanentReferenceInCollectionPredicate(permanents, game)); return Optional .of(new TargetPermanent(0, 1, filterPermanent, true)) .map(t -> { diff --git a/Mage.Sets/src/mage/cards/g/GiltBladeProwler.java b/Mage.Sets/src/mage/cards/g/GiltBladeProwler.java index d6e26165c25..a50ddcaf47a 100644 --- a/Mage.Sets/src/mage/cards/g/GiltBladeProwler.java +++ b/Mage.Sets/src/mage/cards/g/GiltBladeProwler.java @@ -13,7 +13,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.watchers.common.DiscardedCardWatcher; import java.util.UUID; @@ -33,8 +32,8 @@ public final class GiltBladeProwler extends CardImpl { // {1}, {T}, Pay 1 life: Draw a card. Activate only if you've discarded a card this turn. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), - new GenericManaCost(1), ControllerDiscardedThisTurnCondition.instance + new DrawCardSourceControllerEffect(1), new GenericManaCost(1), + ControllerDiscardedThisTurnCondition.instance ); ability.addCost(new TapSourceCost()); ability.addCost(new PayLifeCost(1)); diff --git a/Mage.Sets/src/mage/cards/g/GiltLeafWinnower.java b/Mage.Sets/src/mage/cards/g/GiltLeafWinnower.java index 60d3c9a4a1e..470bc8c4f3c 100644 --- a/Mage.Sets/src/mage/cards/g/GiltLeafWinnower.java +++ b/Mage.Sets/src/mage/cards/g/GiltLeafWinnower.java @@ -16,6 +16,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicate; import mage.filter.predicate.Predicates; import mage.game.Game; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -43,7 +44,7 @@ public final class GiltLeafWinnower extends CardImpl { // When Gilt-Leaf Winnower enters the battlefield, you may destroy target non-Elf creature whose power and toughness aren't equal. Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), true); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GimlisRecklessMight.java b/Mage.Sets/src/mage/cards/g/GimlisRecklessMight.java index 8ad1f100229..824bf4b2c6e 100644 --- a/Mage.Sets/src/mage/cards/g/GimlisRecklessMight.java +++ b/Mage.Sets/src/mage/cards/g/GimlisRecklessMight.java @@ -1,30 +1,31 @@ package mage.cards.g; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.AttacksWithCreaturesTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.FormidableCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.FightTargetsEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.AbilityWord; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.TargetController; +import mage.filter.FilterPermanent; import mage.filter.StaticFilters; import mage.filter.common.FilterAttackingCreature; -import mage.filter.common.FilterCreaturePermanent; import mage.target.TargetPermanent; import java.util.UUID; /** - * * @author notgreat */ public final class GimlisRecklessMight extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterAttackingCreature("attacking creature you control"); + private static final FilterPermanent filter = new FilterAttackingCreature("attacking creature you control"); static { filter.add(TargetController.YOU.getControllerPredicate()); @@ -35,14 +36,15 @@ public final class GimlisRecklessMight extends CardImpl { // Creatures you control have haste. this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect( - HasteAbility.getInstance(), Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURES))); + HasteAbility.getInstance(), Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURES + ))); + // Formidable -- Whenever you attack, if creatures you control have total power 8 or greater, target attacking creature you control fights up to one target creature you don't control. - TriggeredAbility ability = new AttacksWithCreaturesTriggeredAbility(new FightTargetsEffect(),1); + Ability ability = new AttacksWithCreaturesTriggeredAbility(new FightTargetsEffect(), 1) + .withInterveningIf(FormidableCondition.instance); ability.addTarget(new TargetPermanent(filter)); ability.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); - ability.setAbilityWord(AbilityWord.FORMIDABLE); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, FormidableCondition.instance, - "Formidable — Whenever you attack, if creatures you control have total power 8 or greater, target attacking creature you control fights up to one target creature you don't control.")); + this.addAbility(ability.setAbilityWord(AbilityWord.FORMIDABLE)); } private GimlisRecklessMight(final GimlisRecklessMight card) { diff --git a/Mage.Sets/src/mage/cards/g/GixianSkullflayer.java b/Mage.Sets/src/mage/cards/g/GixianSkullflayer.java index 17f6c723062..b8d4ab3d6de 100644 --- a/Mage.Sets/src/mage/cards/g/GixianSkullflayer.java +++ b/Mage.Sets/src/mage/cards/g/GixianSkullflayer.java @@ -1,26 +1,25 @@ package mage.cards.g; -import java.util.UUID; import mage.MageInt; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInControllerGraveyardCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; -import mage.constants.SubType; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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 java.util.UUID; + /** - * * @author weirddan455 */ public final class GixianSkullflayer extends CardImpl { - private static final CardsInControllerGraveyardCondition condition - = new CardsInControllerGraveyardCondition(3, StaticFilters.FILTER_CARD_CREATURES); + private static final Condition condition = new CardsInControllerGraveyardCondition(3, StaticFilters.FILTER_CARD_CREATURES); public GixianSkullflayer(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); @@ -32,11 +31,7 @@ public final class GixianSkullflayer extends CardImpl { this.toughness = new MageInt(3); // At the beginning of your upkeep, if there are three or more creature cards in your graveyard, put a +1/+1 counter on Gixian Skullflayer. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance())), - condition, - "At the beginning of your upkeep, if there are three or more creature cards in your graveyard, put a +1/+1 counter on {this}." - )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance())).withInterveningIf(condition)); } private GixianSkullflayer(final GixianSkullflayer card) { diff --git a/Mage.Sets/src/mage/cards/g/GladeWatcher.java b/Mage.Sets/src/mage/cards/g/GladeWatcher.java index 07d0f2b4b4c..22da2a0cde7 100644 --- a/Mage.Sets/src/mage/cards/g/GladeWatcher.java +++ b/Mage.Sets/src/mage/cards/g/GladeWatcher.java @@ -1,9 +1,6 @@ - package mage.cards.g; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.common.FormidableCondition; import mage.abilities.costs.mana.ManaCostsImpl; @@ -13,32 +10,30 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AbilityWord; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class GladeWatcher extends CardImpl { public GladeWatcher(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); this.subtype.add(SubType.ELEMENTAL); this.power = new MageInt(3); this.toughness = new MageInt(3); // Defender this.addAbility(DefenderAbility.getInstance()); + // Formidable — {G}: Glade Watcher can attack this turn as though it didn't have defender. Activate this ability only if creatures you control have total power 8 or greater. - Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, + this.addAbility(new ActivateIfConditionActivatedAbility( new CanAttackAsThoughItDidntHaveDefenderSourceEffect(Duration.EndOfTurn), - new ManaCostsImpl<>("{G}"), - FormidableCondition.instance); - ability.setAbilityWord(AbilityWord.FORMIDABLE); - this.addAbility(ability); + new ManaCostsImpl<>("{G}"), FormidableCondition.instance + ).setAbilityWord(AbilityWord.FORMIDABLE)); } private GladeWatcher(final GladeWatcher card) { diff --git a/Mage.Sets/src/mage/cards/g/GladewalkerRitualist.java b/Mage.Sets/src/mage/cards/g/GladewalkerRitualist.java index 38738ed0554..12b0c4e6424 100644 --- a/Mage.Sets/src/mage/cards/g/GladewalkerRitualist.java +++ b/Mage.Sets/src/mage/cards/g/GladewalkerRitualist.java @@ -1,7 +1,7 @@ package mage.cards.g; import mage.MageInt; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.keyword.ChangelingAbility; import mage.cards.CardImpl; @@ -9,9 +9,9 @@ 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.NamePredicate; +import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.predicate.mageobject.NamePredicate; import java.util.UUID; @@ -21,7 +21,7 @@ import java.util.UUID; public final class GladewalkerRitualist extends CardImpl { private static final FilterPermanent filter - = new FilterCreaturePermanent("another creature named Gladewalker Ritualist"); + = new FilterControlledCreaturePermanent("another creature you control named Gladewalker Ritualist"); static { filter.add(AnotherPredicate.instance); @@ -39,9 +39,7 @@ public final class GladewalkerRitualist extends CardImpl { this.addAbility(new ChangelingAbility()); // Whenever another creature named Gladewalker Ritualist you control enters, draw a card. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility( - new DrawCardSourceControllerEffect(1), filter - )); + this.addAbility(new EntersBattlefieldAllTriggeredAbility(new DrawCardSourceControllerEffect(1), filter)); } private GladewalkerRitualist(final GladewalkerRitualist card) { diff --git a/Mage.Sets/src/mage/cards/g/GlareOfSubdual.java b/Mage.Sets/src/mage/cards/g/GlareOfSubdual.java index ccecee5f520..64e746b7b43 100644 --- a/Mage.Sets/src/mage/cards/g/GlareOfSubdual.java +++ b/Mage.Sets/src/mage/cards/g/GlareOfSubdual.java @@ -7,33 +7,25 @@ import mage.abilities.effects.common.TapTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; import mage.filter.StaticFilters; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.permanent.TappedPredicate; import mage.target.TargetPermanent; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; import java.util.UUID; /** - * * @author Loki */ public final class GlareOfSubdual extends CardImpl { - private static final FilterControlledCreaturePermanent filterCost = new FilterControlledCreaturePermanent("untapped creature you control"); - - static { - filterCost.add(TappedPredicate.UNTAPPED); - } - public GlareOfSubdual(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{G}{W}"); - + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}{W}"); // Tap an untapped creature you control: Tap target artifact or creature. - Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filterCost, true))); + Ability ability = new SimpleActivatedAbility( + new TapTargetEffect(), + new TapTargetCost(new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURE)) + ); ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GlaringAegis.java b/Mage.Sets/src/mage/cards/g/GlaringAegis.java index 8fb0ab81b99..801e5d89384 100644 --- a/Mage.Sets/src/mage/cards/g/GlaringAegis.java +++ b/Mage.Sets/src/mage/cards/g/GlaringAegis.java @@ -16,6 +16,8 @@ import mage.filter.StaticFilters; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author fireshoes @@ -35,7 +37,7 @@ public final class GlaringAegis extends CardImpl { // When Glaring Aegis enters the battlefield, tap target creature an opponent controls. Ability ability2 = new EntersBattlefieldTriggeredAbility(new TapTargetEffect()); - ability2.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability2.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability2); // Enchanted creature gets +1/+3. diff --git a/Mage.Sets/src/mage/cards/g/GlimmerdustNap.java b/Mage.Sets/src/mage/cards/g/GlimmerdustNap.java index 6291db3c059..d10c441d5a9 100644 --- a/Mage.Sets/src/mage/cards/g/GlimmerdustNap.java +++ b/Mage.Sets/src/mage/cards/g/GlimmerdustNap.java @@ -35,7 +35,7 @@ public final class GlimmerdustNap extends CardImpl { // Enchant tapped creature - TargetPermanent auraTarget = new TargetCreaturePermanent(filter); + TargetPermanent auraTarget = new TargetPermanent(filter); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); this.addAbility(new EnchantAbility(auraTarget)); diff --git a/Mage.Sets/src/mage/cards/g/Glimmervoid.java b/Mage.Sets/src/mage/cards/g/Glimmervoid.java index 496eb6510e7..6d7d609e923 100644 --- a/Mage.Sets/src/mage/cards/g/Glimmervoid.java +++ b/Mage.Sets/src/mage/cards/g/Glimmervoid.java @@ -1,33 +1,36 @@ - package mage.cards.g; -import java.util.UUID; -import mage.abilities.TriggeredAbility; -import mage.abilities.common.OnEventTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.mana.AnyColorManaAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; +import mage.constants.TargetController; import mage.filter.common.FilterControlledArtifactPermanent; -import mage.game.events.GameEvent; + +import java.util.UUID; /** - * * @author jonubuu */ public final class Glimmervoid extends CardImpl { + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledArtifactPermanent("you control no artifacts"), ComparisonType.EQUAL_TO, 0 + ); + public Glimmervoid(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.LAND},""); + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); // At the beginning of the end step, if you control no artifacts, sacrifice Glimmervoid. - TriggeredAbility triggered = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new SacrificeSourceEffect()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(triggered, new PermanentsOnTheBattlefieldCondition(new FilterControlledArtifactPermanent(), ComparisonType.FEWER_THAN, 1), - "At the beginning of the end step, if you control no artifacts, sacrifice {this}.")); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.NEXT, new SacrificeSourceEffect(), false, condition + )); + // {tap}: Add one mana of any color. this.addAbility(new AnyColorManaAbility()); } diff --git a/Mage.Sets/src/mage/cards/g/GlintHornBuccaneer.java b/Mage.Sets/src/mage/cards/g/GlintHornBuccaneer.java index 871a50572c7..bc6b206fb60 100644 --- a/Mage.Sets/src/mage/cards/g/GlintHornBuccaneer.java +++ b/Mage.Sets/src/mage/cards/g/GlintHornBuccaneer.java @@ -6,7 +6,7 @@ import mage.abilities.TriggeredAbilityImpl; import mage.abilities.condition.common.SourceAttackingCondition; import mage.abilities.costs.common.DiscardCardCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DamagePlayersEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.keyword.HasteAbility; @@ -41,9 +41,8 @@ public final class GlintHornBuccaneer extends CardImpl { this.addAbility(new GlintHornBuccaneerTriggeredAbility()); // {1}{R}, Discard a card: Draw a card. Activate this ability only if Glint-Horn Buccaneer is attacking. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), - new ManaCostsImpl<>("{1}{R}"), SourceAttackingCondition.instance + Ability ability = new ActivateIfConditionActivatedAbility( + new DrawCardSourceControllerEffect(1), new ManaCostsImpl<>("{1}{R}"), SourceAttackingCondition.instance ); ability.addCost(new DiscardCardCost()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/g/GloriousEnforcer.java b/Mage.Sets/src/mage/cards/g/GloriousEnforcer.java index 9073f354890..815cd12948d 100644 --- a/Mage.Sets/src/mage/cards/g/GloriousEnforcer.java +++ b/Mage.Sets/src/mage/cards/g/GloriousEnforcer.java @@ -1,26 +1,25 @@ package mage.cards.g; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.DoubleStrikeAbility; -import mage.constants.Duration; -import mage.constants.SubType; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.LifelinkAbility; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; 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.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author weirddan455 */ public final class GloriousEnforcer extends CardImpl { @@ -39,14 +38,12 @@ public final class GloriousEnforcer extends CardImpl { this.addAbility(LifelinkAbility.getInstance()); // At the beginning of each combat, if you have more life than an opponent, Glorious Enforcer gains double strike until end of turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility( - TargetController.ANY, new GainAbilitySourceEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn), - false - ), - GloriousEnforcerCondition.instance, - "At the beginning of each combat, if you have more life than an opponent, {this} gains double strike until end of turn." - )); + this.addAbility(new BeginningOfCombatTriggeredAbility( + TargetController.ANY, + new GainAbilitySourceEffect( + DoubleStrikeAbility.getInstance(), Duration.EndOfTurn + ), false + ).withInterveningIf(GloriousEnforcerCondition.instance)); } private GloriousEnforcer(final GloriousEnforcer card) { @@ -66,14 +63,20 @@ enum GloriousEnforcerCondition implements Condition { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - for (UUID opponentId : game.getOpponents(source.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null && controller.getLife() > opponent.getLife()) { - return true; - } + if (controller == null) { + return false; + } + for (UUID opponentId : game.getOpponents(source.getControllerId())) { + Player opponent = game.getPlayer(opponentId); + if (opponent != null && controller.getLife() > opponent.getLife()) { + return true; } } return false; } + + @Override + public String toString() { + return "you have more life than an opponent"; + } } diff --git a/Mage.Sets/src/mage/cards/g/Glorybringer.java b/Mage.Sets/src/mage/cards/g/Glorybringer.java index a029e6847b5..898840dd46d 100644 --- a/Mage.Sets/src/mage/cards/g/Glorybringer.java +++ b/Mage.Sets/src/mage/cards/g/Glorybringer.java @@ -16,6 +16,7 @@ import mage.constants.SubType; import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -48,7 +49,7 @@ public final class Glorybringer extends CardImpl { Effect effect = new DamageTargetEffect(4); effect.setText("it deals 4 damage to target non-Dragon creature an opponent controls"); BecomesExertSourceTriggeredAbility ability = new BecomesExertSourceTriggeredAbility(effect); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(new ExertAbility(ability)); } diff --git a/Mage.Sets/src/mage/cards/g/GlyphOfDelusion.java b/Mage.Sets/src/mage/cards/g/GlyphOfDelusion.java index 431d0f82bec..4b6b8c25125 100644 --- a/Mage.Sets/src/mage/cards/g/GlyphOfDelusion.java +++ b/Mage.Sets/src/mage/cards/g/GlyphOfDelusion.java @@ -20,7 +20,6 @@ import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; -import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; import mage.watchers.common.BlockedAttackerWatcher; @@ -43,7 +42,7 @@ public final class GlyphOfDelusion extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}"); // Put X glyph counters on target creature that target Wall blocked this turn, where X is the power of that blocked creature. The creature gains “This creature doesn’t untap during your untap step if it has a glyph counter on it” and “At the beginning of your upkeep, remove a glyph counter from this creature.” - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addTarget(new GlyphOfDelusionSecondTarget()); this.getSpellAbility().addEffect(new GlyphOfDelusionEffect()); } @@ -82,7 +81,7 @@ class GlyphOfDelusionSecondTarget extends TargetPermanent { if (targetSource != null) { for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, sourceControllerId, source, game)) { if (!targets.containsKey(creature.getId()) && creature.canBeTargetedBy(targetSource, sourceControllerId, source, game)) { - if (watcher.creatureHasBlockedAttacker(new MageObjectReference(creature, game), new MageObjectReference(firstTarget, game), game)) { + if (watcher.creatureHasBlockedAttacker(new MageObjectReference(creature, game), new MageObjectReference(firstTarget, game))) { possibleTargets.add(creature.getId()); } } diff --git a/Mage.Sets/src/mage/cards/g/GlyphOfDestruction.java b/Mage.Sets/src/mage/cards/g/GlyphOfDestruction.java index ddfb5909c3b..ccb4409e045 100644 --- a/Mage.Sets/src/mage/cards/g/GlyphOfDestruction.java +++ b/Mage.Sets/src/mage/cards/g/GlyphOfDestruction.java @@ -1,26 +1,26 @@ - package mage.cards.g; -import java.util.UUID; import mage.abilities.effects.common.DestroyTargetAtBeginningOfNextEndStepEffect; import mage.abilities.effects.common.PreventDamageToTargetEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; 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.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.permanent.BlockingPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author L_J */ public final class GlyphOfDestruction extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("blocking Wall you control"); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("blocking Wall you control"); static { filter.add(SubType.WALL.getPredicate()); @@ -28,13 +28,13 @@ public final class GlyphOfDestruction extends CardImpl { } public GlyphOfDestruction(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{R}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}"); // Target blocking Wall you control gets +10/+0 until end of combat. Prevent all damage that would be dealt to it this turn. Destroy it at the beginning of the next end step. this.getSpellAbility().addEffect(new BoostTargetEffect(10, 0, Duration.EndOfCombat)); this.getSpellAbility().addEffect(new PreventDamageToTargetEffect(Duration.EndOfTurn, Integer.MAX_VALUE).setText("Prevent all damage that would be dealt to it this turn")); this.getSpellAbility().addEffect(new DestroyTargetAtBeginningOfNextEndStepEffect().setText("Destroy it at the beginning of the next end step")); - this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private GlyphOfDestruction(final GlyphOfDestruction card) { diff --git a/Mage.Sets/src/mage/cards/g/GlyphOfDoom.java b/Mage.Sets/src/mage/cards/g/GlyphOfDoom.java index 8accdeb1223..101163093f7 100644 --- a/Mage.Sets/src/mage/cards/g/GlyphOfDoom.java +++ b/Mage.Sets/src/mage/cards/g/GlyphOfDoom.java @@ -19,7 +19,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import mage.watchers.common.BlockedAttackerWatcher; /** @@ -38,7 +38,7 @@ public final class GlyphOfDoom extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}"); // Choose target Wall creature. At this turn's next end of combat, destroy all creatures that were blocked by that creature this turn. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new InfoEffect("Choose target Wall creature")); this.getSpellAbility().addEffect(new GlyphOfDoomCreateDelayedTriggeredAbilityEffect()); } @@ -109,7 +109,7 @@ class GlyphOfDoomEffect extends OneShotEffect { List toDestroy = new ArrayList<>(); for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source, game)) { if (!creature.getId().equals(targetCreature.getSourceId())) { - if (watcher.creatureHasBlockedAttacker(new MageObjectReference(creature, game), targetCreature, game)) { + if (watcher.creatureHasBlockedAttacker(new MageObjectReference(creature, game), targetCreature)) { toDestroy.add(creature); } } diff --git a/Mage.Sets/src/mage/cards/g/GlyphOfLife.java b/Mage.Sets/src/mage/cards/g/GlyphOfLife.java index d41a3c57d93..e947e944ca1 100644 --- a/Mage.Sets/src/mage/cards/g/GlyphOfLife.java +++ b/Mage.Sets/src/mage/cards/g/GlyphOfLife.java @@ -19,6 +19,7 @@ import mage.game.events.DamagedEvent; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -37,7 +38,7 @@ public final class GlyphOfLife extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{W}"); // Choose target Wall creature. Whenever that creature is dealt damage by an attacking creature this turn, you gain that much life. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new InfoEffect("Choose target Wall creature")); this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new GlyphOfLifeTriggeredAbility())); } diff --git a/Mage.Sets/src/mage/cards/g/GlyphOfReincarnation.java b/Mage.Sets/src/mage/cards/g/GlyphOfReincarnation.java index 2d4fafefeea..640b7749364 100644 --- a/Mage.Sets/src/mage/cards/g/GlyphOfReincarnation.java +++ b/Mage.Sets/src/mage/cards/g/GlyphOfReincarnation.java @@ -20,8 +20,8 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCardInGraveyard; -import mage.target.common.TargetCreaturePermanent; import mage.watchers.common.BlockedAttackerWatcher; import java.util.HashMap; @@ -46,7 +46,7 @@ public final class GlyphOfReincarnation extends CardImpl { this.addAbility(new CastOnlyDuringPhaseStepSourceAbility(null, null, AfterCombatCondition.instance, "Cast this spell only after combat")); // Destroy all creatures that were blocked by target Wall this turn. They can’t be regenerated. For each creature that died this way, put a creature card from the graveyard of the player who controlled that creature the last time it became blocked by that Wall onto the battlefield under its owner’s control. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new GlyphOfReincarnationEffect()); } @@ -86,7 +86,7 @@ class GlyphOfReincarnationEffect extends OneShotEffect { Map destroyed = new HashMap<>(); for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source, game)) { if (!creature.getId().equals(targetWall.getId())) { - if (watcher.creatureHasBlockedAttacker(new MageObjectReference(creature, game), new MageObjectReference(targetWall, game), game)) { + if (watcher.creatureHasBlockedAttacker(new MageObjectReference(creature, game), new MageObjectReference(targetWall, game))) { if (creature.destroy(source, game, true) && game.getState().getZone(creature.getId()) == Zone.GRAVEYARD) { // If a commander is replaced to command zone, the creature does not die Player permController = game.getPlayer(creature.getControllerId()); diff --git a/Mage.Sets/src/mage/cards/g/GnawingVermin.java b/Mage.Sets/src/mage/cards/g/GnawingVermin.java index 265cadccae4..ed9a70f7870 100644 --- a/Mage.Sets/src/mage/cards/g/GnawingVermin.java +++ b/Mage.Sets/src/mage/cards/g/GnawingVermin.java @@ -12,9 +12,12 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.TargetPlayer; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * * @author weirddan455 @@ -35,7 +38,7 @@ public final class GnawingVermin extends CardImpl { // When Gnawing Vermin dies, target creature you don't control gets -1/-1 until end of turn. ability = new DiesSourceTriggeredAbility(new BoostTargetEffect(-1, -1)); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + ability.addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GoForBlood.java b/Mage.Sets/src/mage/cards/g/GoForBlood.java index 9829274798a..714bff806f4 100644 --- a/Mage.Sets/src/mage/cards/g/GoForBlood.java +++ b/Mage.Sets/src/mage/cards/g/GoForBlood.java @@ -7,11 +7,14 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author TheElk801 */ @@ -23,7 +26,7 @@ public final class GoForBlood extends CardImpl { // Target creature you control fights target creature you don't control. this.getSpellAbility().addEffect(new FightTargetsEffect()); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); // Cycling {1} this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{1}"))); diff --git a/Mage.Sets/src/mage/cards/g/GoForTheThroat.java b/Mage.Sets/src/mage/cards/g/GoForTheThroat.java index 1f145b3380d..f3ff694c212 100644 --- a/Mage.Sets/src/mage/cards/g/GoForTheThroat.java +++ b/Mage.Sets/src/mage/cards/g/GoForTheThroat.java @@ -6,6 +6,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -26,7 +27,7 @@ public final class GoForTheThroat extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{B}"); // Destroy target nonartifact creature. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); } diff --git a/Mage.Sets/src/mage/cards/g/GoblinBirdGrabber.java b/Mage.Sets/src/mage/cards/g/GoblinBirdGrabber.java index d63bcf6759c..53835aaa838 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinBirdGrabber.java +++ b/Mage.Sets/src/mage/cards/g/GoblinBirdGrabber.java @@ -4,7 +4,7 @@ import mage.MageInt; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -12,7 +12,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; @@ -41,9 +40,10 @@ public final class GoblinBirdGrabber extends CardImpl { this.toughness = new MageInt(1); // {R}: Goblin Bird-Grabber gains flying until end of turn. Activate this ability only if you control a creature with flying. - this.addAbility(new ConditionalActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect( - FlyingAbility.getInstance(), Duration.EndOfTurn - ), new ManaCostsImpl<>("{R}"), condition)); + this.addAbility(new ActivateIfConditionActivatedAbility( + new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), + new ManaCostsImpl<>("{R}"), condition + )); } private GoblinBirdGrabber(final GoblinBirdGrabber card) { diff --git a/Mage.Sets/src/mage/cards/g/GoblinBurrows.java b/Mage.Sets/src/mage/cards/g/GoblinBurrows.java index 2899d5e9ab4..c5c627e33b7 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinBurrows.java +++ b/Mage.Sets/src/mage/cards/g/GoblinBurrows.java @@ -15,6 +15,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -37,7 +38,7 @@ public final class GoblinBurrows extends CardImpl { // {1}{R}, {tap}: Target Goblin creature gets +2/+0 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(2,0, Duration.EndOfTurn), new ManaCostsImpl<>("{1}{R}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GoblinBushwhacker.java b/Mage.Sets/src/mage/cards/g/GoblinBushwhacker.java index aee5bf27ee4..f200e9172b6 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinBushwhacker.java +++ b/Mage.Sets/src/mage/cards/g/GoblinBushwhacker.java @@ -1,11 +1,9 @@ - package mage.cards.g; -import java.util.UUID; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.keyword.HasteAbility; @@ -13,12 +11,13 @@ import mage.abilities.keyword.KickerAbility; 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.filter.StaticFilters; +import java.util.UUID; + /** - * * @author North */ public final class GoblinBushwhacker extends CardImpl { @@ -35,19 +34,14 @@ public final class GoblinBushwhacker extends CardImpl { this.addAbility(new KickerAbility("{R}")); // When this creature enters, if it was kicked, creatures you control get +1/+0 and gain haste until end of turn. - EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new BoostControlledEffect(1, 0, Duration.EndOfTurn), false); + Ability ability = new EntersBattlefieldTriggeredAbility( + new BoostControlledEffect(1, 0, Duration.EndOfTurn) + .setText("creatures you control get +1/+0")).withInterveningIf(KickedCondition.ONCE); ability.addEffect(new GainAbilityControlledEffect( - HasteAbility.getInstance(), - Duration.EndOfTurn, + HasteAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURES - )); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - ability, - KickedCondition.ONCE, - "When this creature enters, " - + "if it was kicked, " - + "creatures you control get +1/+0 and gain haste until end of turn." - )); + ).setText("and gain haste until end of turn")); + this.addAbility(ability); } private GoblinBushwhacker(final GoblinBushwhacker card) { diff --git a/Mage.Sets/src/mage/cards/g/GoblinFirestarter.java b/Mage.Sets/src/mage/cards/g/GoblinFirestarter.java index 92a7ac76a7e..b3b70ff4d1b 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinFirestarter.java +++ b/Mage.Sets/src/mage/cards/g/GoblinFirestarter.java @@ -1,7 +1,5 @@ - package mage.cards.g; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; @@ -12,24 +10,26 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** - * * @author fireshoes */ public final class GoblinFirestarter extends CardImpl { public GoblinFirestarter(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}"); this.subtype.add(SubType.GOBLIN); this.power = new MageInt(1); this.toughness = new MageInt(1); // Sacrifice Goblin Firestarter: Goblin Firestarter deals 1 damage to any target. Activate this ability only during your turn, before attackers are declared. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new DamageTargetEffect(1,"it"), new SacrificeSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new DamageTargetEffect(1, "it"), + new SacrificeSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance + ); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GoblinGloryChaser.java b/Mage.Sets/src/mage/cards/g/GoblinGloryChaser.java index 0f965af1b8d..8444540ca98 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinGloryChaser.java +++ b/Mage.Sets/src/mage/cards/g/GoblinGloryChaser.java @@ -1,31 +1,27 @@ - package mage.cards.g; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.RenownedSourceCondition; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.MenaceAbility; import mage.abilities.keyword.RenownAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; + +import java.util.UUID; /** - * * @author fireshoes */ public final class GoblinGloryChaser extends CardImpl { public GoblinGloryChaser(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}"); this.subtype.add(SubType.GOBLIN); this.subtype.add(SubType.WARRIOR); this.power = new MageInt(1); @@ -35,13 +31,11 @@ public final class GoblinGloryChaser extends CardImpl { this.addAbility(new RenownAbility(1)); // As long as Goblin Glory Chaser is renowned, it has menace. - Effect effect = new ConditionalContinuousEffect( + this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect( new GainAbilitySourceEffect(new MenaceAbility(), Duration.WhileOnBattlefield), - RenownedSourceCondition.instance, - "As long as {this} is renowned, it has menace. " + - "(It can't be blocked except by two or more creatures.)"); - Ability ability = new SimpleStaticAbility(effect); - this.addAbility(ability); + RenownedSourceCondition.THIS, "as long as {this} is renowned, " + + "it has menace. (It can't be blocked except by two or more creatures.)" + ))); } private GoblinGloryChaser(final GoblinGloryChaser card) { diff --git a/Mage.Sets/src/mage/cards/g/GoblinRacketeer.java b/Mage.Sets/src/mage/cards/g/GoblinRacketeer.java index a02c72ddb6f..7b0198c6748 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinRacketeer.java +++ b/Mage.Sets/src/mage/cards/g/GoblinRacketeer.java @@ -10,6 +10,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.DefendingPlayerControlsSourceAttackingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -35,7 +36,7 @@ public final class GoblinRacketeer extends CardImpl { // Whenever Goblin Racketeer attacks, you may goad target creature defending player controls. Ability ability = new AttacksTriggeredAbility(new GoadTargetEffect(), true); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GoblinRuinblaster.java b/Mage.Sets/src/mage/cards/g/GoblinRuinblaster.java index ef91213e832..b1d434bc76d 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinRuinblaster.java +++ b/Mage.Sets/src/mage/cards/g/GoblinRuinblaster.java @@ -2,11 +2,10 @@ package mage.cards.g; -import java.util.UUID; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.KickerAbility; @@ -16,14 +15,15 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.target.common.TargetNonBasicLandPermanent; +import java.util.UUID; + /** - * * @author BetaSteward_at_googlemail.com */ public final class GoblinRuinblaster extends CardImpl { public GoblinRuinblaster(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); this.subtype.add(SubType.GOBLIN); this.subtype.add(SubType.SHAMAN); @@ -33,14 +33,13 @@ public final class GoblinRuinblaster extends CardImpl { // Kicker {R} (You may pay an additional {R} as you cast this spell.) this.addAbility(new KickerAbility("{R}")); - // Haste this.addAbility(HasteAbility.getInstance()); // When Goblin Ruinblaster enters the battlefield, if it was kicked, destroy target nonbasic land. - EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), false); + Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()).withInterveningIf(KickedCondition.ONCE); ability.addTarget(new TargetNonBasicLandPermanent()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.ONCE, "When {this} enters, if it was kicked, destroy target nonbasic land.")); + this.addAbility(ability); } private GoblinRuinblaster(final GoblinRuinblaster card) { diff --git a/Mage.Sets/src/mage/cards/g/GoblinSkycutter.java b/Mage.Sets/src/mage/cards/g/GoblinSkycutter.java index fa99a35d84e..4cfbe13ee95 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinSkycutter.java +++ b/Mage.Sets/src/mage/cards/g/GoblinSkycutter.java @@ -17,6 +17,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -42,7 +43,7 @@ public final class GoblinSkycutter extends CardImpl { // Sacrifice Goblin Skycutter: Goblin Skycutter deals 2 damage to target creature with flying. That creature loses flying until end of turn. Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(2, "it"), new SacrificeSourceCost()); ability.addEffect(new LoseAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn).setText("that creature loses flying until end of turn")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GoblinTaskmaster.java b/Mage.Sets/src/mage/cards/g/GoblinTaskmaster.java index 51af39c4703..dee31fb7217 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinTaskmaster.java +++ b/Mage.Sets/src/mage/cards/g/GoblinTaskmaster.java @@ -15,6 +15,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -37,7 +38,7 @@ public final class GoblinTaskmaster extends CardImpl { // {1}{R}: Target Goblin creature gets +1/+0 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl<>("{1}{R}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // Morph {R} diff --git a/Mage.Sets/src/mage/cards/g/GoblinTunneler.java b/Mage.Sets/src/mage/cards/g/GoblinTunneler.java index 794fcf94f45..acbd8568247 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinTunneler.java +++ b/Mage.Sets/src/mage/cards/g/GoblinTunneler.java @@ -16,6 +16,7 @@ import mage.constants.ComparisonType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class GoblinTunneler extends CardImpl { // {tap}: Target creature with power 2 or less can't be blocked this turn. Ability ability = new SimpleActivatedAbility(new CantBeBlockedTargetEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GoblinVandal.java b/Mage.Sets/src/mage/cards/g/GoblinVandal.java index a0e7da6ecd1..c189a74c840 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinVandal.java +++ b/Mage.Sets/src/mage/cards/g/GoblinVandal.java @@ -1,29 +1,23 @@ package mage.cards.g; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; +import mage.abilities.common.AttacksAndIsNotBlockedTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; -import mage.filter.FilterPermanent; -import mage.filter.common.FilterArtifactPermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.game.combat.CombatGroup; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; -import mage.target.Target; -import mage.target.TargetPermanent; +import mage.constants.SetTargetPointer; +import mage.constants.SubType; +import mage.target.common.TargetArtifactPermanent; +import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster; + +import java.util.UUID; /** * @@ -40,14 +34,13 @@ public final class GoblinVandal extends CardImpl { this.toughness = new MageInt(1); // Whenever Goblin Vandal attacks and isn't blocked, you may pay {R}. If you do, destroy target artifact defending player controls and Goblin Vandal assigns no combat damage this turn. - Effect effect = new DestroyTargetEffect(); - effect.setText("destroy target artifact defending player controls"); - DoIfCostPaid effect2 = new DoIfCostPaid(effect, new ManaCostsImpl<>("{R}"), "Pay {R} to destroy artifact of defending player?"); - effect = new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn); - effect.setText("and {this} assigns no combat damage this turn"); - effect2.addEffect(effect); - this.addAbility(new GoblinVandalTriggeredAbility(effect2)); - + DoIfCostPaid effect = new DoIfCostPaid(new DestroyTargetEffect().setText("destroy target artifact defending player controls"), + new ManaCostsImpl<>("{R}"), "Pay {R} to destroy artifact of defending player?"); + effect.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn).setText("and {this} assigns no combat damage this turn")); + Ability ability = new AttacksAndIsNotBlockedTriggeredAbility(effect, false, SetTargetPointer.PLAYER); + ability.addTarget(new TargetArtifactPermanent()); + ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster()); + this.addAbility(ability); } private GoblinVandal(final GoblinVandal card) { @@ -59,47 +52,3 @@ public final class GoblinVandal extends CardImpl { return new GoblinVandal(this); } } - -class GoblinVandalTriggeredAbility extends TriggeredAbilityImpl { - - public GoblinVandalTriggeredAbility(Effect effect) { - super(Zone.BATTLEFIELD, effect, false ); - } - - private GoblinVandalTriggeredAbility(final GoblinVandalTriggeredAbility ability) { - super(ability); - } - - @Override - public GoblinVandalTriggeredAbility copy() { - return new GoblinVandalTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DECLARED_BLOCKERS; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - Permanent sourcePermanent = game.getPermanent(getSourceId()); - if (sourcePermanent.isAttacking()) { - for (CombatGroup combatGroup: game.getCombat().getGroups()) { - if (combatGroup.getBlockers().isEmpty() && combatGroup.getAttackers().contains(getSourceId())) { - UUID defendingPlayerId = game.getCombat().getDefendingPlayerId(getSourceId(), game); - FilterPermanent filter = new FilterArtifactPermanent(); - filter.add(new ControllerIdPredicate(defendingPlayerId)); - Target target = new TargetPermanent(filter); - this.addTarget(target); - return true; - } - } - } - return false; - } - - @Override - public String getRule() { - return "Whenever {this} attacks and isn't blocked, you may pay {R}. If you do, destroy target artifact defending player controls and {this} assigns no combat damage this turn."; - } -} diff --git a/Mage.Sets/src/mage/cards/g/Godsend.java b/Mage.Sets/src/mage/cards/g/Godsend.java index ccf9d841a03..7a08c002b29 100644 --- a/Mage.Sets/src/mage/cards/g/Godsend.java +++ b/Mage.Sets/src/mage/cards/g/Godsend.java @@ -23,6 +23,7 @@ import mage.game.combat.CombatGroup; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FirstTargetPointer; import mage.target.targetpointer.FixedTarget; @@ -117,7 +118,7 @@ class GodsendTriggeredAbility extends TriggeredAbilityImpl { uuidPredicates.add(new PermanentIdPredicate(creatureId)); } filter.add(Predicates.or(uuidPredicates)); - this.getTargets().add(new TargetCreaturePermanent(filter)); + this.getTargets().add(new TargetPermanent(filter)); } return true; } diff --git a/Mage.Sets/src/mage/cards/g/GodtrackerOfJund.java b/Mage.Sets/src/mage/cards/g/GodtrackerOfJund.java index b890d219e00..4bc51670d13 100644 --- a/Mage.Sets/src/mage/cards/g/GodtrackerOfJund.java +++ b/Mage.Sets/src/mage/cards/g/GodtrackerOfJund.java @@ -1,33 +1,33 @@ package mage.cards.g; -import java.util.UUID; import mage.MageInt; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; 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.ComparisonType; -import mage.constants.Zone; +import mage.constants.SubType; import mage.counters.CounterType; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class GodtrackerOfJund extends CardImpl { - - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a creature with power 5 or greater"); - + + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("a creature you control with power 5 or greater"); + static { filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 4)); } public GodtrackerOfJund(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{R}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{G}"); this.subtype.add(SubType.ELF); this.subtype.add(SubType.SHAMAN); @@ -35,8 +35,9 @@ public final class GodtrackerOfJund extends CardImpl { this.toughness = new MageInt(2); // Whenever a creature with power 5 or greater you control enters, you may put a +1/+1 counter on Godtracker of Jund. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, - new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filter, true)); + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filter, true + )); } private GodtrackerOfJund(final GodtrackerOfJund card) { diff --git a/Mage.Sets/src/mage/cards/g/GoldenGuardian.java b/Mage.Sets/src/mage/cards/g/GoldenGuardian.java index d04e4c4c767..af1a5657715 100644 --- a/Mage.Sets/src/mage/cards/g/GoldenGuardian.java +++ b/Mage.Sets/src/mage/cards/g/GoldenGuardian.java @@ -1,6 +1,5 @@ package mage.cards.g; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; @@ -8,26 +7,23 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.FightTargetSourceEffect; import mage.abilities.keyword.DefenderAbility; import mage.abilities.keyword.TransformAbility; 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.SubType; -import mage.constants.Zone; +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.Permanent; import mage.players.Player; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class GoldenGuardian extends CardImpl { @@ -46,11 +42,10 @@ public final class GoldenGuardian extends CardImpl { // {2}: Golden Guardian fights another target creature you control. When Golden Guardian dies this turn, return it to the battlefield transformed under your control. this.addAbility(new TransformAbility()); - Ability ability = new SimpleActivatedAbility(new GoldenGuardianEffect(), new GenericManaCost(2)); - ability.addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); + Ability ability = new SimpleActivatedAbility(new FightTargetSourceEffect(), new GenericManaCost(2)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new GoldenGuardianDelayedTriggeredAbility(), false)); this.addAbility(ability); - } private GoldenGuardian(final GoldenGuardian card) { @@ -63,36 +58,6 @@ public final class GoldenGuardian extends CardImpl { } } -class GoldenGuardianEffect extends OneShotEffect { - - GoldenGuardianEffect() { - super(Outcome.Damage); - this.staticText = "{this} fights another target creature you control"; - } - - private GoldenGuardianEffect(final GoldenGuardianEffect effect) { - super(effect); - } - - @Override - public GoldenGuardianEffect copy() { - return new GoldenGuardianEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent creature1 = game.getPermanent(source.getSourceId()); - Permanent creature2 = game.getPermanent(source.getFirstTarget()); - // 20110930 - 701.10 - if (creature1 != null && creature2 != null) { - if (creature1.isCreature(game) && creature2.isCreature(game)) { - return creature1.fight(creature2, source, game); - } - } - return false; - } -} - class GoldenGuardianDelayedTriggeredAbility extends DelayedTriggeredAbility { public GoldenGuardianDelayedTriggeredAbility() { diff --git a/Mage.Sets/src/mage/cards/g/GolemArtisan.java b/Mage.Sets/src/mage/cards/g/GolemArtisan.java index 893ec99853d..e4fbc4bc4f7 100644 --- a/Mage.Sets/src/mage/cards/g/GolemArtisan.java +++ b/Mage.Sets/src/mage/cards/g/GolemArtisan.java @@ -17,10 +17,13 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_PERMANENT_ARTIFACT_CREATURE; + /** * @author nantuko */ @@ -35,13 +38,13 @@ public final class GolemArtisan extends CardImpl { // {2}: Target artifact creature gets +1/+1 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(1, 1, Duration.EndOfTurn), new GenericManaCost(2)); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_PERMANENT_ARTIFACT_CREATURE)); this.addAbility(ability); // {2}: Target artifact creature gains your choice of flying, trample, or haste until end of turn. ability = new SimpleActivatedAbility(new GainsChoiceOfAbilitiesEffect( FlyingAbility.getInstance(), TrampleAbility.getInstance(), HasteAbility.getInstance()), new GenericManaCost(2)); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_PERMANENT_ARTIFACT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GoliathHatchery.java b/Mage.Sets/src/mage/cards/g/GoliathHatchery.java index 2cfe4da6bb4..a1449663878 100644 --- a/Mage.Sets/src/mage/cards/g/GoliathHatchery.java +++ b/Mage.Sets/src/mage/cards/g/GoliathHatchery.java @@ -1,13 +1,12 @@ package mage.cards.g; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CorruptedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.ToxicAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AbilityWord; @@ -38,11 +37,10 @@ public final class GoliathHatchery extends CardImpl { )); // Corrupted -- At the beginning of your upkeep, if an opponent has three or more poison counters, choose a creature you control, then draw cards equal to its total toxic value. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility( - new GoliathHatcheryEffect(), false - ).setAbilityWord(AbilityWord.CORRUPTED), CorruptedCondition.instance, null - ).addHint(CorruptedCondition.getHint())); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new GoliathHatcheryEffect()) + .withInterveningIf(CorruptedCondition.instance) + .setAbilityWord(AbilityWord.CORRUPTED) + .addHint(CorruptedCondition.getHint())); } private GoliathHatchery(final GoliathHatchery card) { @@ -59,8 +57,7 @@ class GoliathHatcheryEffect extends OneShotEffect { GoliathHatcheryEffect() { super(Outcome.Benefit); - staticText = "if an opponent has three or more poison counters, " + - "choose a creature you control, then draw cards equal to its total toxic value"; + staticText = "choose a creature you control, then draw cards equal to its total toxic value"; } private GoliathHatcheryEffect(final GoliathHatcheryEffect effect) { diff --git a/Mage.Sets/src/mage/cards/g/GollumObsessedStalker.java b/Mage.Sets/src/mage/cards/g/GollumObsessedStalker.java index f513e05e29a..03fa20978c7 100644 --- a/Mage.Sets/src/mage/cards/g/GollumObsessedStalker.java +++ b/Mage.Sets/src/mage/cards/g/GollumObsessedStalker.java @@ -1,13 +1,12 @@ package mage.cards.g; import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.dynamicvalue.common.ControllerGainedLifeCount; import mage.abilities.effects.OneShotEffect; import mage.abilities.hint.Hint; import mage.abilities.keyword.SkulkAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -63,8 +62,8 @@ public final class GollumObsessedStalker extends CardImpl { class GollumObsessedStalkerWatcher extends Watcher { - // For each creature name, the players damaged by them during combat. - private final Map> playersPerName = new HashMap<>(); + // The players damaged by anything named "Gollum, Obsessed Stalker" during combat. + private final Set playersGollumDamaged = new HashSet<>(); public GollumObsessedStalkerWatcher() { super(WatcherScope.GAME); @@ -81,18 +80,14 @@ class GollumObsessedStalkerWatcher extends Watcher { return; } - String name = creature.getName(); UUID playerId = event.getPlayerId(); - if (creature.getName().isEmpty() || playerId == null) { - return; + if (creature.getName().equals("Gollum, Obsessed Stalker") && playerId != null) { + playersGollumDamaged.add(playerId); } - - playersPerName.computeIfAbsent(name, k -> new HashSet<>()); - playersPerName.get(name).add(playerId); } - public Set getPlayersDamagedByNamed(String name) { - return playersPerName.getOrDefault(name, new HashSet<>()); + public Set getPlayersDamaged() { + return playersGollumDamaged; } } @@ -101,7 +96,7 @@ class GollumObsessedStalkerEffect extends OneShotEffect { GollumObsessedStalkerEffect() { super(Outcome.LoseLife); staticText = "each opponent dealt combat damage this game by a creature named " - + "{this} loses life equal to the amount of life you gained this turn."; + + "Gollum, Obsessed Stalker loses life equal to the amount of life you gained this turn."; } private GollumObsessedStalkerEffect(final GollumObsessedStalkerEffect effect) { @@ -122,9 +117,8 @@ class GollumObsessedStalkerEffect extends OneShotEffect { return false; } - String name = gollum.getName(); int amount = lifeWatcher.getLifeGained(source.getControllerId()); - Set playersDamaged = damageWatcher.getPlayersDamagedByNamed(name); + Set playersDamaged = damageWatcher.getPlayersDamaged(); if (amount == 0 || playersDamaged.isEmpty()) { return true; @@ -157,34 +151,17 @@ enum GollumObsessedStalkerHint implements Hint { return ""; } - String name = null; - Permanent gollum = game.getPermanentOrLKIBattlefield(ability.getSourceId()); - if (gollum != null) { - // Gollum is or was in play, its name is using LKI. - name = gollum.getName(); - } else { - // if Gollum LKI not in play (like in hand or in command zone), - // find the object. - MageObject gollumObj = game.getObject(ability.getSourceId()); - if (gollumObj != null) { - name = gollumObj.getName(); - } - } - if (name == null || name.isEmpty()) { - return ""; - } - // Not filtering by opponent intentionally, just to provide full info everywhere. List namesOfPlayersDealtDamage = - watcher.getPlayersDamagedByNamed(name) - .stream() - .map(game::getPlayer) - .filter(Objects::nonNull) - .map(Player::getName) - .filter(n -> !n.isEmpty()) - .collect(Collectors.toList()); + watcher.getPlayersDamaged() + .stream() + .map(game::getPlayer) + .filter(Objects::nonNull) + .map(Player::getName) + .filter(n -> !n.isEmpty()) + .collect(Collectors.toList()); - return "Players dealt combat damage by creatures named " + name + " this game: [" + return "Players dealt combat damage by creatures named Gollum, Obsessed Stalker this game: [" + String.join(", ", namesOfPlayersDealtDamage) + "]"; } diff --git a/Mage.Sets/src/mage/cards/g/GornogTheRedReaper.java b/Mage.Sets/src/mage/cards/g/GornogTheRedReaper.java index 4411563c90c..93f24e52fe4 100644 --- a/Mage.Sets/src/mage/cards/g/GornogTheRedReaper.java +++ b/Mage.Sets/src/mage/cards/g/GornogTheRedReaper.java @@ -1,7 +1,8 @@ package mage.cards.g; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; +import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; @@ -16,13 +17,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.AttackingPredicate; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.game.events.DefenderAttackedEvent; -import mage.game.events.GameEvent; import mage.target.TargetPermanent; +import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster; import java.util.UUID; @@ -31,16 +30,17 @@ import java.util.UUID; */ public final class GornogTheRedReaper extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.WARRIOR, "Attacking Warriors"); - private static final FilterPermanent filter2 = new FilterPermanent(SubType.COWARD, "Cowards your opponents control"); + private static final FilterPermanent filterAttackWarrior = new FilterCreaturePermanent(SubType.WARRIOR, "Attacking Warriors"); + private static final FilterPermanent filterWarrior = new FilterControlledPermanent(SubType.WARRIOR, "Warriors you control"); + private static final FilterPermanent filterCoward = new FilterPermanent(SubType.COWARD, "Cowards your opponents control"); static { - filter.add(AttackingPredicate.instance); - filter2.add(TargetController.OPPONENT.getControllerPredicate()); + filterAttackWarrior.add(AttackingPredicate.instance); + filterCoward.add(TargetController.OPPONENT.getControllerPredicate()); } - private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter2, null); - private static final Hint hint = new ValueHint(filter2.getMessage(), xValue); + private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filterCoward, null); + private static final Hint hint = new ValueHint(filterCoward.getMessage(), xValue); public GornogTheRedReaper(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); @@ -58,11 +58,16 @@ public final class GornogTheRedReaper extends CardImpl { this.addAbility(new SimpleStaticAbility(new CowardsCantBlockWarriorsEffect())); // Whenever one or more Warriors you control attack a player, target creature that player controls becomes a Coward. - this.addAbility(new GornogTheRedReaperTriggeredAbility()); + Ability ability = new AttacksPlayerWithCreaturesTriggeredAbility( + new BecomesCreatureTypeTargetEffect(Duration.EndOfGame, SubType.COWARD).setText("target creature that player controls becomes a Coward"), + filterWarrior, SetTargetPointer.PLAYER); + ability.addTarget(new TargetPermanent()); + ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster()); + this.addAbility(ability); // Attacking Warriors you control get +X/+0, where X is the number of Cowards your opponents control. this.addAbility(new SimpleStaticAbility(new BoostControlledEffect( - xValue, StaticValue.get(0), Duration.WhileOnBattlefield, filter, false + xValue, StaticValue.get(0), Duration.WhileOnBattlefield, filterAttackWarrior, false )).addHint(hint)); } @@ -75,42 +80,3 @@ public final class GornogTheRedReaper extends CardImpl { return new GornogTheRedReaper(this); } } - -class GornogTheRedReaperTriggeredAbility extends TriggeredAbilityImpl { - - GornogTheRedReaperTriggeredAbility() { - super(Zone.BATTLEFIELD, new BecomesCreatureTypeTargetEffect(Duration.EndOfGame, SubType.COWARD) - .setText("target creature that player controls becomes a Coward")); - this.setTriggerPhrase("Whenever one or more Warriors you control attack a player, "); - } - - private GornogTheRedReaperTriggeredAbility(final GornogTheRedReaperTriggeredAbility ability) { - super(ability); - } - - @Override - public GornogTheRedReaperTriggeredAbility copy() { - return new GornogTheRedReaperTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DEFENDER_ATTACKED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (game.getPlayer(event.getTargetId()) == null - || ((DefenderAttackedEvent) event) - .getAttackers(game) - .stream() - .noneMatch(p -> p.hasSubtype(SubType.WARRIOR, game) && p.isControlledBy(getControllerId()))) { - return false; - } - FilterPermanent filter = new FilterCreaturePermanent("creature controlled by defending player"); - filter.add(new ControllerIdPredicate(event.getTargetId())); - this.getTargets().clear(); - this.addTarget(new TargetPermanent(filter)); - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/g/GoroGoroDiscipleOfRyusei.java b/Mage.Sets/src/mage/cards/g/GoroGoroDiscipleOfRyusei.java index 2ea296d1457..0a5ab3cfd16 100644 --- a/Mage.Sets/src/mage/cards/g/GoroGoroDiscipleOfRyusei.java +++ b/Mage.Sets/src/mage/cards/g/GoroGoroDiscipleOfRyusei.java @@ -5,7 +5,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.abilities.hint.ConditionHint; @@ -13,7 +13,10 @@ import mage.abilities.hint.Hint; import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.filter.FilterPermanent; import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; @@ -29,7 +32,7 @@ import java.util.UUID; public final class GoroGoroDiscipleOfRyusei extends CardImpl { private static final FilterPermanent filter - = new FilterControlledCreaturePermanent("if you control an attacking modified creature"); + = new FilterControlledCreaturePermanent("you control an attacking modified creature"); static { filter.add(AttackingPredicate.instance); @@ -37,9 +40,7 @@ public final class GoroGoroDiscipleOfRyusei extends CardImpl { } private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); - private static final Hint hint = new ConditionHint( - condition, "You control and attacking modified creature" - ); + private static final Hint hint = new ConditionHint(condition); public GoroGoroDiscipleOfRyusei(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); @@ -57,8 +58,8 @@ public final class GoroGoroDiscipleOfRyusei extends CardImpl { ), new ManaCostsImpl<>("{R}"))); // {3}{R}{R}: Create a 5/5 red Dragon Spirit creature token with flying. Activate only if you control an attacking modified creature. - this.addAbility(new ConditionalActivatedAbility( - Zone.BATTLEFIELD, new CreateTokenEffect(new DragonSpiritToken()), + this.addAbility(new ActivateIfConditionActivatedAbility( + new CreateTokenEffect(new DragonSpiritToken()), new ManaCostsImpl<>("{3}{R}{R}"), condition ).addHint(hint)); } diff --git a/Mage.Sets/src/mage/cards/g/GossamerChains.java b/Mage.Sets/src/mage/cards/g/GossamerChains.java index 56afe0a9dba..5cc3c833f3a 100644 --- a/Mage.Sets/src/mage/cards/g/GossamerChains.java +++ b/Mage.Sets/src/mage/cards/g/GossamerChains.java @@ -13,6 +13,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.UnblockedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -32,7 +33,7 @@ public final class GossamerChains extends CardImpl { // Return Gossamer Chains to its owner's hand: Prevent all combat damage that would be dealt by target unblocked creature this turn. Ability ability = new SimpleActivatedAbility(new PreventDamageByTargetEffect(Duration.EndOfTurn, true), new ReturnToHandFromBattlefieldSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GougedZealot.java b/Mage.Sets/src/mage/cards/g/GougedZealot.java index e0bb7822c98..4c573cf9ca6 100644 --- a/Mage.Sets/src/mage/cards/g/GougedZealot.java +++ b/Mage.Sets/src/mage/cards/g/GougedZealot.java @@ -3,12 +3,12 @@ package mage.cards.g; import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.DeliriumCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.effects.common.DamageAllControlledTargetEffect; import mage.abilities.keyword.ReachAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SetTargetPointer; import mage.constants.SubType; @@ -16,7 +16,6 @@ import mage.constants.SubType; import java.util.UUID; /** - * * @author weirddan455 */ public final class GougedZealot extends CardImpl { @@ -33,11 +32,11 @@ public final class GougedZealot extends CardImpl { this.addAbility(ReachAbility.getInstance()); // Delirium — Whenever Gouged Zealot attacks, if there are four or more card types among cards in your graveyard, Gouged Zealot deals 1 damage to each creature defending player controls. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new DamageAllControlledTargetEffect(1), false, null, SetTargetPointer.PLAYER), - DeliriumCondition.instance, - "Delirium — Whenever {this} attacks, if there are four or more card types among cards in your graveyard, {this} deals 1 damage to each creature defending player controls." - ).addHint(CardTypesInGraveyardCount.YOU.getHint())); + this.addAbility(new AttacksTriggeredAbility( + new DamageAllControlledTargetEffect(1) + .setText("{this} deals 1 damage to each creature defending player controls"), + false, null, SetTargetPointer.PLAYER + ).withInterveningIf(DeliriumCondition.instance).setAbilityWord(AbilityWord.DELIRIUM).addHint(CardTypesInGraveyardCount.YOU.getHint())); } private GougedZealot(final GougedZealot card) { diff --git a/Mage.Sets/src/mage/cards/g/GovernTheGuildless.java b/Mage.Sets/src/mage/cards/g/GovernTheGuildless.java index 81e25b92ed2..73ee79d0453 100644 --- a/Mage.Sets/src/mage/cards/g/GovernTheGuildless.java +++ b/Mage.Sets/src/mage/cards/g/GovernTheGuildless.java @@ -12,6 +12,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.MonocoloredPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -31,7 +32,7 @@ public final class GovernTheGuildless extends CardImpl { // Gain control of target monocolored creature. this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.Custom)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // Forecast - {1}{U}, Reveal Govern the Guildless from your hand: Target creature becomes the color or colors of your choice until end of turn. ForecastAbility ability = new ForecastAbility(new BecomesColorOrColorsTargetEffect(Duration.EndOfTurn), new ManaCostsImpl<>("{1}{U}")); diff --git a/Mage.Sets/src/mage/cards/g/GrafRats.java b/Mage.Sets/src/mage/cards/g/GrafRats.java index 5b37662a5df..6715c1b3c80 100644 --- a/Mage.Sets/src/mage/cards/g/GrafRats.java +++ b/Mage.Sets/src/mage/cards/g/GrafRats.java @@ -1,11 +1,10 @@ package mage.cards.g; import mage.MageInt; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.MeldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.MeldEffect; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -30,13 +29,9 @@ public final class GrafRats extends CardImpl { this.meldsToClazz = mage.cards.c.ChitteringHost.class; // At the beginning of combat on your turn, if you both own and control Graf Rats and a creature named Midnight Scavengers, exile them, then meld them into Chittering Host. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility(new MeldEffect( - "Midnight Scavengers", "Chittering Host" - )), condition, "At the beginning " + - "of combat on your turn, if you both own and control {this} and a creature " + - "named Midnight Scavengers, exile them, then meld them into Chittering Host." - )); + this.addAbility(new BeginningOfCombatTriggeredAbility(new MeldEffect( + "Midnight Scavengers", "Chittering Host" + )).withInterveningIf(condition)); } private GrafRats(final GrafRats card) { diff --git a/Mage.Sets/src/mage/cards/g/GrandArchitect.java b/Mage.Sets/src/mage/cards/g/GrandArchitect.java index e21d3124bc3..99f2d0e2372 100644 --- a/Mage.Sets/src/mage/cards/g/GrandArchitect.java +++ b/Mage.Sets/src/mage/cards/g/GrandArchitect.java @@ -17,13 +17,13 @@ import mage.constants.*; import mage.filter.FilterPermanent; import mage.filter.StaticFilters; 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.TappedPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; -import mage.target.common.TargetControlledCreaturePermanent; import java.util.UUID; @@ -33,7 +33,7 @@ import java.util.UUID; public final class GrandArchitect extends CardImpl { private static final FilterCreaturePermanent boostFilter = new FilterCreaturePermanent("blue creatures"); - private static final FilterControlledCreaturePermanent tapFilter = new FilterControlledCreaturePermanent("untapped blue creature you control"); + private static final FilterControlledPermanent tapFilter = new FilterControlledCreaturePermanent("untapped blue creature you control"); static { boostFilter.add(new ColorPredicate(ObjectColor.BLUE)); @@ -108,9 +108,8 @@ class GrandArchitectManaAbility extends ActivatedManaAbilityImpl { private final FilterPermanent filter; - GrandArchitectManaAbility(FilterControlledCreaturePermanent filter) { - super(Zone.BATTLEFIELD, new BasicManaEffect(new GrandArchitectConditionalMana()), - new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, true))); + GrandArchitectManaAbility(FilterControlledPermanent filter) { + super(Zone.BATTLEFIELD, new BasicManaEffect(new GrandArchitectConditionalMana()), new TapTargetCost(filter)); this.netMana.add(new GrandArchitectConditionalMana()); this.filter = filter; } diff --git a/Mage.Sets/src/mage/cards/g/GrapeshotCatapult.java b/Mage.Sets/src/mage/cards/g/GrapeshotCatapult.java index 12561052632..ae8d84dce82 100644 --- a/Mage.Sets/src/mage/cards/g/GrapeshotCatapult.java +++ b/Mage.Sets/src/mage/cards/g/GrapeshotCatapult.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,7 +39,7 @@ public final class GrapeshotCatapult extends CardImpl { // {tap}: Grapeshot Catapult deals 1 damage to target creature with flying. Ability activatedAbility = new SimpleActivatedAbility(new DamageTargetEffect(1), new TapSourceCost()); - activatedAbility.addTarget(new TargetCreaturePermanent(filter)); + activatedAbility.addTarget(new TargetPermanent(filter)); this.addAbility(activatedAbility); } diff --git a/Mage.Sets/src/mage/cards/g/GraspOfTheHieromancer.java b/Mage.Sets/src/mage/cards/g/GraspOfTheHieromancer.java index 13ce22155bc..2aafbb2a977 100644 --- a/Mage.Sets/src/mage/cards/g/GraspOfTheHieromancer.java +++ b/Mage.Sets/src/mage/cards/g/GraspOfTheHieromancer.java @@ -1,7 +1,5 @@ - package mage.cards.g; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleStaticAbility; @@ -13,12 +11,7 @@ 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.SubType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; @@ -26,14 +19,15 @@ import mage.game.events.GameEvent; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class GraspOfTheHieromancer extends CardImpl { public GraspOfTheHieromancer(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}"); this.subtype.add(SubType.AURA); // Enchant creature @@ -42,18 +36,18 @@ public final class GraspOfTheHieromancer extends CardImpl { this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); Ability ability = new EnchantAbility(auraTarget); this.addAbility(ability); - + // Enchanted creature gets +1/+1 and has "Whenever this creature attacks, tap target creature defending player controls." ability = new SimpleStaticAbility(new BoostEnchantedEffect(1, 1, Duration.WhileOnBattlefield)); - Ability gainedAbility = new GraspOfTheHieromancerTriggeredAbility(new TapTargetEffect(), false); - gainedAbility.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature defending player controls"))); + Ability gainedAbility = new GraspOfTheHieromancerTriggeredAbility(new TapTargetEffect(), false); + gainedAbility.addTarget(new TargetPermanent(new FilterCreaturePermanent("creature defending player controls"))); Effect effect = new GainAbilityAttachedEffect(gainedAbility, AttachmentType.AURA); effect.setText("and has \"Whenever this creature attacks, tap target creature defending player controls.\""); ability.addEffect(effect); this.addAbility(ability); - + } - + private GraspOfTheHieromancer(final GraspOfTheHieromancer card) { super(card); } @@ -65,9 +59,8 @@ public final class GraspOfTheHieromancer extends CardImpl { } class GraspOfTheHieromancerTriggeredAbility extends TriggeredAbilityImpl { - - + public GraspOfTheHieromancerTriggeredAbility(Effect effect, boolean optional) { super(Zone.BATTLEFIELD, effect, optional); } @@ -83,17 +76,16 @@ class GraspOfTheHieromancerTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (game.getCombat().getAttackers().contains(getSourceId()) ) { + if (game.getCombat().getAttackers().contains(getSourceId())) { UUID defendingPlayerId = game.getCombat().getDefendingPlayerId(getSourceId(), game); - if (defendingPlayerId != null) { + if (defendingPlayerId != null) { this.getTargets().clear(); FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); UUID defenderId = game.getCombat().getDefenderId(getSourceId()); filter.add(new ControllerIdPredicate(defenderId)); - TargetCreaturePermanent target = new TargetCreaturePermanent(filter); - this.addTarget(target); + this.addTarget(new TargetPermanent(filter)); return true; - } + } } return false; } diff --git a/Mage.Sets/src/mage/cards/g/GrasslandCrusader.java b/Mage.Sets/src/mage/cards/g/GrasslandCrusader.java index 0536fa34cb4..64dc8f3e3a2 100644 --- a/Mage.Sets/src/mage/cards/g/GrasslandCrusader.java +++ b/Mage.Sets/src/mage/cards/g/GrasslandCrusader.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -39,7 +40,7 @@ public final class GrasslandCrusader extends CardImpl { // {tap}: Target Elf or Soldier creature gets +2/+2 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(2, 2, Duration.EndOfTurn), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GraveScrabbler.java b/Mage.Sets/src/mage/cards/g/GraveScrabbler.java index 2eb04dcdb6b..d03ead0c285 100644 --- a/Mage.Sets/src/mage/cards/g/GraveScrabbler.java +++ b/Mage.Sets/src/mage/cards/g/GraveScrabbler.java @@ -1,22 +1,25 @@ package mage.cards.g; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.abilities.keyword.MadnessAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.filter.FilterCard; import mage.filter.common.FilterCreatureCard; import mage.target.common.TargetCardInGraveyard; +import java.util.UUID; + public final class GraveScrabbler extends CardImpl { + private static final FilterCard filter = new FilterCreatureCard("creature card from a graveyard"); + public GraveScrabbler(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); this.subtype.add(SubType.ZOMBIE); @@ -24,15 +27,14 @@ public final class GraveScrabbler extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - //Madness {1}{B} + // Madness {1}{B} this.addAbility(new MadnessAbility(new ManaCostsImpl<>("{1}{B}"))); - //When Grave Scrabbler enters the battlefield, if its madness cost was paid, - //you may return target creature card from a graveyard to its owner's hand. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true); - ability.addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card in a graveyard"))); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, MadnessAbility.getCondition(), - "When {this} enters, if its madness cost was paid, you may return target creature card from a graveyard to its owner's hand.")); + // When Grave Scrabbler enters the battlefield, if its madness cost was paid, you may return target creature card from a graveyard to its owner's hand. + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true) + .withInterveningIf(MadnessAbility.getCondition()); + ability.addTarget(new TargetCardInGraveyard(filter)); + this.addAbility(ability); } private GraveScrabbler(final GraveScrabbler card) { diff --git a/Mage.Sets/src/mage/cards/g/GravelSlinger.java b/Mage.Sets/src/mage/cards/g/GravelSlinger.java index ab01098cca4..8f40f40e767 100644 --- a/Mage.Sets/src/mage/cards/g/GravelSlinger.java +++ b/Mage.Sets/src/mage/cards/g/GravelSlinger.java @@ -15,6 +15,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterAttackingOrBlockingCreature; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -32,7 +33,7 @@ public final class GravelSlinger extends CardImpl { // {tap}: Gravel Slinger deals 1 damage to target attacking or blocking creature. Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(new FilterAttackingOrBlockingCreature())); + ability.addTarget(new TargetPermanent(new FilterAttackingOrBlockingCreature())); this.addAbility(ability); // Morph {1}{W} this.addAbility(new MorphAbility(this, new ManaCostsImpl<>("{1}{W}"))); diff --git a/Mage.Sets/src/mage/cards/g/Gravelighter.java b/Mage.Sets/src/mage/cards/g/Gravelighter.java index ff42e68b7d9..2f492cd509a 100644 --- a/Mage.Sets/src/mage/cards/g/Gravelighter.java +++ b/Mage.Sets/src/mage/cards/g/Gravelighter.java @@ -36,7 +36,7 @@ public final class Gravelighter extends CardImpl { new DrawCardSourceControllerEffect(1), new SacrificeAllEffect(StaticFilters.FILTER_PERMANENT_CREATURE), MorbidCondition.instance, "draw a card if a creature died this turn. " + - "Otherwise, each player sacrifices a creature" + "Otherwise, each player sacrifices a creature of their choice" )).addHint(MorbidHint.instance)); } diff --git a/Mage.Sets/src/mage/cards/g/GravespawnSovereign.java b/Mage.Sets/src/mage/cards/g/GravespawnSovereign.java index 126f0f857cf..fd0955b3970 100644 --- a/Mage.Sets/src/mage/cards/g/GravespawnSovereign.java +++ b/Mage.Sets/src/mage/cards/g/GravespawnSovereign.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; @@ -11,21 +9,20 @@ 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.FilterControlledCreaturePermanent; -import mage.filter.common.FilterCreatureCard; +import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.permanent.TappedPredicate; import mage.target.common.TargetCardInGraveyard; -import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; /** - * * @author escplan9 (Derek Monturo - dmontur1 at gmail dot com) */ public final class GravespawnSovereign extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Zombies you control"); + private static final FilterControlledPermanent filter = new FilterControlledCreaturePermanent("untapped Zombies you control"); static { filter.add(SubType.ZOMBIE.getPredicate()); @@ -39,10 +36,11 @@ public final class GravespawnSovereign extends CardImpl { this.toughness = new MageInt(3); // Tap five untapped Zombies you control: Put target creature card from a graveyard onto the battlefield under your control. - Ability ability = new SimpleActivatedAbility(new ReturnFromGraveyardToBattlefieldTargetEffect(), new TapTargetCost(new TargetControlledCreaturePermanent(5, 5, filter, true))); + Ability ability = new SimpleActivatedAbility( + new ReturnFromGraveyardToBattlefieldTargetEffect(), new TapTargetCost(5, filter) + ); ability.addTarget(new TargetCardInGraveyard(StaticFilters.FILTER_CARD_CREATURE_A_GRAVEYARD)); this.addAbility(ability); - } private GravespawnSovereign(final GravespawnSovereign card) { diff --git a/Mage.Sets/src/mage/cards/g/GravityNegator.java b/Mage.Sets/src/mage/cards/g/GravityNegator.java index 8b90a1c8ba7..5d908c291a2 100644 --- a/Mage.Sets/src/mage/cards/g/GravityNegator.java +++ b/Mage.Sets/src/mage/cards/g/GravityNegator.java @@ -16,8 +16,11 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Duration; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * * @author fireshoes @@ -40,7 +43,7 @@ public final class GravityNegator extends CardImpl { // Whenenever Gravity Negator attacks, you may pay {C}. If you do, another target creature gains flying until end of turn. Ability ability = new AttacksTriggeredAbility(new DoIfCostPaid(new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{C}")), false, "Whenever {this} attacks, you may pay {C}. If you do, another target creature gains flying until end of turn."); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GreenerPastures.java b/Mage.Sets/src/mage/cards/g/GreenerPastures.java index 41af30b83f1..91388dce603 100644 --- a/Mage.Sets/src/mage/cards/g/GreenerPastures.java +++ b/Mage.Sets/src/mage/cards/g/GreenerPastures.java @@ -1,9 +1,9 @@ package mage.cards.g; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.effects.common.CreateTokenTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -16,7 +16,6 @@ import mage.players.Player; import java.util.UUID; /** - * * @author TheElk801 */ public final class GreenerPastures extends CardImpl { @@ -26,7 +25,7 @@ public final class GreenerPastures extends CardImpl { // At the beginning of each player's upkeep, if that player controls more lands than each other player, the player creates a 1/1 green Saproling creature token. this.addAbility(new BeginningOfUpkeepTriggeredAbility( - TargetController.EACH_PLAYER, new CreateTokenTargetEffect(new SaprolingToken()), + TargetController.EACH_PLAYER, new CreateTokenTargetEffect(new SaprolingToken()).setText("the player creates a 1/1 green Saproling creature token"), false ).withInterveningIf(ActivePlayerMostLandsCondition.instance)); } diff --git a/Mage.Sets/src/mage/cards/g/GreenhiltTrainee.java b/Mage.Sets/src/mage/cards/g/GreenhiltTrainee.java index 31122f6b718..7c985e7530f 100644 --- a/Mage.Sets/src/mage/cards/g/GreenhiltTrainee.java +++ b/Mage.Sets/src/mage/cards/g/GreenhiltTrainee.java @@ -11,7 +11,6 @@ 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.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; @@ -30,8 +29,9 @@ public final class GreenhiltTrainee extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(3); + Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new BoostTargetEffect(4, 4, Duration.EndOfTurn), + new BoostTargetEffect(4, 4, Duration.EndOfTurn), new TapSourceCost(), GreenhiltTraineeCondition.instance ); ability.addTarget(new TargetCreaturePermanent()); diff --git a/Mage.Sets/src/mage/cards/g/GrenzoHavocRaiser.java b/Mage.Sets/src/mage/cards/g/GrenzoHavocRaiser.java index 755c7b2dc10..2f5e42808ec 100644 --- a/Mage.Sets/src/mage/cards/g/GrenzoHavocRaiser.java +++ b/Mage.Sets/src/mage/cards/g/GrenzoHavocRaiser.java @@ -19,7 +19,9 @@ import mage.game.events.DamagedEvent; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.DefineByTriggerTargetAdjuster; import mage.target.targetpointer.FixedTarget; import mage.util.CardUtil; @@ -69,6 +71,7 @@ class GrenzoHavocRaiserTriggeredAbility extends TriggeredAbilityImpl { public GrenzoHavocRaiserTriggeredAbility(Effect effect) { super(Zone.BATTLEFIELD, effect, false); setTriggerPhrase("Whenever a creature you control deals combat damage to a player, "); + setTargetAdjuster(DefineByTriggerTargetAdjuster.instance); } private GrenzoHavocRaiserTriggeredAbility(final GrenzoHavocRaiserTriggeredAbility ability) { @@ -107,7 +110,7 @@ class GrenzoHavocRaiserTriggeredAbility extends TriggeredAbilityImpl { FilterCreaturePermanent filter = new FilterCreaturePermanent("creature " + damagedPlayer.getLogName() + " controls"); filter.add(new ControllerIdPredicate(damagedPlayer.getId())); this.getTargets().clear(); - this.addTarget(new TargetCreaturePermanent(filter)); + this.addTarget(new TargetPermanent(filter)); for (Effect effect : this.getAllEffects()) { if (effect instanceof GrenzoHavocRaiserEffect) { effect.setTargetPointer(new FixedTarget(event.getPlayerId())); diff --git a/Mage.Sets/src/mage/cards/g/GriffinAerie.java b/Mage.Sets/src/mage/cards/g/GriffinAerie.java index 2c23807b080..95c852f9c70 100644 --- a/Mage.Sets/src/mage/cards/g/GriffinAerie.java +++ b/Mage.Sets/src/mage/cards/g/GriffinAerie.java @@ -1,12 +1,10 @@ package mage.cards.g; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.YouGainedLifeCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.dynamicvalue.common.ControllerGainedLifeCount; import mage.abilities.effects.common.CreateTokenEffect; -import mage.abilities.hint.ConditionHint; -import mage.abilities.hint.Hint; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -22,18 +20,13 @@ import java.util.UUID; 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()) - ), 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()); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new CreateTokenEffect(new GriffinToken())) + .withInterveningIf(condition).addHint(ControllerGainedLifeCount.getHint()), new PlayerGainedLifeWatcher()); } private GriffinAerie(final GriffinAerie card) { diff --git a/Mage.Sets/src/mage/cards/g/GrimPoppet.java b/Mage.Sets/src/mage/cards/g/GrimPoppet.java index c55993e5700..dd090b52cb8 100644 --- a/Mage.Sets/src/mage/cards/g/GrimPoppet.java +++ b/Mage.Sets/src/mage/cards/g/GrimPoppet.java @@ -17,6 +17,7 @@ import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -42,7 +43,7 @@ public final class GrimPoppet extends CardImpl { // Remove a -1/-1 counter from Grim Poppet: Put a -1/-1 counter on another target creature. Ability ability = new SimpleActivatedAbility(new AddCountersTargetEffect(CounterType.M1M1.createInstance()), new RemoveCountersSourceCost(CounterType.M1M1.createInstance())); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GrimReminder.java b/Mage.Sets/src/mage/cards/g/GrimReminder.java index 3da95e7a63e..3a2c509bb2c 100644 --- a/Mage.Sets/src/mage/cards/g/GrimReminder.java +++ b/Mage.Sets/src/mage/cards/g/GrimReminder.java @@ -1,27 +1,15 @@ - package mage.cards.g; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect; -import mage.abilities.effects.common.ReturnToHandSourceEffect; -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.PhaseStep; import mage.constants.WatcherScope; import mage.constants.Zone; import mage.filter.StaticFilters; @@ -31,8 +19,9 @@ import mage.players.Player; import mage.target.common.TargetCardInLibrary; import mage.watchers.Watcher; +import java.util.*; + /** - * * @author TheElk801 */ public final class GrimReminder extends CardImpl { @@ -45,12 +34,9 @@ public final class GrimReminder extends CardImpl { this.getSpellAbility().addWatcher(new GrimReminderWatcher()); // {B}{B}: Return Grim Reminder from your graveyard to your hand. Activate this ability only during your upkeep. - this.addAbility(new ConditionalActivatedAbility( - Zone.GRAVEYARD, - new ReturnSourceFromGraveyardToHandEffect(), - new ManaCostsImpl<>("{B}{B}"), - new IsStepCondition(PhaseStep.UPKEEP), - null + this.addAbility(new ActivateIfConditionActivatedAbility( + Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(), + new ManaCostsImpl<>("{B}{B}"), IsStepCondition.getMyUpkeep() )); } diff --git a/Mage.Sets/src/mage/cards/g/GrimgrinCorpseBorn.java b/Mage.Sets/src/mage/cards/g/GrimgrinCorpseBorn.java index b462f8fddc2..c84496798d5 100644 --- a/Mage.Sets/src/mage/cards/g/GrimgrinCorpseBorn.java +++ b/Mage.Sets/src/mage/cards/g/GrimgrinCorpseBorn.java @@ -20,6 +20,7 @@ import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.DefendingPlayerControlsSourceAttackingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; @@ -60,7 +61,7 @@ public final class GrimgrinCorpseBorn extends CardImpl { // Whenever Grimgrin attacks, destroy target creature defending player controls, then put a +1/+1 counter on Grimgrin. ability = new AttacksTriggeredAbility(new DestroyTargetEffect()); ability.addEffect(new AddCountersSourceEffect(CounterType.P1P1.createInstance()).concatBy(", then")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GrindDust.java b/Mage.Sets/src/mage/cards/g/GrindDust.java index 38b34a7fc46..7f11a2d869d 100644 --- a/Mage.Sets/src/mage/cards/g/GrindDust.java +++ b/Mage.Sets/src/mage/cards/g/GrindDust.java @@ -1,8 +1,5 @@ - package mage.cards.g; -import java.util.UUID; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.keyword.AftermathAbility; @@ -11,34 +8,40 @@ import mage.cards.SplitCard; import mage.constants.CardType; import mage.constants.SpellAbilityType; import mage.counters.CounterType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class GrindDust extends SplitCard { + private static final FilterPermanent filter = new FilterCreaturePermanent("creatures that have -1/-1 counters on them"); + + static { + filter.add(CounterType.M1M1.getPredicate()); + } + public GrindDust(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, new CardType[]{CardType.SORCERY}, "{1}{B}", "{3}{W}", SpellAbilityType.SPLIT_AFTERMATH); // Grind // Put a -1/-1 counter on each of up to two target creatures. - Effect effect = new AddCountersTargetEffect(CounterType.M1M1.createInstance()); - effect.setText("Put a -1/-1 counter on each of up to two target creatures"); - getLeftHalfCard().getSpellAbility().addEffect(effect); - getLeftHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent(0, 2)); + this.getLeftHalfCard().getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.M1M1.createInstance()) + .setText("Put a -1/-1 counter on each of up to two target creatures")); + this.getLeftHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent(0, 2)); // Dust // Aftermath - getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); - // Exile any number of target creatures that have -1/-1 counters on them. - getRightHalfCard().getSpellAbility().addEffect(new ExileTargetEffect()); - FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures that have -1/-1 counters on them"); - filter.add(CounterType.M1M1.getPredicate()); - getRightHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent(0, Integer.MAX_VALUE, filter, false)); + this.getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); + // Exile any number of target creatures that have -1/-1 counters on them. + this.getRightHalfCard().getSpellAbility().addEffect(new ExileTargetEffect()); + this.getRightHalfCard().getSpellAbility().addTarget(new TargetPermanent(0, Integer.MAX_VALUE, filter)); } private GrindDust(final GrindDust card) { diff --git a/Mage.Sets/src/mage/cards/g/GrotagSiegeRunner.java b/Mage.Sets/src/mage/cards/g/GrotagSiegeRunner.java index cde46db7dc5..83930a294c6 100644 --- a/Mage.Sets/src/mage/cards/g/GrotagSiegeRunner.java +++ b/Mage.Sets/src/mage/cards/g/GrotagSiegeRunner.java @@ -16,6 +16,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -44,7 +45,7 @@ public final class GrotagSiegeRunner extends CardImpl { Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new ManaCostsImpl<>("{R}")); ability.addCost(new SacrificeSourceCost()); ability.addEffect(new DamageTargetControllerEffect(2)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GroundRift.java b/Mage.Sets/src/mage/cards/g/GroundRift.java index 7e355382293..b99262affd7 100644 --- a/Mage.Sets/src/mage/cards/g/GroundRift.java +++ b/Mage.Sets/src/mage/cards/g/GroundRift.java @@ -12,6 +12,7 @@ import mage.constants.Duration; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -31,7 +32,7 @@ public final class GroundRift extends CardImpl { // Target creature without flying can't block this turn. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new CantBlockTargetEffect(Duration.EndOfTurn)); // Storm this.addAbility(new StormAbility()); diff --git a/Mage.Sets/src/mage/cards/g/GroveOfTheBurnwillows.java b/Mage.Sets/src/mage/cards/g/GroveOfTheBurnwillows.java index 616a8ec8b8a..88f33581be5 100644 --- a/Mage.Sets/src/mage/cards/g/GroveOfTheBurnwillows.java +++ b/Mage.Sets/src/mage/cards/g/GroveOfTheBurnwillows.java @@ -1,37 +1,35 @@ - package mage.cards.g; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.GainLifeAllEffect; import mage.abilities.mana.ColorlessManaAbility; import mage.abilities.mana.GreenManaAbility; import mage.abilities.mana.RedManaAbility; 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.constants.TargetController; + +import java.util.UUID; /** - * * @author jonubuu */ public final class GroveOfTheBurnwillows extends CardImpl { public GroveOfTheBurnwillows(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.LAND},""); + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); // {tap}: Add {C}. this.addAbility(new ColorlessManaAbility()); + // {tap}: Add {R} or {G}. Each opponent gains 1 life. - Ability RedManaAbility = new RedManaAbility(); - RedManaAbility.addEffect(new GroveOfTheBurnwillowsEffect()); - this.addAbility(RedManaAbility); - Ability GreenManaAbility = new GreenManaAbility(); - GreenManaAbility.addEffect(new GroveOfTheBurnwillowsEffect()); - this.addAbility(GreenManaAbility); + Ability ability = new RedManaAbility(); + ability.addEffect(new GainLifeAllEffect(1, TargetController.OPPONENT)); + this.addAbility(ability); + ability = new GreenManaAbility(); + ability.addEffect(new GainLifeAllEffect(1, TargetController.OPPONENT)); + this.addAbility(ability); } private GroveOfTheBurnwillows(final GroveOfTheBurnwillows card) { @@ -43,31 +41,3 @@ public final class GroveOfTheBurnwillows extends CardImpl { return new GroveOfTheBurnwillows(this); } } - -class GroveOfTheBurnwillowsEffect extends OneShotEffect { - - GroveOfTheBurnwillowsEffect() { - super(Outcome.Benefit); - staticText = "Each opponent gains 1 life"; - } - - private GroveOfTheBurnwillowsEffect(final GroveOfTheBurnwillowsEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - for (UUID playerId : game.getOpponents(source.getControllerId())) { - Player player = game.getPlayer(playerId); - if(player != null) { - player.gainLife(1, game, source); - } - } - return true; - } - - @Override - public GroveOfTheBurnwillowsEffect copy() { - return new GroveOfTheBurnwillowsEffect(this); - } -} diff --git a/Mage.Sets/src/mage/cards/g/GroveOfTheGuardian.java b/Mage.Sets/src/mage/cards/g/GroveOfTheGuardian.java index d2623292303..1da7365b6c4 100644 --- a/Mage.Sets/src/mage/cards/g/GroveOfTheGuardian.java +++ b/Mage.Sets/src/mage/cards/g/GroveOfTheGuardian.java @@ -13,10 +13,8 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.permanent.TappedPredicate; +import mage.filter.StaticFilters; import mage.game.permanent.token.GreenAndWhiteElementalToken; -import mage.target.common.TargetControlledCreaturePermanent; import java.util.UUID; @@ -25,12 +23,6 @@ import java.util.UUID; */ public final class GroveOfTheGuardian extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); - - static { - filter.add(TappedPredicate.UNTAPPED); - } - public GroveOfTheGuardian(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); @@ -40,7 +32,7 @@ public final class GroveOfTheGuardian extends CardImpl { // {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(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 TapTargetCost(2, StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURES)); ability.addCost(new SacrificeSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GrowingRitesOfItlimoc.java b/Mage.Sets/src/mage/cards/g/GrowingRitesOfItlimoc.java index e4f6c554687..cbc80fc495e 100644 --- a/Mage.Sets/src/mage/cards/g/GrowingRitesOfItlimoc.java +++ b/Mage.Sets/src/mage/cards/g/GrowingRitesOfItlimoc.java @@ -1,24 +1,34 @@ package mage.cards.g; -import java.util.UUID; - -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.hint.common.CreaturesYouControlHint; import mage.abilities.keyword.TransformAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.PutCards; +import mage.constants.SuperType; import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledCreaturePermanent; + +import java.util.UUID; /** * @author JRHerlehy */ public final class GrowingRitesOfItlimoc extends CardImpl { + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledCreaturePermanent("you control four or more creatures"), + ComparisonType.MORE_THAN, 3 + ); + public GrowingRitesOfItlimoc(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); @@ -30,14 +40,13 @@ public final class GrowingRitesOfItlimoc extends CardImpl { // You may reveal a creature card from among them and put it into your hand. // Put the rest on the bottom of your library in any order. this.addAbility(new EntersBattlefieldTriggeredAbility(new LookLibraryAndPickControllerEffect( - 4, 1, StaticFilters.FILTER_CARD_CREATURE_A, PutCards.HAND, PutCards.BOTTOM_ANY))); + 4, 1, StaticFilters.FILTER_CARD_CREATURE_A, PutCards.HAND, PutCards.BOTTOM_ANY + ))); // At the beginning of your end step, if you control four or more creatures, transform Growing Rites of Itlimoc. this.addAbility(new TransformAbility()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect()), - new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_CONTROLLED_A_CREATURE, ComparisonType.MORE_THAN, 3), - "At the beginning of your end step, if you control four or more creatures, transform {this}")); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect()) + .withInterveningIf(condition).addHint(CreaturesYouControlHint.instance)); } private GrowingRitesOfItlimoc(final GrowingRitesOfItlimoc card) { diff --git a/Mage.Sets/src/mage/cards/g/GruffTriplets.java b/Mage.Sets/src/mage/cards/g/GruffTriplets.java index 3cc9396f980..134ab775e69 100644 --- a/Mage.Sets/src/mage/cards/g/GruffTriplets.java +++ b/Mage.Sets/src/mage/cards/g/GruffTriplets.java @@ -3,8 +3,8 @@ package mage.cards.g; import mage.MageInt; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.SourcePermanentPowerValue; import mage.abilities.effects.CreateTokenCopySourceEffect; import mage.abilities.effects.common.counter.AddCountersAllEffect; @@ -26,14 +26,16 @@ import java.util.UUID; */ public final class GruffTriplets extends CardImpl { - private static final FilterPermanent filterNonToken = new FilterPermanent("non-token permanent"); - private static final FilterControlledPermanent filterNamedGruffTriplets = new FilterControlledPermanent("creature you control named Gruff Triplets"); + private static final FilterPermanent filterNonToken = new FilterPermanent("it isn't a token"); + private static final FilterPermanent filterNamedGruffTriplets = new FilterControlledPermanent("creature you control named Gruff Triplets"); static { filterNonToken.add(TokenPredicate.FALSE); filterNamedGruffTriplets.add(new NamePredicate("Gruff Triplets")); } + private static final Condition condition = new SourceMatchesFilterCondition(filterNonToken); + public GruffTriplets(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}{G}"); @@ -46,20 +48,13 @@ public final class GruffTriplets extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // When Gruff Triplets enters the battlefield, if it isn't a token, create two tokens that are copies of it. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new CreateTokenCopySourceEffect(2)), - new SourceMatchesFilterCondition(filterNonToken), - "When {this} enters, if it isn't a token, create two tokens that are copies of it." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenCopySourceEffect(2) + .setText("create two tokens that are copies of it")).withInterveningIf(condition)); // When Gruff Triplets dies, put a number of +1/+1 counters equal to its power on each creature you control named Gruff Triplets. - this.addAbility(new DiesSourceTriggeredAbility( - new AddCountersAllEffect( - CounterType.P1P1.createInstance(), - SourcePermanentPowerValue.NOT_NEGATIVE, - filterNamedGruffTriplets - ).setText("put a number of +1/+1 counters equal to its power on each creature you control named Gruff Triplets.") - )); + this.addAbility(new DiesSourceTriggeredAbility(new AddCountersAllEffect( + CounterType.P1P1.createInstance(), SourcePermanentPowerValue.NOT_NEGATIVE, filterNamedGruffTriplets + ).setText("put a number of +1/+1 counters equal to its power on each creature you control named Gruff Triplets"))); } private GruffTriplets(final GruffTriplets card) { diff --git a/Mage.Sets/src/mage/cards/g/GuardianOfFaith.java b/Mage.Sets/src/mage/cards/g/GuardianOfFaith.java index 4d39ff349a1..52c49e1dd2a 100644 --- a/Mage.Sets/src/mage/cards/g/GuardianOfFaith.java +++ b/Mage.Sets/src/mage/cards/g/GuardianOfFaith.java @@ -1,27 +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.effects.common.PhaseOutTargetEffect; -import mage.constants.SubType; import mage.abilities.keyword.FlashAbility; import mage.abilities.keyword.VigilanceAbility; 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.AnotherPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author weirddan455 */ public final class GuardianOfFaith extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("other target creatures you control"); + static { filter.add(AnotherPredicate.instance); } @@ -42,7 +43,7 @@ public final class GuardianOfFaith extends CardImpl { // When Guardian of Faith enters the battlefield, any number of other target creatures you control phase out. Ability ability = new EntersBattlefieldTriggeredAbility(new PhaseOutTargetEffect()); - ability.addTarget(new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, filter, false)); + ability.addTarget(new TargetPermanent(0, Integer.MAX_VALUE, filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GuardianOfTazeem.java b/Mage.Sets/src/mage/cards/g/GuardianOfTazeem.java index 686c6f475d8..e3591de4522 100644 --- a/Mage.Sets/src/mage/cards/g/GuardianOfTazeem.java +++ b/Mage.Sets/src/mage/cards/g/GuardianOfTazeem.java @@ -18,9 +18,12 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author fireshoes @@ -38,7 +41,7 @@ public final class GuardianOfTazeem extends CardImpl { // Landfall — Whenever a land enters the battlefield under you control, tap target creature an opponent controls. If that land is an Island, that creature doesn't untap during its controller's next untap step. Ability ability = new GuardianOfTazeemTriggeredAbility(); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GuardianShieldBearer.java b/Mage.Sets/src/mage/cards/g/GuardianShieldBearer.java index 949b4d244a8..7c8187d8ffd 100644 --- a/Mage.Sets/src/mage/cards/g/GuardianShieldBearer.java +++ b/Mage.Sets/src/mage/cards/g/GuardianShieldBearer.java @@ -1,6 +1,5 @@ package mage.cards.g; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.TurnedFaceUpSourceTriggeredAbility; @@ -13,16 +12,17 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.counters.CounterType; import mage.filter.StaticFilters; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class GuardianShieldBearer extends CardImpl { public GuardianShieldBearer(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.SOLDIER); this.power = new MageInt(2); @@ -33,9 +33,8 @@ public final class GuardianShieldBearer extends CardImpl { // When Guardian Shield-Bearer is turned face up, put a +1/+1 counter on another target creature you control. Ability ability = new TurnedFaceUpSourceTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), false); - ability.addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); this.addAbility(ability); - } private GuardianShieldBearer(final GuardianShieldBearer card) { diff --git a/Mage.Sets/src/mage/cards/g/GuardiansOfKoilos.java b/Mage.Sets/src/mage/cards/g/GuardiansOfKoilos.java index 56573bd9568..a2e3811ba4b 100644 --- a/Mage.Sets/src/mage/cards/g/GuardiansOfKoilos.java +++ b/Mage.Sets/src/mage/cards/g/GuardiansOfKoilos.java @@ -1,16 +1,19 @@ 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.ReturnToHandChosenControlledPermanentEffect; +import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterControlledPermanent; -import mage.filter.predicate.mageobject.HistoricPredicate; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.predicate.mageobject.HistoricPredicate; +import mage.target.TargetPermanent; + +import java.util.UUID; /** * @@ -32,8 +35,11 @@ public final class GuardiansOfKoilos extends CardImpl { this.toughness = new MageInt(4); // When Guardians of Koilos enters the battlefield, you may return another target historic permanent you control to its owner's hand. - this.addAbility(new EntersBattlefieldTriggeredAbility(new ReturnToHandChosenControlledPermanentEffect(filter) - .setText("you may return another target historic permanent you control to its owner's hand. (Artifacts, legendaries, and Sagas are historic.)"), true)); + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect() + .setText("you may return another target historic permanent you control to its owner's hand. (Artifacts, legendaries, and Sagas are historic.)"), + true); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); } private GuardiansOfKoilos(final GuardiansOfKoilos card) { diff --git a/Mage.Sets/src/mage/cards/g/GuildswornProwler.java b/Mage.Sets/src/mage/cards/g/GuildswornProwler.java index a7d63dbdbdc..6bafc744f30 100644 --- a/Mage.Sets/src/mage/cards/g/GuildswornProwler.java +++ b/Mage.Sets/src/mage/cards/g/GuildswornProwler.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.keyword.DeathtouchAbility; import mage.cards.CardImpl; @@ -35,10 +34,8 @@ public final class GuildswornProwler extends CardImpl { this.addAbility(DeathtouchAbility.getInstance()); // When Guildsworn Prowler dies, if it wasn't blocking, draw a card. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1)), - GuildswornProwlerCondition.instance, "When {this} dies, if it wasn't blocking, draw a card." - )); + this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1)) + .withInterveningIf(GuildswornProwlerCondition.instance)); } private GuildswornProwler(final GuildswornProwler card) { @@ -61,4 +58,9 @@ enum GuildswornProwlerCondition implements Condition { .map(permanent -> !BlockingOrBlockedWatcher.check(permanent, game)) .orElse(false); } -} \ No newline at end of file + + @Override + public String toString() { + return "it wasn't blocking"; + } +} diff --git a/Mage.Sets/src/mage/cards/g/GunnerConscript.java b/Mage.Sets/src/mage/cards/g/GunnerConscript.java index ecc84b5ad1a..a7f254b25e2 100644 --- a/Mage.Sets/src/mage/cards/g/GunnerConscript.java +++ b/Mage.Sets/src/mage/cards/g/GunnerConscript.java @@ -5,11 +5,8 @@ import mage.abilities.Ability; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.dynamicvalue.AdditiveDynamicValue; import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.AuraAttachedCount; -import mage.abilities.dynamicvalue.common.EquipmentAttachedCount; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.keyword.TrampleAbility; @@ -18,7 +15,9 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.AttachedToSourcePredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.JunkToken; @@ -31,6 +30,18 @@ import java.util.UUID; */ public final class GunnerConscript extends CardImpl { + private static final FilterPermanent filter = new FilterPermanent("Aura and Equipment attached to it"); + + static { + filter.add(Predicates.or( + SubType.AURA.getPredicate(), + SubType.EQUIPMENT.getPredicate() + )); + filter.add(AttachedToSourcePredicate.instance); + } + + private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter); + public GunnerConscript(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); @@ -43,20 +54,15 @@ public final class GunnerConscript extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // Gunner Conscript gets +1/+1 for each Aura and Equipment attached to it. - DynamicValue totalAmount = new AdditiveDynamicValue(new AuraAttachedCount(), new EquipmentAttachedCount()); - this.addAbility(new SimpleStaticAbility( - new BoostSourceEffect(totalAmount, totalAmount, Duration.WhileOnBattlefield) - .setText("{this} gets +1/+1 for each Aura and Equipment attached to it"))); + this.addAbility(new SimpleStaticAbility(new BoostSourceEffect(xValue, xValue, Duration.WhileOnBattlefield))); // When Gunner Conscript dies, if it was enchanted, create a Junk token. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new DiesSourceTriggeredAbility(new CreateTokenEffect(new JunkToken())), GunnerConscriptEnchantedCondition.instance, - "When Gunner Conscript dies, if it was enchanted, create a Junk token.")); + this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new JunkToken())) + .withInterveningIf(GunnerConscriptEnchantedCondition.instance)); // When Gunner Conscript dies, if it was equipped, create a Junk token. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new DiesSourceTriggeredAbility(new CreateTokenEffect(new JunkToken())), GunnerConscriptEquippedCondition.instance, - "When Gunner Conscript dies, if it was equipped, create a Junk token.")); + this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new JunkToken())) + .withInterveningIf(GunnerConscriptEquippedCondition.instance)); } private GunnerConscript(final GunnerConscript card) { @@ -84,6 +90,11 @@ enum GunnerConscriptEnchantedCondition implements Condition { .filter(Objects::nonNull) .anyMatch(permanent -> permanent.isEnchantment(game)); } + + @Override + public String toString() { + return "it was enchanted"; + } } enum GunnerConscriptEquippedCondition implements Condition { @@ -98,4 +109,9 @@ enum GunnerConscriptEquippedCondition implements Condition { .filter(Objects::nonNull) .anyMatch(attachment -> attachment.hasSubtype(SubType.EQUIPMENT, game)); } + + @Override + public String toString() { + return "it was equipped"; + } } diff --git a/Mage.Sets/src/mage/cards/g/GutlessPlunderer.java b/Mage.Sets/src/mage/cards/g/GutlessPlunderer.java index 8614b3d54cf..7f89a39080e 100644 --- a/Mage.Sets/src/mage/cards/g/GutlessPlunderer.java +++ b/Mage.Sets/src/mage/cards/g/GutlessPlunderer.java @@ -1,10 +1,8 @@ package mage.cards.g; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; import mage.abilities.hint.common.RaidHint; import mage.abilities.keyword.DeathtouchAbility; @@ -19,14 +17,13 @@ import mage.watchers.common.PlayerAttackedWatcher; import java.util.UUID; /** - * * @author ciaccona007 */ public final class GutlessPlunderer extends CardImpl { public GutlessPlunderer(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); - + this.subtype.add(SubType.SKELETON); this.subtype.add(SubType.PIRATE); this.power = new MageInt(2); @@ -36,17 +33,9 @@ public final class GutlessPlunderer extends CardImpl { this.addAbility(DeathtouchAbility.getInstance()); // Raid -- When this creature enters, if you attacked this turn, look at the top three cards of your library. You may put one of those cards back on top of your library. Put the rest into your graveyard. - Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility( - new LookLibraryAndPickControllerEffect( - 3, 1, PutCards.TOP_ANY, PutCards.GRAVEYARD, true - ) - ), RaidCondition.instance, "When this creature enters, if you attacked this turn, " - + "look at the top three cards of your library. You may " - + "put one of those cards back on top of your library. Put the rest into your graveyard." - ); - ability.setAbilityWord(AbilityWord.RAID); - ability.addHint(RaidHint.instance); - this.addAbility(ability, new PlayerAttackedWatcher()); + this.addAbility(new EntersBattlefieldTriggeredAbility(new LookLibraryAndPickControllerEffect( + 3, 1, PutCards.TOP_ANY, PutCards.GRAVEYARD, true + )).withInterveningIf(RaidCondition.instance).setAbilityWord(AbilityWord.RAID).addHint(RaidHint.instance), new PlayerAttackedWatcher()); } private GutlessPlunderer(final GutlessPlunderer card) { diff --git a/Mage.Sets/src/mage/cards/g/Gutterbones.java b/Mage.Sets/src/mage/cards/g/Gutterbones.java index b06f079c872..27615280382 100644 --- a/Mage.Sets/src/mage/cards/g/Gutterbones.java +++ b/Mage.Sets/src/mage/cards/g/Gutterbones.java @@ -7,7 +7,7 @@ import mage.abilities.condition.Condition; import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.condition.common.OpponentsLostLifeCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect; import mage.abilities.hint.common.OpponentsLostLifeHint; import mage.cards.CardImpl; @@ -40,7 +40,7 @@ public final class Gutterbones extends CardImpl { this.addAbility(new EntersBattlefieldTappedAbility()); // {1}{B}: Return Gutterbones from your graveyard to your hand. Activate this ability only during your turn and only if an opponent lost life this turn. - this.addAbility(new ConditionalActivatedAbility( + this.addAbility(new ActivateIfConditionActivatedAbility( Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(), new ManaCostsImpl<>("{1}{B}"), condition ).addHint(OpponentsLostLifeHint.instance)); diff --git a/Mage.Sets/src/mage/cards/g/GwafaHazidProfiteer.java b/Mage.Sets/src/mage/cards/g/GwafaHazidProfiteer.java index 874b272b4a3..598f25bf9f9 100644 --- a/Mage.Sets/src/mage/cards/g/GwafaHazidProfiteer.java +++ b/Mage.Sets/src/mage/cards/g/GwafaHazidProfiteer.java @@ -16,10 +16,13 @@ import mage.counters.CounterType; 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; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author jeffwadsworth */ @@ -37,7 +40,7 @@ public final class GwafaHazidProfiteer extends CardImpl { // {W}{U}, {tap}: Put a bribery counter on target creature you don't control. Its controller draws a card. Ability ability = new SimpleActivatedAbility(new AddCountersTargetEffect(CounterType.BRIBERY.createInstance()), new ManaCostsImpl<>("{W}{U}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + ability.addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); ability.addEffect(new DrawCardTargetControllerEffect(1)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/g/GwendlynDiCorci.java b/Mage.Sets/src/mage/cards/g/GwendlynDiCorci.java index 886dc073273..f57d54bd42d 100644 --- a/Mage.Sets/src/mage/cards/g/GwendlynDiCorci.java +++ b/Mage.Sets/src/mage/cards/g/GwendlynDiCorci.java @@ -6,13 +6,11 @@ import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.common.discard.DiscardTargetEffect; -import mage.abilities.hint.common.MyTurnHint; 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.target.TargetPlayer; import java.util.UUID; @@ -31,9 +29,10 @@ public final class GwendlynDiCorci extends CardImpl { this.toughness = new MageInt(5); // {T}: Target player discards a card at random. Activate this ability only during your turn. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new DiscardTargetEffect(1, true), new TapSourceCost(), MyTurnCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new DiscardTargetEffect(1, true), new TapSourceCost(), MyTurnCondition.instance + ); ability.addTarget(new TargetPlayer()); - ability.addHint(MyTurnHint.instance); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/g/GwyllionHedgeMage.java b/Mage.Sets/src/mage/cards/g/GwyllionHedgeMage.java index 06071cbaadd..5c79ce47c72 100644 --- a/Mage.Sets/src/mage/cards/g/GwyllionHedgeMage.java +++ b/Mage.Sets/src/mage/cards/g/GwyllionHedgeMage.java @@ -3,8 +3,8 @@ package mage.cards.g; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.cards.CardImpl; @@ -13,7 +13,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.SubType; import mage.counters.CounterType; -import mage.filter.common.FilterLandPermanent; +import mage.filter.common.FilterControlledPermanent; import mage.game.permanent.token.KithkinSoldierToken; import mage.target.common.TargetCreaturePermanent; @@ -24,16 +24,14 @@ import java.util.UUID; */ public final class GwyllionHedgeMage extends CardImpl { - private static final FilterLandPermanent filter = new FilterLandPermanent("Plains"); - private static final FilterLandPermanent filter2 = new FilterLandPermanent("Swamps"); - - static { - filter.add(SubType.PLAINS.getPredicate()); - filter2.add(SubType.SWAMP.getPredicate()); - } - - private static final String rule1 = "When {this} enters, if you control two or more Plains, you may create a 1/1 white Kithkin Soldier creature token."; - private static final String rule2 = "When {this} enters, if you control two or more Swamps, you may put a -1/-1 counter on target creature."; + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPermanent(SubType.PLAINS, "you control two or more Plains"), + ComparisonType.MORE_THAN, 1 + ); + private static final Condition condition2 = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPermanent(SubType.SWAMP, "you control two or more Swamps"), + ComparisonType.MORE_THAN, 1 + ); public GwyllionHedgeMage(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W/B}"); @@ -44,16 +42,12 @@ public final class GwyllionHedgeMage extends CardImpl { this.toughness = new MageInt(2); // When Gwyllion Hedge-Mage enters the battlefield, if you control two or more Plains, you may create a 1/1 white Kithkin Soldier creature token. - Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new KithkinSoldierToken()), true), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1), rule1); - this.addAbility(ability); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new KithkinSoldierToken()), true).withInterveningIf(condition)); // When Gwyllion Hedge-Mage enters the battlefield, if you control two or more Swamps, you may put a -1/-1 counter on target creature. - Ability ability2 = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new AddCountersTargetEffect(CounterType.M1M1.createInstance()), true), - new PermanentsOnTheBattlefieldCondition(filter2, ComparisonType.MORE_THAN, 1), - rule2); - ability2.addTarget(new TargetCreaturePermanent()); - this.addAbility(ability2); + Ability ability = new EntersBattlefieldTriggeredAbility(new AddCountersTargetEffect(CounterType.M1M1.createInstance()), true).withInterveningIf(condition2); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HaazdaSnareSquad.java b/Mage.Sets/src/mage/cards/h/HaazdaSnareSquad.java index c86cdfc3a12..2f017e789b4 100644 --- a/Mage.Sets/src/mage/cards/h/HaazdaSnareSquad.java +++ b/Mage.Sets/src/mage/cards/h/HaazdaSnareSquad.java @@ -14,10 +14,13 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -37,7 +40,7 @@ public final class HaazdaSnareSquad extends CardImpl { // Whenever Haazda Snare Squad attacks you may pay {W}. If you do, tap target creature an opponent controls. Ability ability = new AttacksTriggeredAbility(new DoIfCostPaid(new TapTargetEffect(), new ManaCostsImpl<>("{W}")),false, "Whenever {this} attacks, you may pay {W}. If you do, tap target creature an opponent controls."); - Target target = new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE); + Target target = new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE); ability.addTarget(target); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/h/HagHedgeMage.java b/Mage.Sets/src/mage/cards/h/HagHedgeMage.java index 3b633432287..a15f4dfc892 100644 --- a/Mage.Sets/src/mage/cards/h/HagHedgeMage.java +++ b/Mage.Sets/src/mage/cards/h/HagHedgeMage.java @@ -1,12 +1,11 @@ package mage.cards.h; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.PutOnLibraryTargetEffect; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.cards.CardImpl; @@ -14,30 +13,28 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.SubType; -import mage.filter.common.FilterLandPermanent; +import mage.filter.common.FilterControlledPermanent; import mage.target.TargetPlayer; import mage.target.common.TargetCardInYourGraveyard; +import java.util.UUID; + /** - * * @author jeffwadsworth - * */ public final class HagHedgeMage extends CardImpl { - private static final FilterLandPermanent filter = new FilterLandPermanent(); - private static final FilterLandPermanent filter2 = new FilterLandPermanent(); - - static { - filter.add(SubType.SWAMP.getPredicate()); - filter2.add(SubType.FOREST.getPredicate()); - } - - private static final String rule = "When {this} enters, if you control two or more Swamps, you may have target player discard a card."; - private static final String rule2 = "When {this} enters, if you control two or more Forests, you may put target card from your graveyard on top of your library."; + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPermanent(SubType.SWAMP, "you control two or more Swamps"), + ComparisonType.MORE_THAN, 1 + ); + private static final Condition condition2 = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPermanent(SubType.FOREST, "you control two or more Forests"), + ComparisonType.MORE_THAN, 1 + ); public HagHedgeMage(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B/G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B/G}"); this.subtype.add(SubType.HAG); this.subtype.add(SubType.SHAMAN); @@ -45,12 +42,12 @@ public final class HagHedgeMage extends CardImpl { this.toughness = new MageInt(2); // When Hag Hedge-Mage enters the battlefield, if you control two or more Swamps, you may have target player discard a card. - Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(1), true), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1), rule); + Ability ability = new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(1), true).withInterveningIf(condition); ability.addTarget(new TargetPlayer()); this.addAbility(ability); // When Hag Hedge-Mage enters the battlefield, if you control two or more Forests, you may put target card from your graveyard on top of your library. - Ability ability2 = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new PutOnLibraryTargetEffect(true), true), new PermanentsOnTheBattlefieldCondition(filter2, ComparisonType.MORE_THAN, 1), rule2); + Ability ability2 = new EntersBattlefieldTriggeredAbility(new PutOnLibraryTargetEffect(true), true).withInterveningIf(condition2); ability2.addTarget(new TargetCardInYourGraveyard()); this.addAbility(ability2); } diff --git a/Mage.Sets/src/mage/cards/h/HairStrungKoto.java b/Mage.Sets/src/mage/cards/h/HairStrungKoto.java index 9c339dd0103..01e67622f1e 100644 --- a/Mage.Sets/src/mage/cards/h/HairStrungKoto.java +++ b/Mage.Sets/src/mage/cards/h/HairStrungKoto.java @@ -1,39 +1,38 @@ package mage.cards.h; -import java.util.UUID; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapTargetCost; import mage.abilities.effects.common.MillCardsTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; +import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.permanent.TappedPredicate; import mage.target.TargetPlayer; -import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; /** - * * @author LevelX */ public final class HairStrungKoto extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); + private static final FilterControlledPermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); static { filter.add(TappedPredicate.UNTAPPED); } - public HairStrungKoto (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{6}"); + public HairStrungKoto(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}"); - /* Tap an untapped creature you control: Target player puts the top - * card of their library into their graveyard. - */ + // Tap an untapped creature you control: Target player puts the top card of their library into their graveyard. SimpleActivatedAbility ability = new SimpleActivatedAbility( new MillCardsTargetEffect(1), - new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, false))); + new TapTargetCost(StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURE) + ); ability.addTarget(new TargetPlayer()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HakbalOfTheSurgingSoul.java b/Mage.Sets/src/mage/cards/h/HakbalOfTheSurgingSoul.java index 91580715647..16665e4b411 100644 --- a/Mage.Sets/src/mage/cards/h/HakbalOfTheSurgingSoul.java +++ b/Mage.Sets/src/mage/cards/h/HakbalOfTheSurgingSoul.java @@ -1,35 +1,35 @@ package mage.cards.h; -import java.util.List; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.keyword.ExploreSourceEffect; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.Card; -import mage.constants.*; 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.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetCardInHand; -import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.List; +import java.util.UUID; /** - * * @author Grath */ public final class HakbalOfTheSurgingSoul extends CardImpl { public HakbalOfTheSurgingSoul(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{U}"); - + this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.MERFOLK); this.subtype.add(SubType.SCOUT); @@ -55,24 +55,24 @@ public final class HakbalOfTheSurgingSoul extends CardImpl { class HakbalOfTheSurgingSoulExploreEffect extends OneShotEffect { - HakbalOfTheSurgingSoulExploreEffect( ) { + private static final FilterPermanent filter = new FilterControlledCreaturePermanent(SubType.MERFOLK); + + HakbalOfTheSurgingSoulExploreEffect() { super(Outcome.Benefit); staticText = "each Merfolk creature you control explores"; } - HakbalOfTheSurgingSoulExploreEffect(HakbalOfTheSurgingSoulExploreEffect effect ) { + HakbalOfTheSurgingSoulExploreEffect(HakbalOfTheSurgingSoulExploreEffect effect) { super(effect); } @Override public boolean apply(Game game, Ability source) { - FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(SubType.MERFOLK); - List creatures = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game); Player player = game.getPlayer(source.getControllerId()); if (player != null && player.chooseUse(Outcome.AIDontUseIt, "Choose order for Merfolk to explore? (Note: You will need to set \"Auto-choose targets for player:\" to \"Off\" in Preferences.)", source, game)) { - TargetPermanent target = new TargetControlledCreaturePermanent(creatures.size(), creatures.size(), filter, true); + TargetPermanent target = new TargetPermanent(creatures.size(), creatures.size(), filter, true); target.withChooseHint("the order in which to explore (first selected will explore first)"); player.choose(outcome, target, source, game); for (UUID targetId : target.getTargets()) { diff --git a/Mage.Sets/src/mage/cards/h/HakimLoreweaver.java b/Mage.Sets/src/mage/cards/h/HakimLoreweaver.java index 6ba435e5547..f971fa8440a 100644 --- a/Mage.Sets/src/mage/cards/h/HakimLoreweaver.java +++ b/Mage.Sets/src/mage/cards/h/HakimLoreweaver.java @@ -6,7 +6,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DestroyAllEffect; import mage.abilities.keyword.FlyingAbility; @@ -53,11 +53,8 @@ public final class HakimLoreweaver extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // {U}{U}: Return target Aura card from your graveyard to the battlefield attached to Hakim, Loreweaver. Activate this ability only during your upkeep and only if Hakim isn't enchanted. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, - new HakimLoreweaverEffect(), - new ManaCostsImpl<>("{U}{U}"), - HakimLoreweaverCondition.instance + Ability ability = new ActivateIfConditionActivatedAbility( + new HakimLoreweaverEffect(), new ManaCostsImpl<>("{U}{U}"), HakimLoreweaverCondition.instance ); ability.addTarget(new TargetCardInYourGraveyard(filter)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/h/HaktosTheUnscarred.java b/Mage.Sets/src/mage/cards/h/HaktosTheUnscarred.java index dbea77aff18..170498ae371 100644 --- a/Mage.Sets/src/mage/cards/h/HaktosTheUnscarred.java +++ b/Mage.Sets/src/mage/cards/h/HaktosTheUnscarred.java @@ -106,7 +106,7 @@ enum HaktosTheUnscarredPredicate implements ObjectSourcePlayerPredicate { @Override public boolean apply(ObjectSourcePlayer input, Game game) { - Object obj = game.getState().getValue(input.getSourceId() + "" + input.getSource().getSourceObjectZoneChangeCounter() + "_haktos_number"); + Object obj = game.getState().getValue(input.getSourceId() + "" + input.getObject().getZoneChangeCounter(game) + "_haktos_number"); if (!(obj instanceof Integer)) { return false; } diff --git a/Mage.Sets/src/mage/cards/h/Halfdane.java b/Mage.Sets/src/mage/cards/h/Halfdane.java index 0271882d98f..27530170b0d 100644 --- a/Mage.Sets/src/mage/cards/h/Halfdane.java +++ b/Mage.Sets/src/mage/cards/h/Halfdane.java @@ -15,6 +15,7 @@ import mage.filter.predicate.mageobject.AnotherPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -40,7 +41,7 @@ public final class Halfdane extends CardImpl { // At the beginning of your upkeep, change Halfdane's base power and toughness to the power and toughness of target creature other than Halfdane until the end of your next upkeep. Ability ability = new BeginningOfUpkeepTriggeredAbility(new HalfdaneUpkeepEffect()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HallOfOracles.java b/Mage.Sets/src/mage/cards/h/HallOfOracles.java index 6a502314ffa..39ecd74e32a 100644 --- a/Mage.Sets/src/mage/cards/h/HallOfOracles.java +++ b/Mage.Sets/src/mage/cards/h/HallOfOracles.java @@ -5,7 +5,7 @@ import mage.abilities.ActivatedAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.mana.AnyColorManaAbility; import mage.abilities.mana.ColorlessManaAbility; @@ -13,7 +13,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.TimingRule; -import mage.constants.Zone; import mage.counters.CounterType; import mage.game.Game; import mage.target.common.TargetCreaturePermanent; @@ -39,13 +38,11 @@ public final class HallOfOracles extends CardImpl { this.addAbility(ability); // {T}: Put a +1/+1 counter on target creature. Activate only as a sorcery and only if you've cast an instant or sorcery spell this turn. - ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.P1P1.createInstance()), new TapSourceCost(), - HallOfOraclesCondition.instance, "{T}: Put a +1/+1 counter on target creature. " + - "Activate only as a sorcery and only if you've cast an instant or sorcery spell this turn." - ); + ability = new ActivateIfConditionActivatedAbility( + new AddCountersTargetEffect(CounterType.P1P1.createInstance()), + new TapSourceCost(), HallOfOraclesCondition.instance + ).setTiming(TimingRule.SORCERY); ability.addTarget(new TargetCreaturePermanent()); - ability.setTiming(TimingRule.SORCERY); this.addAbility(ability); } @@ -71,4 +68,9 @@ enum HallOfOraclesCondition implements Condition { .filter(Objects::nonNull) .anyMatch(spell -> spell.isInstantOrSorcery(game)); } + + @Override + public String toString() { + return "you've cast an instant or sorcery spell this turn"; + } } diff --git a/Mage.Sets/src/mage/cards/h/HallowedHealer.java b/Mage.Sets/src/mage/cards/h/HallowedHealer.java index 21a746202e7..5987a2c528e 100644 --- a/Mage.Sets/src/mage/cards/h/HallowedHealer.java +++ b/Mage.Sets/src/mage/cards/h/HallowedHealer.java @@ -5,7 +5,7 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.ThresholdCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.PreventDamageToTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -37,7 +37,7 @@ public final class HallowedHealer extends CardImpl { this.addAbility(ability); // Threshold - {tap}: Prevent the next 4 damage that would be dealt to any target this turn. Activate this ability only if seven or more cards are in your graveyard. - Ability thresholdAbility = new ConditionalActivatedAbility( + Ability thresholdAbility = new ActivateIfConditionActivatedAbility( new PreventDamageToTargetEffect(Duration.EndOfTurn, 4), new TapSourceCost(), ThresholdCondition.instance ); diff --git a/Mage.Sets/src/mage/cards/h/HallowedMoonlight.java b/Mage.Sets/src/mage/cards/h/HallowedMoonlight.java index 91b3fd9046a..21e73944f51 100644 --- a/Mage.Sets/src/mage/cards/h/HallowedMoonlight.java +++ b/Mage.Sets/src/mage/cards/h/HallowedMoonlight.java @@ -48,7 +48,7 @@ class HallowedMoonlightEffect extends ReplacementEffectImpl { HallowedMoonlightEffect() { super(Duration.EndOfTurn, Outcome.Exile); - staticText = "Until end of turn, if a creature would enter the battlefield and it wasn't cast, exile it instead"; + staticText = "Until end of turn, if a creature would enter and it wasn't cast, exile it instead"; } private HallowedMoonlightEffect(final HallowedMoonlightEffect effect) { diff --git a/Mage.Sets/src/mage/cards/h/HallowedRespite.java b/Mage.Sets/src/mage/cards/h/HallowedRespite.java index 62cc4fff36e..8097408ce27 100644 --- a/Mage.Sets/src/mage/cards/h/HallowedRespite.java +++ b/Mage.Sets/src/mage/cards/h/HallowedRespite.java @@ -17,6 +17,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -37,7 +38,7 @@ public final class HallowedRespite extends CardImpl { // Exile target nonlegendary creature, then return it to the battlefield under its owner's control. If it entered under your control, put a +1/+1 counter on it. Otherwise, tap it. this.getSpellAbility().addEffect(new ExileThenReturnTargetEffect(false, false)); this.getSpellAbility().addEffect(new HallowedRespiteEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // Flashback {1}{W}{U} this.addAbility(new FlashbackAbility(this, new ManaCostsImpl<>("{1}{W}{U}"))); diff --git a/Mage.Sets/src/mage/cards/h/HaloHunter.java b/Mage.Sets/src/mage/cards/h/HaloHunter.java index bb60c987e06..f57522afc48 100644 --- a/Mage.Sets/src/mage/cards/h/HaloHunter.java +++ b/Mage.Sets/src/mage/cards/h/HaloHunter.java @@ -12,6 +12,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -35,7 +36,7 @@ public final class HaloHunter extends CardImpl { this.addAbility(IntimidateAbility.getInstance()); Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HammerJammer.java b/Mage.Sets/src/mage/cards/h/HammerJammer.java index 03599290a08..41d3a1e146a 100644 --- a/Mage.Sets/src/mage/cards/h/HammerJammer.java +++ b/Mage.Sets/src/mage/cards/h/HammerJammer.java @@ -1,10 +1,9 @@ - package mage.cards.h; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect; import mage.cards.CardImpl; @@ -38,7 +37,7 @@ public final class HammerJammer extends CardImpl { this.toughness = new MageInt(0); // As Hammer Jammer enters the battlefield, roll a six-sided die. Hammer Jammer enters the battlefield with a number of +1/+1 counters on it equal to the result. - this.addAbility(new EntersBattlefieldAbility(new HammerJammerEntersEffect(CounterType.P1P1.createInstance()))); + this.addAbility(new AsEntersBattlefieldAbility(new HammerJammerEntersEffect(CounterType.P1P1.createInstance()))); // Whenever you roll a die, remove all +1/+1 counters from Hammer Jammer, then put a number of +1/+1 counters on it equal to the result. this.addAbility(new HammerJammerTriggeredAbility()); @@ -59,9 +58,10 @@ class HammerJammerEntersEffect extends EntersBattlefieldWithXCountersEffect { HammerJammerEntersEffect(Counter counter) { super(counter); + staticText = "roll a six-sided die. {this} enters with a number of +1/+1 counters on it equal to the result"; } - public HammerJammerEntersEffect(EntersBattlefieldWithXCountersEffect effect) { + private HammerJammerEntersEffect(EntersBattlefieldWithXCountersEffect effect) { super(effect); } @@ -86,7 +86,7 @@ class HammerJammerEntersEffect extends EntersBattlefieldWithXCountersEffect { class HammerJammerTriggeredAbility extends TriggeredAbilityImpl { - public HammerJammerTriggeredAbility() { + HammerJammerTriggeredAbility() { super(Zone.BATTLEFIELD, new HammerJammerEffect(), false); setTriggerPhrase("Whenever you roll a die, "); } diff --git a/Mage.Sets/src/mage/cards/h/HammerOfBogardan.java b/Mage.Sets/src/mage/cards/h/HammerOfBogardan.java index 5afd779f585..f79470a03de 100644 --- a/Mage.Sets/src/mage/cards/h/HammerOfBogardan.java +++ b/Mage.Sets/src/mage/cards/h/HammerOfBogardan.java @@ -1,37 +1,35 @@ - package mage.cards.h; -import java.util.UUID; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.PhaseStep; import mage.constants.Zone; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** - * * @author jeffwadsworth - * */ public final class HammerOfBogardan extends CardImpl { public HammerOfBogardan(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{R}{R}"); - + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{R}{R}"); // Hammer of Bogardan deals 3 damage to any target. this.getSpellAbility().addEffect(new DamageTargetEffect(3)); this.getSpellAbility().addTarget(new TargetAnyTarget()); // {2}{R}{R}{R}: Return Hammer of Bogardan from your graveyard to your hand. Activate this ability only during your upkeep. - this.addAbility(new ConditionalActivatedAbility(Zone.GRAVEYARD, - new ReturnSourceFromGraveyardToHandEffect(), new ManaCostsImpl<>("{2}{R}{R}{R}"), new IsStepCondition(PhaseStep.UPKEEP), null)); + this.addAbility(new ActivateIfConditionActivatedAbility( + Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(), + new ManaCostsImpl<>("{2}{R}{R}{R}"), IsStepCondition.getMyUpkeep() + )); } private HammerOfBogardan(final HammerOfBogardan card) { diff --git a/Mage.Sets/src/mage/cards/h/HammerheadCorvette.java b/Mage.Sets/src/mage/cards/h/HammerheadCorvette.java index 15158821bf1..2d3bd991552 100644 --- a/Mage.Sets/src/mage/cards/h/HammerheadCorvette.java +++ b/Mage.Sets/src/mage/cards/h/HammerheadCorvette.java @@ -16,6 +16,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.DefendingPlayerControlsSourceAttackingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -47,7 +48,7 @@ public final class HammerheadCorvette extends CardImpl { Ability ability = new AttacksTriggeredAbility(effect1, true, "Whenever {this} attacks, you may uptap target Starship creature defending player controls and have that creature block {this} this turn if able"); ability.addEffect(effect2); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HammerheimDeadeye.java b/Mage.Sets/src/mage/cards/h/HammerheimDeadeye.java index fde29bbccc2..dcd68bafae4 100644 --- a/Mage.Sets/src/mage/cards/h/HammerheimDeadeye.java +++ b/Mage.Sets/src/mage/cards/h/HammerheimDeadeye.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class HammerheimDeadeye extends CardImpl { this.addAbility(new EchoAbility("{5}{R}")); // When Hammerheim Deadeye enters the battlefield, destroy target creature with flying. Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()); - Target target = new TargetCreaturePermanent(filter); + Target target = new TargetPermanent(filter); ability.addTarget(target); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HanSolo.java b/Mage.Sets/src/mage/cards/h/HanSolo.java index fe7d6413af0..e8f427eb6e0 100644 --- a/Mage.Sets/src/mage/cards/h/HanSolo.java +++ b/Mage.Sets/src/mage/cards/h/HanSolo.java @@ -13,6 +13,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -46,7 +47,7 @@ public final class HanSolo extends CardImpl { effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn); effect.setText("and gains haste until end of turn"); ability.addEffect(effect); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HanSoloScrumrat.java b/Mage.Sets/src/mage/cards/h/HanSoloScrumrat.java index b0b9a81407d..5baa79e3b64 100644 --- a/Mage.Sets/src/mage/cards/h/HanSoloScrumrat.java +++ b/Mage.Sets/src/mage/cards/h/HanSoloScrumrat.java @@ -1,33 +1,34 @@ package mage.cards.h; -import java.util.UUID; import mage.MageInt; -import mage.abilities.*; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.PartnerWithAbility; -import mage.constants.*; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.*; 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.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author NinthWorld */ public final class HanSoloScrumrat extends CardImpl { public HanSoloScrumrat(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); - + this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.ROGUE); @@ -38,11 +39,13 @@ public final class HanSoloScrumrat extends CardImpl { this.addAbility(new PartnerWithAbility("Chewbacca, the Beast")); // R: Han Solo, Scrumrat gains first strike until end of turn. - this.addAbility(new SimpleActivatedAbility(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{R}"))); + this.addAbility(new SimpleActivatedAbility(new GainAbilitySourceEffect( + FirstStrikeAbility.getInstance(), Duration.EndOfTurn + ), new ManaCostsImpl<>("{R}"))); // Whenever Han Solo, Scrumrat deals damage during your turn, put a +1/+1 counter on another target creature you control. Ability ability = new HanSoloScrumratTriggeredAbility(); - ability.addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); this.addAbility(ability); } @@ -75,7 +78,7 @@ class HanSoloScrumratTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkEventType(GameEvent event, Game game) { return event.getType() == GameEvent.EventType.DAMAGED_PERMANENT - || event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + || event.getType() == GameEvent.EventType.DAMAGED_PLAYER; } @Override diff --git a/Mage.Sets/src/mage/cards/h/HandOfDeath.java b/Mage.Sets/src/mage/cards/h/HandOfDeath.java index 91abfc5034b..7d3920722dd 100644 --- a/Mage.Sets/src/mage/cards/h/HandOfDeath.java +++ b/Mage.Sets/src/mage/cards/h/HandOfDeath.java @@ -6,8 +6,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author anonymous @@ -18,7 +21,7 @@ public final class HandOfDeath extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{B}"); // Destroy target nonblack creature. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); } diff --git a/Mage.Sets/src/mage/cards/h/HandOfJustice.java b/Mage.Sets/src/mage/cards/h/HandOfJustice.java index 251edadb036..d3a534e4fb1 100644 --- a/Mage.Sets/src/mage/cards/h/HandOfJustice.java +++ b/Mage.Sets/src/mage/cards/h/HandOfJustice.java @@ -1,7 +1,5 @@ - package mage.cards.h; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; import mage.abilities.Ability; @@ -13,20 +11,20 @@ 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.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class HandOfJustice extends CardImpl { - - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped white creatures you control"); + + private static final FilterControlledPermanent filter = new FilterControlledCreaturePermanent("untapped white creatures you control"); static { filter.add(new ColorPredicate(ObjectColor.WHITE)); @@ -34,14 +32,14 @@ public final class HandOfJustice extends CardImpl { } public HandOfJustice(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.AVATAR); this.power = new MageInt(2); this.toughness = new MageInt(6); // {tap}, Tap three untapped white creatures you control: Destroy target creature. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new TapSourceCost()); - ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(3, 3, filter, true))); + ability.addCost(new TapTargetCost(3, filter)); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HandsOfBinding.java b/Mage.Sets/src/mage/cards/h/HandsOfBinding.java index 78aa695dd1a..a66e57c01f7 100644 --- a/Mage.Sets/src/mage/cards/h/HandsOfBinding.java +++ b/Mage.Sets/src/mage/cards/h/HandsOfBinding.java @@ -8,8 +8,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author Plopman @@ -22,7 +25,7 @@ public final class HandsOfBinding extends CardImpl { //Tap target creature an opponent controls. That creature doesn't untap during its controller's next untap step. this.getSpellAbility().addEffect(new TapTargetEffect()); this.getSpellAbility().addEffect(new DontUntapInControllersNextUntapStepTargetEffect("that creature")); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); //Cipher this.getSpellAbility().addEffect(new CipherEffect()); } diff --git a/Mage.Sets/src/mage/cards/h/HanweirBattlements.java b/Mage.Sets/src/mage/cards/h/HanweirBattlements.java index bbb155ab7fe..16d1e5b3881 100644 --- a/Mage.Sets/src/mage/cards/h/HanweirBattlements.java +++ b/Mage.Sets/src/mage/cards/h/HanweirBattlements.java @@ -2,11 +2,8 @@ package mage.cards.h; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.condition.Condition; -import mage.abilities.condition.common.MeldCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; import mage.abilities.effects.common.MeldEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.HasteAbility; @@ -15,7 +12,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Zone; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -25,8 +21,6 @@ import java.util.UUID; */ public final class HanweirBattlements extends CardImpl { - private static final Condition condition = new MeldCondition("Hanweir Garrison"); - public HanweirBattlements(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); @@ -36,7 +30,7 @@ public final class HanweirBattlements extends CardImpl { // {T}: Add {C}. this.addAbility(new ColorlessManaAbility()); - // {R},{T}: Target creature gains haste until end of turn. + // {R}, {T}: Target creature gains haste until end of turn. Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect( HasteAbility.getInstance(), Duration.EndOfTurn ), new ManaCostsImpl<>("{R}")); @@ -44,11 +38,12 @@ public final class HanweirBattlements extends CardImpl { ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); - // {3}{R}{R},{T}: If you both own and control Hanweir Battlements and a creature named Hanweir Garrison, exile them, then meld them into Hanweir, the Writhing Township. - ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, new MeldEffect("Hanweir Garrison", "Hanweir, the Writhing Township"), - new ManaCostsImpl<>("{3}{R}{R}"), condition, "{3}{R}{R}, {T}: If you both own and control {this} " + - "and a creature named Hanweir Garrison, exile them, then meld them into Hanweir, the Writhing Township." + // {3}{R}{R}, {T}: If you both own and control Hanweir Battlements and a creature named Hanweir Garrison, exile them, then meld them into Hanweir, the Writhing Township. + ability = new SimpleActivatedAbility( + new MeldEffect("Hanweir Garrison", "Hanweir, the Writhing Township") + .setText("if you both own and control {this} and a creature named Hanweir Garrison, " + + "exile them, then meld them into Hanweir, the Writhing Township"), + new ManaCostsImpl<>("{3}{R}{R}") ); ability.addCost(new TapSourceCost()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/h/HanweirMilitiaCaptain.java b/Mage.Sets/src/mage/cards/h/HanweirMilitiaCaptain.java index 2ae81956b58..a6bb769ba9c 100644 --- a/Mage.Sets/src/mage/cards/h/HanweirMilitiaCaptain.java +++ b/Mage.Sets/src/mage/cards/h/HanweirMilitiaCaptain.java @@ -1,27 +1,30 @@ - package mage.cards.h; -import java.util.UUID; - import mage.MageInt; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.hint.common.CreaturesYouControlHint; import mage.abilities.keyword.TransformAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.ComparisonType; +import mage.constants.SubType; import mage.filter.common.FilterControlledCreaturePermanent; +import java.util.UUID; + /** * @author fireshoes */ public final class HanweirMilitiaCaptain extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("if you control four or more creatures"); + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledCreaturePermanent("you control four or more creatures"), + ComparisonType.MORE_THAN, 3 + ); public HanweirMilitiaCaptain(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); @@ -34,10 +37,8 @@ public final class HanweirMilitiaCaptain extends CardImpl { // At the beginning of your upkeep, if you control four or more creatures, transform Hanweir Militia Captain. this.addAbility(new TransformAbility()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect()), - new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 3), - "At the beginning of your upkeep, if you control four or more creatures, transform {this}")); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect()) + .withInterveningIf(condition).addHint(CreaturesYouControlHint.instance)); } private HanweirMilitiaCaptain(final HanweirMilitiaCaptain card) { diff --git a/Mage.Sets/src/mage/cards/h/HaphazardBombardment.java b/Mage.Sets/src/mage/cards/h/HaphazardBombardment.java index 8c64f38d7cb..6c4e09e2e5d 100644 --- a/Mage.Sets/src/mage/cards/h/HaphazardBombardment.java +++ b/Mage.Sets/src/mage/cards/h/HaphazardBombardment.java @@ -1,14 +1,12 @@ package mage.cards.h; -import java.util.List; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.IndestructibleAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -25,12 +23,26 @@ import mage.players.Player; import mage.target.TargetPermanent; import mage.util.RandomUtil; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; + /** - * * @author LevelX2 */ public final class HaphazardBombardment extends CardImpl { + private static final FilterPermanent filter = new FilterPermanent("if two or more permanents you don't control have an aim counter on them"); + + static { + filter.add(TargetController.NOT_YOU.getControllerPredicate()); + filter.add(CounterType.AIM.getPredicate()); + } + + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1); + public HaphazardBombardment(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{5}{R}"); @@ -38,12 +50,7 @@ public final class HaphazardBombardment extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new HaphazardBombardmentEffect(), false)); // At the beginning of your end step, if two or more permanents you don't control have an aim counter on them, destroy one of those permanents at random. - FilterPermanent filter = new FilterPermanent("if two or more permanents you don't control have an aim counter on them"); - filter.add(TargetController.NOT_YOU.getControllerPredicate()); - filter.add(CounterType.AIM.getPredicate()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfEndStepTriggeredAbility(new HaphazardBombardmentEndOfTurnEffect()), - new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1, false), - "At the beginning of your end step, if two or more permanents you don't control have an aim counter on them, destroy one of those permanents at random")); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new HaphazardBombardmentEndOfTurnEffect()).withInterveningIf(condition)); } private HaphazardBombardment(final HaphazardBombardment card) { @@ -58,6 +65,13 @@ public final class HaphazardBombardment extends CardImpl { class HaphazardBombardmentEffect extends OneShotEffect { + private static final FilterPermanent filter = new FilterPermanent("nonenchantment permanents you don't control"); + + static { + filter.add(Predicates.not(CardType.ENCHANTMENT.getPredicate())); + filter.add(TargetController.NOT_YOU.getControllerPredicate()); + } + HaphazardBombardmentEffect() { super(Outcome.Benefit); this.staticText = "choose four nonenchantment permanents you don't control and put an aim counter on each of them"; @@ -75,34 +89,43 @@ class HaphazardBombardmentEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - FilterPermanent filter = new FilterPermanent("nonenchantment permanents you don't control"); - filter.add(Predicates.not(CardType.ENCHANTMENT.getPredicate())); - filter.add(TargetController.OPPONENT.getControllerPredicate()); - List permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game); - if (permanents.size() > 4) { - permanents.clear(); - TargetPermanent target = new TargetPermanent(4, 4, filter, true); - controller.chooseTarget(outcome, target, source, game); - for (UUID targetId : target.getTargets()) { - Permanent permanent = game.getPermanent(targetId); - if (permanent != null) { - permanents.add(permanent); - } - } - } - for (Permanent permanent : permanents) { - permanent.addCounters(CounterType.AIM.createInstance(), source.getControllerId(), source, game); - } - return true; - + if (controller == null) { + return false; } - return false; + List permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game); + if (permanents.size() > 4) { + permanents.clear(); + TargetPermanent target = new TargetPermanent(4, 4, filter, true); + controller.chooseTarget(outcome, target, source, game); + permanents.addAll( + target.getTargets() + .stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .collect(Collectors.toList()) + ); + } + for (Permanent permanent : permanents) { + permanent.addCounters(CounterType.AIM.createInstance(), source.getControllerId(), source, game); + } + return true; + } } class HaphazardBombardmentEndOfTurnEffect extends OneShotEffect { + private static final FilterPermanent filter = new FilterPermanent(); + + static { + filter.add(TargetController.NOT_YOU.getControllerPredicate()); + filter.add(CounterType.AIM.getPredicate()); + // 4/27/2018 If one or more of the permanents with aim counters on them have indestructible, + // select the permanent destroyed at random from among the permanents with aim counters + // that don't have indestructible. + filter.add(Predicates.not(new AbilityPredicate(IndestructibleAbility.class))); + } + HaphazardBombardmentEndOfTurnEffect() { super(Outcome.Benefit); this.staticText = "destroy one of those permanents at random"; @@ -119,21 +142,12 @@ class HaphazardBombardmentEndOfTurnEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - - // 4/27/2018 If one or more of the permanents with aim counters on them have indestructible, - // select the permanent destroyed at random from among the permanents with aim counters - // that don't have indestructible. - FilterPermanent filter = new FilterPermanent("if two or more permanents you don't control have an aim counter on them"); - filter.add(TargetController.NOT_YOU.getControllerPredicate()); - filter.add(CounterType.AIM.getPredicate()); - filter.add(Predicates.not(new AbilityPredicate(IndestructibleAbility.class))); - List permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game); - if (!permanents.isEmpty()) { - Permanent permanent = permanents.get(RandomUtil.nextInt(permanents.size())); - if (permanent != null) { - permanent.destroy(source, game, false); - } - } - return true; + return Optional.ofNullable( + game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game) + ) + .filter(p -> !p.isEmpty()) + .map(RandomUtil::randomFromCollection) + .filter(permanent -> permanent.destroy(source, game)) + .isPresent(); } } diff --git a/Mage.Sets/src/mage/cards/h/HappilyEverAfter.java b/Mage.Sets/src/mage/cards/h/HappilyEverAfter.java index 995c71abb29..544db48f69c 100644 --- a/Mage.Sets/src/mage/cards/h/HappilyEverAfter.java +++ b/Mage.Sets/src/mage/cards/h/HappilyEverAfter.java @@ -2,23 +2,21 @@ package mage.cards.h; import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardAllEffect; +import mage.abilities.effects.common.GainLifeAllEffect; import mage.abilities.effects.common.WinGameSourceControllerEffect; import mage.abilities.hint.Hint; import mage.abilities.hint.HintUtils; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.*; -import java.util.List; /** * @author TheElk801 @@ -29,20 +27,16 @@ public final class HappilyEverAfter extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}"); // When Happily Ever After enters the battlefield, each player gains 5 life and draws a card. - this.addAbility(new EntersBattlefieldTriggeredAbility(new HappilyEverAfterEffect())); + Ability ability = new EntersBattlefieldTriggeredAbility(new GainLifeAllEffect(5)); + ability.addEffect(new DrawCardAllEffect(1).setText("and draws a card")); + this.addAbility(ability); // At the beginning of your upkeep, if there are five colors among permanents you control, there are six or more card types among permanents you control and/or cards in your graveyard, and your life total is greater than or equal to your starting life total, you win the game. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility( - new WinGameSourceControllerEffect(), false - ), HappilyEverAfterCondition.instance, "At the beginning of your upkeep, " + - "if there are five colors among permanents you control, there are six or more card types " + - "among permanents you control and/or cards in your graveyard, and your life total is " + - "greater than or equal to your starting life total, you win the game.") + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect()) + .withInterveningIf(HappilyEverAfterCondition.instance) .addHint(HappilyEverAfterColorHint.instance) .addHint(HappilyEverAfterCardTypeHint.instance) - .addHint(HappilyEverAfterLifeHint.instance) - ); + .addHint(HappilyEverAfterLifeHint.instance)); } private HappilyEverAfter(final HappilyEverAfter card) { @@ -55,37 +49,6 @@ public final class HappilyEverAfter extends CardImpl { } } -class HappilyEverAfterEffect extends OneShotEffect { - - HappilyEverAfterEffect() { - super(Outcome.GainLife); - staticText = "each player gains 5 life and draws a card"; - } - - private HappilyEverAfterEffect(final HappilyEverAfterEffect effect) { - super(effect); - } - - @Override - public HappilyEverAfterEffect copy() { - return new HappilyEverAfterEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - game.getState() - .getPlayersInRange(source.getControllerId(), game) - .stream() - .map(game::getPlayer) - .filter(Objects::nonNull) - .forEachOrdered(player -> { - player.gainLife(5, game, source); - player.drawCards(1, source, game); - }); - return true; - } -} - enum HappilyEverAfterCondition implements Condition { instance; @@ -122,6 +85,13 @@ enum HappilyEverAfterCondition implements Condition { .forEach(cardTypeEnumSet::add); return cardTypeEnumSet.size() >= 6; } + + @Override + public String toString() { + return "there are five colors among permanents you control, " + + "there are six or more card types among permanents you control and/or cards in your graveyard, " + + "and your life total is greater than or equal to your starting life total"; + } } enum HappilyEverAfterColorHint implements Hint { diff --git a/Mage.Sets/src/mage/cards/h/HarbingerOfTheTides.java b/Mage.Sets/src/mage/cards/h/HarbingerOfTheTides.java index 3f6d28d94fa..64fde8b543d 100644 --- a/Mage.Sets/src/mage/cards/h/HarbingerOfTheTides.java +++ b/Mage.Sets/src/mage/cards/h/HarbingerOfTheTides.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -42,7 +43,7 @@ public final class HarbingerOfTheTides extends CardImpl { // When Harbinger of the Tides enters the battlefield, you may return target tapped creature an opponent controls to its owner's hand. Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HarmoniousGrovestrider.java b/Mage.Sets/src/mage/cards/h/HarmoniousGrovestrider.java new file mode 100644 index 00000000000..1c233b124ec --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HarmoniousGrovestrider.java @@ -0,0 +1,44 @@ +package mage.cards.h; + +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.LandsYouControlCount; +import mage.abilities.effects.common.continuous.SetBasePowerToughnessSourceEffect; +import mage.abilities.keyword.WardAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class HarmoniousGrovestrider extends CardImpl { + + public HarmoniousGrovestrider(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}"); + + this.subtype.add(SubType.BEAST); + this.power = new MageInt(0); + this.toughness = new MageInt(0); + + // Ward {2} + this.addAbility(new WardAbility(new ManaCostsImpl<>("{2}"))); + + // This creature's power and toughness are each equal to the number of lands you control. + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetBasePowerToughnessSourceEffect(LandsYouControlCount.instance))); + } + + private HarmoniousGrovestrider(final HarmoniousGrovestrider card) { + super(card); + } + + @Override + public HarmoniousGrovestrider copy() { + return new HarmoniousGrovestrider(this); + } +} diff --git a/Mage.Sets/src/mage/cards/h/HarnessTheStorm.java b/Mage.Sets/src/mage/cards/h/HarnessTheStorm.java index 2f5fe12510c..a6c20b27723 100644 --- a/Mage.Sets/src/mage/cards/h/HarnessTheStorm.java +++ b/Mage.Sets/src/mage/cards/h/HarnessTheStorm.java @@ -1,38 +1,43 @@ package mage.cards.h; -import mage.ApprovingObject; import mage.abilities.Ability; import mage.abilities.common.SpellCastControllerTriggeredAbility; -import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; +import mage.abilities.effects.common.MayCastTargetCardEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; +import mage.constants.SetTargetPointer; +import mage.constants.Zone; import mage.filter.FilterCard; -import mage.filter.common.FilterInstantOrSorcerySpell; +import mage.filter.StaticFilters; import mage.filter.predicate.mageobject.NamePredicate; import mage.game.Game; -import mage.game.events.GameEvent; import mage.game.stack.Spell; -import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; -import mage.watchers.common.CastFromHandWatcher; +import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetpointer.FirstTargetPointer; import java.util.UUID; /** - * * @author LevelX2 */ public final class HarnessTheStorm extends CardImpl { + private static final FilterCard filter = new FilterCard("card with the same name as that spell from your graveyard"); + public HarnessTheStorm(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); // Whenever you cast an instant or sorcery spell from your hand, you may cast // target card with the same name as that spell from your graveyard. - this.addAbility(new HarnessTheStormTriggeredAbility(), new CastFromHandWatcher()); + Ability ability = new SpellCastControllerTriggeredAbility( + Zone.BATTLEFIELD, new MayCastTargetCardEffect(false), StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, + false, SetTargetPointer.SPELL, Zone.HAND + ); + ability.addTarget(new TargetCardInYourGraveyard(filter)); // Only used for text generation + ability.setTargetAdjuster(HarnessTheStormAdjuster.instance); + this.addAbility(ability); } private HarnessTheStorm(final HarnessTheStorm card) { @@ -46,77 +51,21 @@ public final class HarnessTheStorm extends CardImpl { } -class HarnessTheStormTriggeredAbility extends SpellCastControllerTriggeredAbility { - - private static final FilterInstantOrSorcerySpell filterSpell = new FilterInstantOrSorcerySpell("an instant or sorcery spell from your hand"); - - HarnessTheStormTriggeredAbility() { - super(new HarnessTheStormEffect(), filterSpell, false); - } - - private HarnessTheStormTriggeredAbility(final HarnessTheStormTriggeredAbility ability) { - super(ability); - } +enum HarnessTheStormAdjuster implements TargetAdjuster { + instance; @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (super.checkTrigger(event, game)) { - CastFromHandWatcher watcher = game.getState().getWatcher(CastFromHandWatcher.class); - if (watcher != null && watcher.spellWasCastFromHand(event.getSourceId())) { - Spell spell = game.getState().getStack().getSpell(event.getSourceId()); - if (spell != null) { - FilterCard filterCard = new FilterCard("a card named " + spell.getName() + " in your graveyard"); - filterCard.add(new NamePredicate(spell.getName())); - this.getTargets().clear(); - this.getTargets().add(new TargetCardInYourGraveyard(filterCard)); - return true; - } - } + public void adjustTargets(Ability ability, Game game) { + UUID spellId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability); + ability.getTargets().clear(); + ability.getAllEffects().setTargetPointer(new FirstTargetPointer()); + + Spell spell = game.getSpellOrLKIStack(spellId); + if (spell == null) { + return; } - return false; - } - - @Override - public HarnessTheStormTriggeredAbility copy() { - return new HarnessTheStormTriggeredAbility(this); - } - -} - -class HarnessTheStormEffect extends OneShotEffect { - - HarnessTheStormEffect() { - super(Outcome.Benefit); - this.staticText = "you may cast target card with the same name as that " - + "spell from your graveyard. (You still pay its costs.)"; - } - - private HarnessTheStormEffect(final HarnessTheStormEffect effect) { - super(effect); - } - - @Override - public HarnessTheStormEffect copy() { - return new HarnessTheStormEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller == null) { - return false; - } - Card card = controller.getGraveyard().get(getTargetPointer().getFirst(game, source), game); - if (card == null) { - return false; - } - if (controller.chooseUse(outcome, "Cast " + card.getIdName() + " from your graveyard?", source, game)) { - game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE); - controller.cast(controller.chooseAbilityForCast(card, game, false), - game, false, new ApprovingObject(source, game)); - game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null); - } - return true; - + FilterCard filter = new FilterCard("a card named " + spell.getName() + " in your graveyard"); + filter.add(new NamePredicate(spell.getName())); + ability.addTarget(new TargetCardInYourGraveyard(filter)); } } diff --git a/Mage.Sets/src/mage/cards/h/HarvesttideSentry.java b/Mage.Sets/src/mage/cards/h/HarvesttideSentry.java index cfb0164577f..6d63232e5ac 100644 --- a/Mage.Sets/src/mage/cards/h/HarvesttideSentry.java +++ b/Mage.Sets/src/mage/cards/h/HarvesttideSentry.java @@ -1,11 +1,10 @@ package mage.cards.h; import mage.MageInt; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.condition.common.CovenCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; import mage.abilities.hint.common.CovenHint; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -19,7 +18,7 @@ import java.util.UUID; */ public final class HarvesttideSentry extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures with power 2 or less"); static { filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 3)); @@ -34,13 +33,9 @@ public final class HarvesttideSentry extends CardImpl { this.toughness = new MageInt(1); // Coven — At the beginning of combat on your turn, if you control three or more creatures with different powers, Harvesttide Sentry can't be blocked by creatures with power 2 or less this turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility( - new CantBeBlockedByCreaturesSourceEffect(filter, Duration.EndOfTurn) - ), CovenCondition.instance, "At the beginning of combat on your turn, " + - "if you control three or more creatures with different powers, " + - "{this} can't be blocked by creatures with power 2 or less this turn." - ).addHint(CovenHint.instance).setAbilityWord(AbilityWord.COVEN)); + this.addAbility(new BeginningOfCombatTriggeredAbility( + new CantBeBlockedByCreaturesSourceEffect(filter, Duration.EndOfTurn) + ).withInterveningIf(CovenCondition.instance).addHint(CovenHint.instance).setAbilityWord(AbilityWord.COVEN)); } private HarvesttideSentry(final HarvesttideSentry card) { diff --git a/Mage.Sets/src/mage/cards/h/HateWeaver.java b/Mage.Sets/src/mage/cards/h/HateWeaver.java index feccdddab81..362ea023329 100644 --- a/Mage.Sets/src/mage/cards/h/HateWeaver.java +++ b/Mage.Sets/src/mage/cards/h/HateWeaver.java @@ -17,6 +17,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -41,7 +42,7 @@ public final class HateWeaver extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(1, 0, Duration.EndOfTurn), new GenericManaCost(2)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HauntOfTheDeadMarshes.java b/Mage.Sets/src/mage/cards/h/HauntOfTheDeadMarshes.java index 8d38f3ac5d6..f587b2cfd43 100644 --- a/Mage.Sets/src/mage/cards/h/HauntOfTheDeadMarshes.java +++ b/Mage.Sets/src/mage/cards/h/HauntOfTheDeadMarshes.java @@ -5,7 +5,7 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; import mage.abilities.effects.keyword.ScryEffect; import mage.abilities.hint.ConditionHint; @@ -48,7 +48,7 @@ public final class HauntOfTheDeadMarshes extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new ScryEffect(1, false))); // {2}{B}: Return Haunt of the Dead Marshes from your graveyard to the battlefield tapped. Activate only if you control a legendary creature. - this.addAbility(new ConditionalActivatedAbility( + this.addAbility(new ActivateIfConditionActivatedAbility( Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldEffect(true, false), new ManaCostsImpl<>("{2}{B}"), condition ).addHint(hint)); diff --git a/Mage.Sets/src/mage/cards/h/HauntedPlateMail.java b/Mage.Sets/src/mage/cards/h/HauntedPlateMail.java index 4fdf4194e4b..1905df694d5 100644 --- a/Mage.Sets/src/mage/cards/h/HauntedPlateMail.java +++ b/Mage.Sets/src/mage/cards/h/HauntedPlateMail.java @@ -1,47 +1,46 @@ - package mage.cards.h; -import java.util.UUID; -import mage.MageInt; -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.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.keyword.EquipAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.ComparisonType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.filter.StaticFilters; -import mage.game.permanent.token.TokenImpl; +import mage.constants.*; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.game.permanent.token.custom.CreatureToken; + +import java.util.UUID; /** - * * @author Plopman */ public final class HauntedPlateMail extends CardImpl { + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledCreaturePermanent("you control no creatures"), ComparisonType.EQUAL_TO, 0 + ); + public HauntedPlateMail(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); this.subtype.add(SubType.EQUIPMENT); // Equipped creature gets +4/+4. this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(4, 4))); + // {0}: Until end of turn, Haunted Plate Mail becomes a 4/4 Spirit artifact creature that's no longer an Equipment. Activate this ability only if you control no creatures. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, - new BecomesCreatureSourceEffect(new HauntedPlateMailToken(), CardType.ARTIFACT, Duration.EndOfTurn).andNotEquipment(true), - new ManaCostsImpl<>("{0}"), - new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_PERMANENT_CREATURE, ComparisonType.EQUAL_TO, 0), - "{0}: Until end of turn, Haunted Plate Mail becomes a 4/4 Spirit artifact creature that's no longer an Equipment. Activate only if you control no creatures."); - this.addAbility(ability); + this.addAbility(new ActivateIfConditionActivatedAbility(new BecomesCreatureSourceEffect( + new CreatureToken( + 4, 4, "4/4 Spirit artifact " + + "creature that's no longer an Equipment", SubType.SPIRIT + ).withType(CardType.ARTIFACT), CardType.ARTIFACT, Duration.EndOfTurn + ).andNotEquipment(true).withDurationRuleAtStart(true), new GenericManaCost(0), condition)); + // Equip {4} this.addAbility(new EquipAbility(Outcome.BoostCreature, new ManaCostsImpl<>("{4}"))); } @@ -55,22 +54,3 @@ public final class HauntedPlateMail extends CardImpl { return new HauntedPlateMail(this); } } - -class HauntedPlateMailToken extends TokenImpl { - - public HauntedPlateMailToken() { - super("Spirit", "4/4 Spirit artifact creature that's no longer an Equipment"); - cardType.add(CardType.ARTIFACT); - cardType.add(CardType.CREATURE); - subtype.add(SubType.SPIRIT); - power = new MageInt(4); - toughness = new MageInt(4); - } - private HauntedPlateMailToken(final HauntedPlateMailToken token) { - super(token); - } - - public HauntedPlateMailToken copy() { - return new HauntedPlateMailToken(this); - } -} diff --git a/Mage.Sets/src/mage/cards/h/HavengulSkaab.java b/Mage.Sets/src/mage/cards/h/HavengulSkaab.java index fcdede83ef3..445ced869f9 100644 --- a/Mage.Sets/src/mage/cards/h/HavengulSkaab.java +++ b/Mage.Sets/src/mage/cards/h/HavengulSkaab.java @@ -1,27 +1,23 @@ package mage.cards.h; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.effects.common.ReturnToHandChosenControlledPermanentEffect; 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.game.Game; -import mage.game.events.GameEvent; -import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; /** - * * @author noxx */ public final class HavengulSkaab extends CardImpl { public HavengulSkaab(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{U}"); this.subtype.add(SubType.ZOMBIE); this.subtype.add(SubType.HORROR); @@ -29,7 +25,7 @@ public final class HavengulSkaab extends CardImpl { this.toughness = new MageInt(5); // Whenever Havengul Skaab attacks, return another creature you control to its owner's hand. - this.addAbility(new HavengulSkaabAbility()); + this.addAbility(new AttacksTriggeredAbility(new ReturnToHandChosenControlledPermanentEffect(StaticFilters.FILTER_ANOTHER_CREATURE_YOU_CONTROL))); } private HavengulSkaab(final HavengulSkaab card) { @@ -41,39 +37,3 @@ public final class HavengulSkaab extends CardImpl { return new HavengulSkaab(this); } } - -class HavengulSkaabAbility extends TriggeredAbilityImpl { - - public HavengulSkaabAbility() { - super(Zone.BATTLEFIELD, new ReturnToHandTargetEffect()); - } - - private HavengulSkaabAbility(final HavengulSkaabAbility ability) { - super(ability); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ATTACKER_DECLARED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getSourceId().equals(this.getSourceId())) { - TargetControlledCreaturePermanent target = new TargetControlledCreaturePermanent(1, 1, StaticFilters.FILTER_ANOTHER_CREATURE_YOU_CONTROL, true); - this.addTarget(target); - return true; - } - return false; - } - - @Override - public String getRule() { - return "Whenever {this} attacks, return another creature you control to its owner's hand."; - } - - @Override - public HavengulSkaabAbility copy() { - return new HavengulSkaabAbility(this); - } -} diff --git a/Mage.Sets/src/mage/cards/h/HazduhrTheAbbot.java b/Mage.Sets/src/mage/cards/h/HazduhrTheAbbot.java index cc5bae4eb23..24692c5aced 100644 --- a/Mage.Sets/src/mage/cards/h/HazduhrTheAbbot.java +++ b/Mage.Sets/src/mage/cards/h/HazduhrTheAbbot.java @@ -1,4 +1,3 @@ - package mage.cards.h; import mage.MageInt; @@ -10,25 +9,27 @@ import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.RedirectionEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; -import mage.target.common.TargetControlledCreaturePermanent; import mage.util.CardUtil; import java.util.UUID; /** - * * @author TheElk801 & L_J */ public final class HazduhrTheAbbot extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("white creature you control"); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("white creature you control"); static { filter.add(new ColorPredicate(ObjectColor.WHITE)); @@ -45,7 +46,7 @@ public final class HazduhrTheAbbot extends CardImpl { // {X}, {T}: The next X damage that would be dealt this turn to target white creature you control is dealt to Hazduhr the Abbot instead. Ability ability = new SimpleActivatedAbility(new HazduhrTheAbbotRedirectDamageEffect(Duration.EndOfTurn), new ManaCostsImpl<>("{X}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetControlledCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } @@ -61,8 +62,6 @@ public final class HazduhrTheAbbot extends CardImpl { class HazduhrTheAbbotRedirectDamageEffect extends RedirectionEffect { - private static FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); - public HazduhrTheAbbotRedirectDamageEffect(Duration duration) { super(duration, 0, UsageType.ACCORDING_DURATION); this.staticText = "The next X damage that would be dealt this turn to target white creature you control is dealt to {this} instead"; @@ -85,19 +84,15 @@ class HazduhrTheAbbotRedirectDamageEffect extends RedirectionEffect { @Override public boolean applies(GameEvent event, Ability source, Game game) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - if (filter.match(permanent, permanent.getControllerId(), source, game)) { - if (event.getTargetId().equals(getTargetPointer().getFirst(game, source))) { - if (event.getTargetId() != null) { - TargetPermanent target = new TargetPermanent(); - target.add(source.getSourceId(), game); - redirectTarget = target; - return true; - } - } - } + Permanent permanent = source.getSourcePermanentIfItStillExists(game); + if (permanent == null + || !event.getTargetId().equals(getTargetPointer().getFirst(game, source)) + || event.getTargetId() == null) { + return false; } - return false; + TargetPermanent target = new TargetPermanent(); + target.add(source.getSourceId(), game); + redirectTarget = target; + return true; } } diff --git a/Mage.Sets/src/mage/cards/h/HeadlessSpecter.java b/Mage.Sets/src/mage/cards/h/HeadlessSpecter.java index 37de60a499f..064186332db 100644 --- a/Mage.Sets/src/mage/cards/h/HeadlessSpecter.java +++ b/Mage.Sets/src/mage/cards/h/HeadlessSpecter.java @@ -3,11 +3,11 @@ package mage.cards.h; import mage.MageInt; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.condition.common.HellbentCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; @@ -29,12 +29,9 @@ public final class HeadlessSpecter extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Hellbent — Whenever Headless Specter deals combat damage to a player, if you have no cards in hand, that player discards a card at random. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new DealsCombatDamageToAPlayerTriggeredAbility( - new DiscardTargetEffect(1, true), false, true - ), HellbentCondition.instance, "Hellbent — Whenever {this} deals combat damage " + - "to a player, if you have no cards in hand, that player discards a card at random." - )); + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility( + new DiscardTargetEffect(1, true), false, true + ).withInterveningIf(HellbentCondition.instance).setAbilityWord(AbilityWord.HELLBENT)); } private HeadlessSpecter(final HeadlessSpecter card) { diff --git a/Mage.Sets/src/mage/cards/h/HeartPiercerBow.java b/Mage.Sets/src/mage/cards/h/HeartPiercerBow.java index 72b32c2cd14..52cb3ab0a6d 100644 --- a/Mage.Sets/src/mage/cards/h/HeartPiercerBow.java +++ b/Mage.Sets/src/mage/cards/h/HeartPiercerBow.java @@ -12,6 +12,7 @@ import mage.constants.Outcome; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.DefendingPlayerControlsAttachedAttackingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -33,7 +34,7 @@ public final class HeartPiercerBow extends CardImpl { // Whenever equipped creature attacks, Heart-Piercer Bow deals 1 damage to target creature defending player controls. Ability ability = new AttacksAttachedTriggeredAbility(new DamageTargetEffect(1)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // Equip {1} diff --git a/Mage.Sets/src/mage/cards/h/HeartPiercerManticore.java b/Mage.Sets/src/mage/cards/h/HeartPiercerManticore.java index 0a17b5860db..9e9efc8e9f2 100644 --- a/Mage.Sets/src/mage/cards/h/HeartPiercerManticore.java +++ b/Mage.Sets/src/mage/cards/h/HeartPiercerManticore.java @@ -1,9 +1,11 @@ package mage.cards.h; import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.delayed.ReflexiveTriggeredAbility; +import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DamageTargetEffect; @@ -15,11 +17,7 @@ import mage.constants.Outcome; import mage.constants.SubType; import mage.filter.StaticFilters; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.Target; -import mage.target.common.TargetAnyTarget; -import mage.target.common.TargetControlledCreaturePermanent; import java.util.UUID; @@ -36,7 +34,7 @@ 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 HeartPiercerManticoreEffect())); // Embalm {5}{R} this.addAbility(new EmbalmAbility(new ManaCostsImpl<>("{5}{R}"), this)); @@ -52,21 +50,21 @@ public final class HeartPiercerManticore extends CardImpl { } } -class HeartPiercerManticoreSacrificeEffect extends OneShotEffect { +class HeartPiercerManticoreEffect extends OneShotEffect { - HeartPiercerManticoreSacrificeEffect() { + HeartPiercerManticoreEffect() { super(Outcome.Damage); - this.staticText = "sacrifice another creature. When you do, " + this.staticText = "you may sacrifice another creature. When you do, " + "{this} deals damage equal to that creature's power to any target"; } - private HeartPiercerManticoreSacrificeEffect(final HeartPiercerManticoreSacrificeEffect effect) { + private HeartPiercerManticoreEffect(final HeartPiercerManticoreEffect effect) { super(effect); } @Override - public HeartPiercerManticoreSacrificeEffect copy() { - return new HeartPiercerManticoreSacrificeEffect(this); + public HeartPiercerManticoreEffect copy() { + return new HeartPiercerManticoreEffect(this); } @Override @@ -75,26 +73,22 @@ class HeartPiercerManticoreSacrificeEffect extends OneShotEffect { if (controller == null) { return false; } - Target target = new TargetControlledCreaturePermanent( - 1, 1, StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE, true - ); - if (!controller.choose(outcome, target, source, game)) { - return false; - } - Permanent toSacrifice = game.getPermanent(target.getFirstTarget()); - if (toSacrifice == null) { - return false; - } - int power = toSacrifice.getPower().getValue(); - if (!toSacrifice.sacrifice(source, game)) { + SacrificeTargetCost cost = new SacrificeTargetCost(StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE); + if (!cost.canPay(source, source, source.getControllerId(), game) + || !controller.chooseUse(outcome, "Sacrifice another creature?", source, game) + || !cost.pay(source, game, source, source.getControllerId(), false)) { return false; } + int power = cost + .getPermanents() + .stream() + .map(MageObject::getPower) + .mapToInt(MageInt::getValue) + .sum(); 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/HeartWolf.java b/Mage.Sets/src/mage/cards/h/HeartWolf.java index 3ec610c1759..abf8410c7e6 100644 --- a/Mage.Sets/src/mage/cards/h/HeartWolf.java +++ b/Mage.Sets/src/mage/cards/h/HeartWolf.java @@ -1,28 +1,30 @@ package mage.cards.h; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.IsPhaseCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; -import mage.constants.*; import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author noahg */ public final class HeartWolf extends CardImpl { @@ -33,9 +35,11 @@ public final class HeartWolf extends CardImpl { filter.add(SubType.DWARF.getPredicate()); } + private static final Condition condition = new IsPhaseCondition(TurnPhase.COMBAT); + public HeartWolf(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); - + this.subtype.add(SubType.WOLF); this.power = new MageInt(2); this.toughness = new MageInt(2); @@ -44,11 +48,14 @@ public final class HeartWolf extends CardImpl { this.addAbility(FirstStrikeAbility.getInstance()); // {tap}: Target Dwarf creature gets +2/+0 and gains first strike until end of turn. When that creature leaves the battlefield this turn, sacrifice Heart Wolf. Activate this ability only during combat. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(2, 0, Duration.EndOfTurn) - .setText("Target Dwarf creature gets +2/+0"), new TapSourceCost(), new IsPhaseCondition(TurnPhase.COMBAT)); + Ability ability = new ActivateIfConditionActivatedAbility( + new BoostTargetEffect(2, 0, Duration.EndOfTurn) + .setText("Target Dwarf creature gets +2/+0"), + new TapSourceCost(), condition + ); ability.addEffect(new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn).setText("and gains first strike until end of turn")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new HeartWolfDelayedTriggeredAbility(), true)); this.addAbility(ability); } @@ -97,4 +104,4 @@ class HeartWolfDelayedTriggeredAbility extends DelayedTriggeredAbility { public String getRule() { return "When that creature leaves the battlefield this turn, sacrifice {this}."; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/h/HearthCharm.java b/Mage.Sets/src/mage/cards/h/HearthCharm.java index 427b8409585..af2c34646a0 100644 --- a/Mage.Sets/src/mage/cards/h/HearthCharm.java +++ b/Mage.Sets/src/mage/cards/h/HearthCharm.java @@ -13,8 +13,11 @@ import mage.constants.Duration; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_ARTIFACT_CREATURE; + /** * * @author LoneFox @@ -32,13 +35,13 @@ public final class HearthCharm extends CardImpl { // Choose one - Destroy target artifact creature this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_CREATURE)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_ARTIFACT_CREATURE)); // or attacking creatures get +1/+0 until end of turn Mode mode = new Mode(new BoostAllEffect(1, 0, Duration.EndOfTurn, StaticFilters.FILTER_ATTACKING_CREATURES, false)); this.getSpellAbility().addMode(mode); // or target creature with power 2 or less is unblockable this turn. mode = new Mode(new CantBeBlockedTargetEffect()); - mode.addTarget(new TargetCreaturePermanent(filter)); + mode.addTarget(new TargetPermanent(filter)); this.getSpellAbility().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/h/HearthcageGiant.java b/Mage.Sets/src/mage/cards/h/HearthcageGiant.java index dc2d93b9588..3b6988d9bc3 100644 --- a/Mage.Sets/src/mage/cards/h/HearthcageGiant.java +++ b/Mage.Sets/src/mage/cards/h/HearthcageGiant.java @@ -18,6 +18,7 @@ import mage.constants.Zone; import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.game.permanent.token.ElementalShamanToken; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; @@ -48,7 +49,7 @@ public final class HearthcageGiant extends CardImpl { //Sacrifice an Elemental: Target Giant creature gets +3/+1 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(3, 1, Duration.EndOfTurn), new SacrificeTargetCost(filterElemental)); - ability.addTarget(new TargetCreaturePermanent(filterGiant)); + ability.addTarget(new TargetPermanent(filterGiant)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HeartstabberMosquito.java b/Mage.Sets/src/mage/cards/h/HeartstabberMosquito.java index 93ee5757008..d91b07cf385 100644 --- a/Mage.Sets/src/mage/cards/h/HeartstabberMosquito.java +++ b/Mage.Sets/src/mage/cards/h/HeartstabberMosquito.java @@ -1,11 +1,9 @@ - package mage.cards.h; -import java.util.UUID; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.KickerAbility; @@ -15,14 +13,15 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author North */ public final class HeartstabberMosquito extends CardImpl { public HeartstabberMosquito(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.INSECT); this.power = new MageInt(2); @@ -31,14 +30,13 @@ public final class HeartstabberMosquito extends CardImpl { // Kicker {2}{B} (You may pay an additional {2}{B} as you cast this spell.) this.addAbility(new KickerAbility("{2}{B}")); - // Flying this.addAbility(FlyingAbility.getInstance()); // When Heartstabber Mosquito enters the battlefield, if it was kicked, destroy target creature. - EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), false); + Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), false).withInterveningIf(KickedCondition.ONCE); ability.addTarget(new TargetCreaturePermanent()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.ONCE, "When {this} enters, if it was kicked, destroy target creature.")); + this.addAbility(ability); } private HeartstabberMosquito(final HeartstabberMosquito card) { diff --git a/Mage.Sets/src/mage/cards/h/HeavyInfantry.java b/Mage.Sets/src/mage/cards/h/HeavyInfantry.java index 4ee8a10b8c1..acab80545c4 100644 --- a/Mage.Sets/src/mage/cards/h/HeavyInfantry.java +++ b/Mage.Sets/src/mage/cards/h/HeavyInfantry.java @@ -11,8 +11,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -28,7 +31,7 @@ public final class HeavyInfantry extends CardImpl { // When Heavy Infantry enters the battlefield, tap target creature an opponent controls. Ability ability = new EntersBattlefieldTriggeredAbility(new TapTargetEffect()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HeidarRimewindMaster.java b/Mage.Sets/src/mage/cards/h/HeidarRimewindMaster.java index 227e47fc90b..6f9b7c9ac05 100644 --- a/Mage.Sets/src/mage/cards/h/HeidarRimewindMaster.java +++ b/Mage.Sets/src/mage/cards/h/HeidarRimewindMaster.java @@ -1,10 +1,9 @@ - package mage.cards.h; -import java.util.UUID; 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.GenericManaCost; @@ -12,27 +11,30 @@ import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.ComparisonType; +import mage.constants.SubType; import mage.constants.SuperType; -import mage.constants.Zone; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledPermanent; import mage.target.TargetPermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class HeidarRimewindMaster extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent("you control four or more snow permanents"); + private static final FilterPermanent filter = new FilterControlledPermanent("you control four or more snow permanents"); static { filter.add(SuperType.SNOW.getPredicate()); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 3); + public HeidarRimewindMaster(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WIZARD); @@ -40,10 +42,9 @@ public final class HeidarRimewindMaster extends CardImpl { this.toughness = new MageInt(3); // {2}, {tap}: Return target permanent to its owner's hand. Activate this ability only if you control four or more snow permanents. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new ReturnToHandTargetEffect(), - new GenericManaCost(2), - new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 3)); + Ability ability = new ActivateIfConditionActivatedAbility( + new ReturnToHandTargetEffect(), new GenericManaCost(2), condition + ); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetPermanent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/h/HeirOfTheWilds.java b/Mage.Sets/src/mage/cards/h/HeirOfTheWilds.java index 50d3890ca83..18ebc9a2b6f 100644 --- a/Mage.Sets/src/mage/cards/h/HeirOfTheWilds.java +++ b/Mage.Sets/src/mage/cards/h/HeirOfTheWilds.java @@ -1,15 +1,14 @@ package mage.cards.h; import mage.MageInt; -import mage.abilities.Ability; 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.AbilityWord; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; @@ -31,15 +30,11 @@ public final class HeirOfTheWilds extends CardImpl { // Deathtouch this.addAbility(DeathtouchAbility.getInstance()); - // Ferocious - Whenever Heir of the Wilds attacks, if you control a creature with power 4 or greater, Heir of the Wilds gets +1/+1 until end of turn. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new BoostSourceEffect(1, 1, Duration.EndOfTurn), false), - FerociousCondition.instance, - "Ferocious — Whenever {this} attacks, if you control a creature with power 4 or greater, {this} gets +1/+1 until end of turn." - ); - ability.addHint(FerociousHint.instance); - this.addAbility(ability); + // Ferocious - Whenever Heir of the Wilds attacks, if you control a creature with power 4 or greater, Heir of the Wilds gets +1/+1 until end of turn. + this.addAbility(new AttacksTriggeredAbility( + new BoostSourceEffect(1, 1, Duration.EndOfTurn), false + ).withInterveningIf(FerociousCondition.instance).addHint(FerociousHint.instance).setAbilityWord(AbilityWord.FEROCIOUS)); } private HeirOfTheWilds(final HeirOfTheWilds card) { diff --git a/Mage.Sets/src/mage/cards/h/HeliodsEmissary.java b/Mage.Sets/src/mage/cards/h/HeliodsEmissary.java index 39c1aac2ece..18f4430cf9d 100644 --- a/Mage.Sets/src/mage/cards/h/HeliodsEmissary.java +++ b/Mage.Sets/src/mage/cards/h/HeliodsEmissary.java @@ -19,8 +19,11 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.StaticFilters; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -38,11 +41,11 @@ public final class HeliodsEmissary extends CardImpl { this.addAbility(new BestowAbility(this, "{6}{W}")); // Whenever Heliod's Emissary or enchanted creature attacks, tap target creature an opponent controls. Ability ability = new AttacksTriggeredAbility(new TapTargetEffect(), false); - Target target = new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE); + Target target = new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE); ability.addTarget(target); this.addAbility(ability); ability = new AttacksAttachedTriggeredAbility(new TapTargetEffect(), AttachmentType.AURA, false); - target = new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE); + target = new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE); ability.addTarget(target); this.addAbility(ability); // Enchanted creature gets +3/+3. diff --git a/Mage.Sets/src/mage/cards/h/HeliumSquirter.java b/Mage.Sets/src/mage/cards/h/HeliumSquirter.java index edb6b49f36e..cf8c96e33cf 100644 --- a/Mage.Sets/src/mage/cards/h/HeliumSquirter.java +++ b/Mage.Sets/src/mage/cards/h/HeliumSquirter.java @@ -16,8 +16,11 @@ import mage.constants.SubType; import mage.constants.Duration; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_CREATURE_P1P1; + /** * * @author JotaPeRL @@ -36,7 +39,7 @@ public final class HeliumSquirter extends CardImpl { // {1}: Target creature with a +1/+1 counter on it gains flying until end of turn. Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), new GenericManaCost(1)); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_P1P1)); + ability.addTarget(new TargetPermanent(FILTER_CREATURE_P1P1)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HellfireMongrel.java b/Mage.Sets/src/mage/cards/h/HellfireMongrel.java index df2bad6a1d6..527669c7bd4 100644 --- a/Mage.Sets/src/mage/cards/h/HellfireMongrel.java +++ b/Mage.Sets/src/mage/cards/h/HellfireMongrel.java @@ -1,13 +1,11 @@ package mage.cards.h; -import java.util.UUID; import mage.MageInt; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.condition.common.CardsInHandCondition; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.CardsInHandCondition; import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -15,14 +13,17 @@ import mage.constants.ComparisonType; import mage.constants.SubType; import mage.constants.TargetController; +import java.util.UUID; + /** - * * @author North */ public final class HellfireMongrel extends CardImpl { + private static final Condition condition = new CardsInHandCondition(ComparisonType.FEWER_THAN, 3, TargetController.ACTIVE); + public HellfireMongrel(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); this.subtype.add(SubType.ELEMENTAL); this.subtype.add(SubType.DOG); @@ -30,11 +31,11 @@ public final class HellfireMongrel extends CardImpl { this.toughness = new MageInt(2); // At the beginning of each opponent's upkeep, if that player has two or fewer cards in hand, Hellfire Mongrel deals 2 damage to that player. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(TargetController.OPPONENT, new DamageTargetEffect(2), false), - (Condition)new CardsInHandCondition(ComparisonType.FEWER_THAN, 3, TargetController.ACTIVE), - "At the beginning of each opponent's upkeep, if that player has two or fewer cards in hand, {this} deals 2 damage to that player." - )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + TargetController.OPPONENT, + new DamageTargetEffect(2, true, "that player"), + false + ).withInterveningIf(condition)); } private HellfireMongrel(final HellfireMongrel card) { diff --git a/Mage.Sets/src/mage/cards/h/HellkiteTyrant.java b/Mage.Sets/src/mage/cards/h/HellkiteTyrant.java index 2fca3826bd8..a4eae8d7156 100644 --- a/Mage.Sets/src/mage/cards/h/HellkiteTyrant.java +++ b/Mage.Sets/src/mage/cards/h/HellkiteTyrant.java @@ -2,17 +2,15 @@ package mage.cards.h; import mage.MageInt; -import mage.abilities.TriggeredAbility; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.common.WinGameSourceControllerEffect; import mage.abilities.effects.common.continuous.GainControlAllControlledTargetEffect; -import mage.abilities.hint.ValueHint; +import mage.abilities.hint.common.ArtifactYouControlHint; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -28,6 +26,10 @@ import java.util.UUID; */ public final class HellkiteTyrant extends CardImpl { + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterArtifactPermanent("you control twenty or more artifacts"), ComparisonType.MORE_THAN, 19 + ); + public HellkiteTyrant(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}{R}"); this.subtype.add(SubType.DRAGON); @@ -37,8 +39,10 @@ public final class HellkiteTyrant extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); + // Trample this.addAbility(TrampleAbility.getInstance()); + // Whenever Hellkite Tyrant deals combat damage to a player, gain control of all artifacts that player controls. this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility( new GainControlAllControlledTargetEffect(StaticFilters.FILTER_PERMANENT_ARTIFACTS) @@ -46,12 +50,8 @@ public final class HellkiteTyrant extends CardImpl { false, true)); // At the beginning of your upkeep, if you control twenty or more artifacts, you win the game. - TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - ability, - new PermanentsOnTheBattlefieldCondition(new FilterArtifactPermanent(), ComparisonType.MORE_THAN, 19), - "At the beginning of your upkeep, if you control twenty or more artifacts, you win the game." - ).addHint(new ValueHint("Artifacts you control", new PermanentsOnBattlefieldCount(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT)))); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect()) + .withInterveningIf(condition).addHint(ArtifactYouControlHint.instance)); } private HellkiteTyrant(final HellkiteTyrant card) { diff --git a/Mage.Sets/src/mage/cards/h/HellsCaretaker.java b/Mage.Sets/src/mage/cards/h/HellsCaretaker.java index 39466c7193c..9ad03a7e746 100644 --- a/Mage.Sets/src/mage/cards/h/HellsCaretaker.java +++ b/Mage.Sets/src/mage/cards/h/HellsCaretaker.java @@ -1,25 +1,22 @@ - package mage.cards.h; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.PhaseStep; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.StaticFilters; import mage.target.common.TargetCardInYourGraveyard; +import java.util.UUID; + /** - * * @author fireshoes */ public final class HellsCaretaker extends CardImpl { @@ -31,10 +28,10 @@ public final class HellsCaretaker extends CardImpl { this.toughness = new MageInt(1); // {tap}, Sacrifice a creature: Return target creature card from your graveyard to the battlefield. Activate this ability only during your upkeep. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, + Ability ability = new ActivateIfConditionActivatedAbility( new ReturnFromGraveyardToBattlefieldTargetEffect(), - new TapSourceCost(), - new IsStepCondition(PhaseStep.UPKEEP)); + new TapSourceCost(), IsStepCondition.getMyUpkeep() + ); ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_CREATURE)); ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/h/HellsThunder.java b/Mage.Sets/src/mage/cards/h/HellsThunder.java index fc671208711..ad6c9aa47dc 100644 --- a/Mage.Sets/src/mage/cards/h/HellsThunder.java +++ b/Mage.Sets/src/mage/cards/h/HellsThunder.java @@ -1,29 +1,27 @@ - - package mage.cards.h; -import java.util.UUID; import mage.MageInt; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.UnearthAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.game.events.GameEvent.EventType; +import mage.constants.TargetController; + +import java.util.UUID; /** - * * @author BetaSteward_at_googlemail.com */ public final class HellsThunder extends CardImpl { public HellsThunder(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.ELEMENTAL); this.power = new MageInt(4); @@ -31,9 +29,10 @@ public final class HellsThunder extends CardImpl { this.addAbility(FlyingAbility.getInstance()); this.addAbility(HasteAbility.getInstance()); - this.addAbility(new OnEventTriggeredAbility(EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new SacrificeSourceEffect())); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.NEXT, new SacrificeSourceEffect(), false + )); this.addAbility(new UnearthAbility(new ManaCostsImpl<>("{4}{R}"))); - } private HellsThunder(final HellsThunder card) { diff --git a/Mage.Sets/src/mage/cards/h/HellsparkElemental.java b/Mage.Sets/src/mage/cards/h/HellsparkElemental.java index ef3573fb740..314a3909c4d 100644 --- a/Mage.Sets/src/mage/cards/h/HellsparkElemental.java +++ b/Mage.Sets/src/mage/cards/h/HellsparkElemental.java @@ -1,21 +1,19 @@ - - package mage.cards.h; -import java.util.UUID; import mage.MageInt; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.TrampleAbility; import mage.abilities.keyword.UnearthAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.game.events.GameEvent.EventType; +import mage.constants.TargetController; +import java.util.UUID; /** * @author BetaSteward_at_googlemail.com @@ -23,7 +21,7 @@ import mage.game.events.GameEvent.EventType; public final class HellsparkElemental extends CardImpl { public HellsparkElemental(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); this.power = new MageInt(3); @@ -34,7 +32,9 @@ public final class HellsparkElemental extends CardImpl { this.addAbility(HasteAbility.getInstance()); // At the beginning of the end step, sacrifice Hellspark Elemental. - this.addAbility(new OnEventTriggeredAbility(EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new SacrificeSourceEffect())); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.NEXT, new SacrificeSourceEffect(), false + )); // Unearth {1}{R}: Return this card from your graveyard to the battlefield. It gains haste. Exile it at the beginning of the next end step or if it would leave the battlefield. Unearth only as a sorcery.) this.addAbility(new UnearthAbility(new ManaCostsImpl<>("{1}{R}"))); diff --git a/Mage.Sets/src/mage/cards/h/HelmOfKaldra.java b/Mage.Sets/src/mage/cards/h/HelmOfKaldra.java index b8b92c6c6b9..092f50e31f2 100644 --- a/Mage.Sets/src/mage/cards/h/HelmOfKaldra.java +++ b/Mage.Sets/src/mage/cards/h/HelmOfKaldra.java @@ -1,16 +1,10 @@ - package mage.cards.h; -import java.util.UUID; import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.Condition; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.keyword.EquipAbility; import mage.abilities.keyword.FirstStrikeAbility; @@ -19,51 +13,48 @@ import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.common.FilterControlledArtifactPermanent; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.predicate.permanent.PermanentReferenceInCollectionPredicate; +import mage.game.Controllable; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.KaldraToken; +import mage.game.permanent.token.Token; +import mage.target.TargetPermanent; +import mage.util.RandomUtil; + +import java.util.*; +import java.util.stream.Collectors; /** - * * @author LevelX2 */ public final class HelmOfKaldra extends CardImpl { - static final FilterControlledArtifactPermanent filterHelm = new FilterControlledArtifactPermanent(); - static final FilterControlledArtifactPermanent filterShield = new FilterControlledArtifactPermanent(); - static final FilterControlledArtifactPermanent filterSword = new FilterControlledArtifactPermanent(); - - static { - filterHelm.add(new NamePredicate("Helm of Kaldra")); - filterShield.add(new NamePredicate("Shield of Kaldra")); - filterSword.add(new NamePredicate("Sword of Kaldra")); - } - public HelmOfKaldra(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.EQUIPMENT); // Equipped creature has first strike, trample, and haste. - Ability ability = new SimpleStaticAbility(new GainAbilityAttachedEffect(FirstStrikeAbility.getInstance(), AttachmentType.EQUIPMENT)); - Effect effect = new GainAbilityAttachedEffect(TrampleAbility.getInstance(), AttachmentType.EQUIPMENT); - effect.setText(", trample"); - ability.addEffect(effect); - effect = new GainAbilityAttachedEffect(HasteAbility.getInstance(), AttachmentType.EQUIPMENT); - effect.setText(", and haste"); - ability.addEffect(effect); + Ability ability = new SimpleStaticAbility(new GainAbilityAttachedEffect( + FirstStrikeAbility.getInstance(), AttachmentType.EQUIPMENT + )); + ability.addEffect(new GainAbilityAttachedEffect( + TrampleAbility.getInstance(), AttachmentType.EQUIPMENT + ).setText(", trample")); + ability.addEffect(new GainAbilityAttachedEffect( + HasteAbility.getInstance(), AttachmentType.EQUIPMENT + ).setText(", and haste")); this.addAbility(ability); + // {1}: If you control Equipment named Helm of Kaldra, Sword of Kaldra, and Shield of Kaldra, create a legendary 4/4 colorless Avatar creature token named Kaldra and attach those Equipment to it. - this.addAbility(new ConditionalActivatedAbility( - Zone.BATTLEFIELD, - new HelmOfKaldraEffect(), - new GenericManaCost(1), - new HelmOfKaldraCondition(), - "{1}: If you control Equipment named Helm of Kaldra, Sword of Kaldra, and Shield of Kaldra, create Kaldra, a legendary 4/4 colorless Avatar creature token. Attach those Equipment to it.")); + this.addAbility(new SimpleActivatedAbility(new HelmOfKaldraEffect(), new GenericManaCost(1))); + // Equip {2} - this.addAbility(new EquipAbility(Outcome.Benefit, new ManaCostsImpl<>("{2}"), false)); + this.addAbility(new EquipAbility(2, false)); } private HelmOfKaldra(final HelmOfKaldra card) { @@ -76,26 +67,22 @@ public final class HelmOfKaldra extends CardImpl { } } -class HelmOfKaldraCondition implements Condition { - - @Override - public boolean apply(Game game, Ability source) { - if (game.getBattlefield().count(HelmOfKaldra.filterHelm, source.getControllerId(), source, game) < 1) { - return false; - } - if (game.getBattlefield().count(HelmOfKaldra.filterSword, source.getControllerId(), source, game) < 1) { - return false; - } - return game.getBattlefield().count(HelmOfKaldra.filterShield, source.getControllerId(), source, game) >= 1; - } - -} - class HelmOfKaldraEffect extends OneShotEffect { + private static final FilterPermanent filterHelm = new FilterControlledPermanent(SubType.EQUIPMENT); + private static final FilterPermanent filterSword = new FilterControlledPermanent(SubType.EQUIPMENT); + private static final FilterPermanent filterShield = new FilterControlledPermanent(SubType.EQUIPMENT); + + static { + filterHelm.add(new NamePredicate("Helm of Kaldra")); + filterSword.add(new NamePredicate("Sword of Kaldra")); + filterShield.add(new NamePredicate("Shield of Kaldra")); + } + HelmOfKaldraEffect() { super(Outcome.Benefit); - this.staticText = "if you control Equipment named Helm of Kaldra, Sword of Kaldra, and Shield of Kaldra, create Kaldra, a legendary 4/4 colorless Avatar creature token. Attach those Equipment to it"; + this.staticText = "if you control Equipment named Helm of Kaldra, Sword of Kaldra, and Shield of Kaldra, " + + "create Kaldra, a legendary 4/4 colorless Avatar creature token. Attach those Equipment to it"; } private HelmOfKaldraEffect(final HelmOfKaldraEffect effect) { @@ -109,32 +96,48 @@ class HelmOfKaldraEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - if (new HelmOfKaldraCondition().apply(game, source)) { - CreateTokenEffect effect = new CreateTokenEffect(new KaldraToken()); - effect.apply(game, source); - for (UUID tokenId : effect.getLastAddedTokenIds()) { - Permanent kaldra = game.getPermanent(tokenId); - if (kaldra != null) { - // Attach helm to the token - for (Permanent kaldrasHelm : game.getBattlefield().getAllActivePermanents(HelmOfKaldra.filterHelm, source.getControllerId(), game)) { - kaldra.addAttachment(kaldrasHelm.getId(), source, game); - break; - } - // Attach shield to the token - for (Permanent kaldrasShield : game.getBattlefield().getAllActivePermanents(HelmOfKaldra.filterShield, source.getControllerId(), game)) { - kaldra.addAttachment(kaldrasShield.getId(), source, game); - break; - } - // Attach sword to the token - for (Permanent kaldrasSword : game.getBattlefield().getAllActivePermanents(HelmOfKaldra.filterSword, source.getControllerId(), game)) { - kaldra.addAttachment(kaldrasSword.getId(), source, game); - break; - } - - } - return true; - } + if (!game.getBattlefield().contains(filterHelm, source, game, 1) + || !game.getBattlefield().contains(filterSword, source, game, 1) + || !game.getBattlefield().contains(filterShield, source, game, 1)) { + return false; } - return false; + Token token = new KaldraToken(); + token.putOntoBattlefield(1, game, source); + Set permanents = token + .getLastAddedTokenIds() + .stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + Permanent permanent; + switch (permanents.size()) { + case 0: + return true; + case 1: + permanent = RandomUtil.randomFromCollection(permanents); + break; + default: + FilterPermanent filter = new FilterPermanent(); + filter.add(new PermanentReferenceInCollectionPredicate(permanents, game)); + TargetPermanent target = new TargetPermanent(filter); + target.withNotTarget(true); + target.withChooseHint("to equip"); + Optional.ofNullable(source) + .map(Controllable::getControllerId) + .map(game::getPlayer) + .ifPresent(player -> player.choose(outcome, target, source, game)); + permanent = game.getPermanent(target.getFirstTarget()); + } + if (permanent == null) { + return true; + } + Set equipments = new HashSet<>(); + equipments.addAll(game.getBattlefield().getActivePermanents(filterHelm, source.getControllerId(), source, game)); + equipments.addAll(game.getBattlefield().getActivePermanents(filterSword, source.getControllerId(), source, game)); + equipments.addAll(game.getBattlefield().getActivePermanents(filterShield, source.getControllerId(), source, game)); + for (Permanent equipment : equipments) { + permanent.addAttachment(equipment.getId(), source, game); + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/h/Helvault.java b/Mage.Sets/src/mage/cards/h/Helvault.java index 2e5d365b095..42eb33d43a2 100644 --- a/Mage.Sets/src/mage/cards/h/Helvault.java +++ b/Mage.Sets/src/mage/cards/h/Helvault.java @@ -12,11 +12,14 @@ import mage.constants.CardType; import mage.constants.SuperType; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author North */ @@ -35,7 +38,7 @@ public final class Helvault extends CardImpl { // {7}, {T}: Exile target creature you don't control. ability = new SimpleActivatedAbility(new ExileTargetForSourceEffect(), new GenericManaCost(7)); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + ability.addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); 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. diff --git a/Mage.Sets/src/mage/cards/h/HeraldOfTheForgotten.java b/Mage.Sets/src/mage/cards/h/HeraldOfTheForgotten.java index 0bbb6d8dd8b..4a8f1a33701 100644 --- a/Mage.Sets/src/mage/cards/h/HeraldOfTheForgotten.java +++ b/Mage.Sets/src/mage/cards/h/HeraldOfTheForgotten.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromEverywhereSourceCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.keyword.CyclingAbility; import mage.abilities.keyword.FlyingAbility; @@ -43,11 +42,8 @@ public final class HeraldOfTheForgotten extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When Herald of the Forgotten enters the battlefield, if you cast it, return any number of target permanent cards with cycling abilities from your graveyard to the battlefield. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect()), - CastFromEverywhereSourceCondition.instance, "When {this} enters, if you cast it, " + - "return any number of target permanent cards with cycling abilities from your graveyard to the battlefield." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect()) + .withInterveningIf(CastFromEverywhereSourceCondition.instance); ability.addTarget(new TargetCardInYourGraveyard(0, Integer.MAX_VALUE, filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HerosDemise.java b/Mage.Sets/src/mage/cards/h/HerosDemise.java index f44114f97d2..bec797fc7c3 100644 --- a/Mage.Sets/src/mage/cards/h/HerosDemise.java +++ b/Mage.Sets/src/mage/cards/h/HerosDemise.java @@ -8,6 +8,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SuperType; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -27,7 +28,7 @@ public final class HerosDemise extends CardImpl { // Destroy target legendary creature. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private HerosDemise(final HerosDemise card) { diff --git a/Mage.Sets/src/mage/cards/h/Hexavus.java b/Mage.Sets/src/mage/cards/h/Hexavus.java index 950797b7b41..d8d53b76ee3 100644 --- a/Mage.Sets/src/mage/cards/h/Hexavus.java +++ b/Mage.Sets/src/mage/cards/h/Hexavus.java @@ -21,6 +21,8 @@ import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * @author PurpleCrowbar */ @@ -45,7 +47,7 @@ public final class Hexavus extends CardImpl { new AddCountersTargetEffect(CounterType.FLYING.createInstance()), new GenericManaCost(1) ); ability.addCost(new RemoveCountersSourceCost(CounterType.P1P1.createInstance())); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); // {1}, Remove a counter from another creature you control: Put a +1/+1 counter on Hexavus. diff --git a/Mage.Sets/src/mage/cards/h/HexplateWallbreaker.java b/Mage.Sets/src/mage/cards/h/HexplateWallbreaker.java index 3ad31995635..86a32669d45 100644 --- a/Mage.Sets/src/mage/cards/h/HexplateWallbreaker.java +++ b/Mage.Sets/src/mage/cards/h/HexplateWallbreaker.java @@ -5,7 +5,6 @@ import mage.abilities.common.AttacksAttachedTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.FirstCombatPhaseCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.AdditionalCombatPhaseEffect; import mage.abilities.effects.common.UntapAllEffect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; @@ -16,7 +15,6 @@ 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 java.util.UUID; @@ -38,12 +36,8 @@ public final class HexplateWallbreaker extends CardImpl { // Whenever equipped creature attacks, if it's the first combat phase of the turn, untap // each attacking creature. After this phase, there is an additional combat phase. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new AttacksAttachedTriggeredAbility(new UntapAllEffect(StaticFilters.FILTER_ATTACKING_CREATURES)), - FirstCombatPhaseCondition.instance, - "Whenever equipped creature attacks, if it's the first combat phase of the turn, untap " + - "each attacking creature. After this phase, there is an additional combat phase" - ); + Ability ability = new AttacksAttachedTriggeredAbility(new UntapAllEffect(StaticFilters.FILTER_ATTACKING_CREATURE) + .setText("untap each attacking creature")).withInterveningIf(FirstCombatPhaseCondition.instance); ability.addEffect(new AdditionalCombatPhaseEffect()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/h/HiddenAncients.java b/Mage.Sets/src/mage/cards/h/HiddenAncients.java index 72cd3429781..693e2c71a84 100644 --- a/Mage.Sets/src/mage/cards/h/HiddenAncients.java +++ b/Mage.Sets/src/mage/cards/h/HiddenAncients.java @@ -1,44 +1,35 @@ - package mage.cards.h; -import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; -import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.SourceIsEnchantmentCondition; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.filter.FilterSpell; +import mage.constants.SubType; import mage.filter.StaticFilters; -import mage.game.permanent.token.TokenImpl; +import mage.game.permanent.token.custom.CreatureToken; import java.util.UUID; /** - * * @author LoneFox - * */ public final class HiddenAncients extends CardImpl { - private static final FilterSpell filter = new FilterSpell("enchantment spell"); - - static { - filter.add(CardType.ENCHANTMENT.getPredicate()); - } - public HiddenAncients(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); // When an opponent casts an enchantment spell, if Hidden Ancients is an enchantment, Hidden Ancients becomes a 5/5 Treefolk creature. - TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new HiddenAncientsTreefolkToken(), null, Duration.WhileOnBattlefield), - filter, false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_PERMANENT_ENCHANTMENT), - "When an opponent casts an enchantment spell, if {this} is an enchantment, {this} becomes a 5/5 Treefolk creature.")); + this.addAbility(new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect( + new CreatureToken( + 5, 5, "5/5 Treefolk creature", SubType.TREEFOLK + ), null, Duration.WhileOnBattlefield + ), StaticFilters.FILTER_SPELL_AN_ENCHANTMENT, false) + .withInterveningIf(SourceIsEnchantmentCondition.instance) + .withRuleTextReplacement(true) + .setTriggerPhrase("When an opponent casts an enchantment spell, ")); } private HiddenAncients(final HiddenAncients card) { @@ -50,21 +41,3 @@ public final class HiddenAncients extends CardImpl { return new HiddenAncients(this); } } - -class HiddenAncientsTreefolkToken extends TokenImpl { - - public HiddenAncientsTreefolkToken() { - super("Treefolk", "5/5 Treefolk creature"); - cardType.add(CardType.CREATURE); - subtype.add(SubType.TREEFOLK); - power = new MageInt(5); - toughness = new MageInt(5); - } - private HiddenAncientsTreefolkToken(final HiddenAncientsTreefolkToken token) { - super(token); - } - - public HiddenAncientsTreefolkToken copy() { - return new HiddenAncientsTreefolkToken(this); - } -} diff --git a/Mage.Sets/src/mage/cards/h/HiddenDragonslayer.java b/Mage.Sets/src/mage/cards/h/HiddenDragonslayer.java index 075c3fe919d..0d09b0e3d84 100644 --- a/Mage.Sets/src/mage/cards/h/HiddenDragonslayer.java +++ b/Mage.Sets/src/mage/cards/h/HiddenDragonslayer.java @@ -17,6 +17,7 @@ import mage.constants.ComparisonType; import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -47,7 +48,7 @@ public final class HiddenDragonslayer extends CardImpl { // When Hidden Dragonslayer is turned face up, destroy target creature with power 4 or greater an opponent controls. Ability ability = new TurnedFaceUpSourceTriggeredAbility(new DestroyTargetEffect(), false, false); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HiddenGibbons.java b/Mage.Sets/src/mage/cards/h/HiddenGibbons.java index aa9fea88e83..2fd9309b0d0 100644 --- a/Mage.Sets/src/mage/cards/h/HiddenGibbons.java +++ b/Mage.Sets/src/mage/cards/h/HiddenGibbons.java @@ -1,44 +1,40 @@ - package mage.cards.h; -import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; -import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.SourceIsEnchantmentCondition; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; 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.filter.FilterSpell; -import mage.filter.StaticFilters; -import mage.game.permanent.token.TokenImpl; +import mage.game.permanent.token.custom.CreatureToken; import java.util.UUID; /** - * * @author LoneFox - * */ public final class HiddenGibbons extends CardImpl { - private static final FilterSpell filter = new FilterSpell("instant spell"); + private static final FilterSpell filter = new FilterSpell("an instant spell"); static { filter.add(CardType.INSTANT.getPredicate()); } public HiddenGibbons(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{G}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{G}"); // When an opponent casts an instant spell, if Hidden Gibbons is an enchantment, Hidden Gibbons becomes a 4/4 Ape creature. - TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new HiddenGibbonsApe(), null, Duration.WhileOnBattlefield), - filter, false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_PERMANENT_ENCHANTMENT), - "When an opponent casts an instant spell, if {this} is an enchantment, {this} becomes a 4/4 Ape creature.")); + this.addAbility(new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect( + new CreatureToken(4, 4, "4/4 Ape creature", SubType.APE), + null, Duration.WhileOnBattlefield + ), filter, false) + .withInterveningIf(SourceIsEnchantmentCondition.instance) + .withRuleTextReplacement(true) + .setTriggerPhrase("When an opponent casts an instant spell, ")); } private HiddenGibbons(final HiddenGibbons card) { @@ -50,21 +46,3 @@ public final class HiddenGibbons extends CardImpl { return new HiddenGibbons(this); } } - -class HiddenGibbonsApe extends TokenImpl { - - public HiddenGibbonsApe() { - super("Ape", "4/4 Ape creature"); - cardType.add(CardType.CREATURE); - subtype.add(SubType.APE); - power = new MageInt(4); - toughness = new MageInt(4); - } - private HiddenGibbonsApe(final HiddenGibbonsApe token) { - super(token); - } - - public HiddenGibbonsApe copy() { - return new HiddenGibbonsApe(this); - } -} diff --git a/Mage.Sets/src/mage/cards/h/HiddenGuerrillas.java b/Mage.Sets/src/mage/cards/h/HiddenGuerrillas.java index 04110c2ed4d..df33a20de37 100644 --- a/Mage.Sets/src/mage/cards/h/HiddenGuerrillas.java +++ b/Mage.Sets/src/mage/cards/h/HiddenGuerrillas.java @@ -1,10 +1,7 @@ package mage.cards.h; -import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; -import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.SourceIsEnchantmentCondition; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; @@ -12,33 +9,28 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.filter.FilterSpell; import mage.filter.StaticFilters; -import mage.game.permanent.token.TokenImpl; +import mage.game.permanent.token.custom.CreatureToken; import java.util.UUID; /** - * * @author LoneFox - * */ public final class HiddenGuerrillas extends CardImpl { - - private static final FilterSpell filter = new FilterSpell("an artifact spell"); - static { - filter.add(CardType.ARTIFACT.getPredicate()); - } - public HiddenGuerrillas(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{G}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{G}"); // When an opponent casts an artifact spell, if Hidden Guerrillas is an enchantment, Hidden Guerrillas becomes a 5/3 Soldier creature with trample. - TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new HiddenGuerrillasSoldier(), null, Duration.WhileOnBattlefield), - filter, false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_PERMANENT_ENCHANTMENT), - "When an opponent casts an artifact spell, if {this} is an enchantment, {this} becomes a 5/3 Soldier creature with trample.")); + this.addAbility(new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect( + new CreatureToken( + 5, 3, "5/3 Soldier creature with trample", SubType.SOLDIER + ).withAbility(TrampleAbility.getInstance()), null, Duration.WhileOnBattlefield + ), StaticFilters.FILTER_SPELL_AN_ARTIFACT, false) + .withInterveningIf(SourceIsEnchantmentCondition.instance) + .withRuleTextReplacement(true) + .setTriggerPhrase("When an opponent casts an artifact spell, ")); } private HiddenGuerrillas(final HiddenGuerrillas card) { @@ -50,22 +42,3 @@ public final class HiddenGuerrillas extends CardImpl { return new HiddenGuerrillas(this); } } - -class HiddenGuerrillasSoldier extends TokenImpl { - - public HiddenGuerrillasSoldier() { - super("Soldier", "5/3 Soldier creature with trample"); - cardType.add(CardType.CREATURE); - subtype.add(SubType.SOLDIER); - power = new MageInt(5); - toughness = new MageInt(3); - this.addAbility(TrampleAbility.getInstance()); - } - private HiddenGuerrillasSoldier(final HiddenGuerrillasSoldier token) { - super(token); - } - - public HiddenGuerrillasSoldier copy() { - return new HiddenGuerrillasSoldier(this); - } -} diff --git a/Mage.Sets/src/mage/cards/h/HiddenHerd.java b/Mage.Sets/src/mage/cards/h/HiddenHerd.java index 076cdbdeff3..643b6a624a4 100644 --- a/Mage.Sets/src/mage/cards/h/HiddenHerd.java +++ b/Mage.Sets/src/mage/cards/h/HiddenHerd.java @@ -1,11 +1,7 @@ - package mage.cards.h; -import java.util.UUID; -import mage.MageInt; import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.SourceIsEnchantmentCondition; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -13,14 +9,14 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; -import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; -import mage.game.permanent.token.TokenImpl; +import mage.game.permanent.token.custom.CreatureToken; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class HiddenHerd extends CardImpl { @@ -29,11 +25,7 @@ public final class HiddenHerd extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{G}"); // When an opponent plays a nonbasic land, if Hidden Herd is an enchantment, Hidden Herd becomes a 3/3 Beast creature. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new HiddenHerdAbility(), - new SourceMatchesFilterCondition(StaticFilters.FILTER_PERMANENT_ENCHANTMENT), - "When an opponent plays a nonbasic land, if {this} is an enchantment, {this} becomes a 3/3 Beast creature." - )); + this.addAbility(new HiddenHerdAbility()); } private HiddenHerd(final HiddenHerd card) { @@ -49,7 +41,13 @@ public final class HiddenHerd extends CardImpl { class HiddenHerdAbility extends TriggeredAbilityImpl { public HiddenHerdAbility() { - super(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new HiddenHerdBeast(), null, Duration.WhileOnBattlefield), false); + super(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect( + new CreatureToken(3, 3, "3/3 Beast creature", SubType.BEAST), + null, Duration.WhileOnBattlefield + ), false); + this.withInterveningIf(SourceIsEnchantmentCondition.instance); + this.withRuleTextReplacement(true); + this.setTriggerPhrase("When an opponent plays a nonbasic land, "); } private HiddenHerdAbility(final HiddenHerdAbility ability) { @@ -69,29 +67,6 @@ class HiddenHerdAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent land = game.getPermanentOrLKIBattlefield(event.getTargetId()); - return game.getOpponents(controllerId).contains(event.getPlayerId()) && !land.isBasic(game); - } - - @Override - public String getRule() { - return "When an opponent plays a nonbasic land, if {this} is an enchantment, {this} becomes a 3/3 Beast creature."; - } -} - -class HiddenHerdBeast extends TokenImpl { - - public HiddenHerdBeast() { - super("Beast", "3/3 Beast creature"); - cardType.add(CardType.CREATURE); - subtype.add(SubType.BEAST); - power = new MageInt(3); - toughness = new MageInt(3); - } - private HiddenHerdBeast(final HiddenHerdBeast token) { - super(token); - } - - public HiddenHerdBeast copy() { - return new HiddenHerdBeast(this); + return land != null && game.getOpponents(getControllerId()).contains(event.getPlayerId()) && !land.isBasic(game); } } diff --git a/Mage.Sets/src/mage/cards/h/HiddenPredators.java b/Mage.Sets/src/mage/cards/h/HiddenPredators.java index 6a2027e90fe..474268107a1 100644 --- a/Mage.Sets/src/mage/cards/h/HiddenPredators.java +++ b/Mage.Sets/src/mage/cards/h/HiddenPredators.java @@ -1,7 +1,7 @@ package mage.cards.h; -import mage.MageInt; import mage.abilities.StateTriggeredAbility; +import mage.abilities.condition.common.SourceIsEnchantmentCondition; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -10,7 +10,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.permanent.token.TokenImpl; +import mage.game.permanent.token.custom.CreatureToken; import java.util.UUID; @@ -46,9 +46,10 @@ class HiddenPredatorsStateTriggeredAbility extends StateTriggeredAbility { } public HiddenPredatorsStateTriggeredAbility() { - super(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new HiddenPredatorsToken(), null, Duration.Custom)); - this.withRuleTextReplacement(false); - setTriggerPhrase("When an opponent controls a creature with power 4 or greater, if {this} is an enchantment, "); + super(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new CreatureToken(4, 4, "4/4 Beast creature", SubType.BEAST), null, Duration.Custom)); + this.withInterveningIf(SourceIsEnchantmentCondition.instance); + this.withRuleTextReplacement(true); + this.setTriggerPhrase("When an opponent controls a creature with power 4 or greater, "); } private HiddenPredatorsStateTriggeredAbility(final HiddenPredatorsStateTriggeredAbility ability) { @@ -64,32 +65,4 @@ class HiddenPredatorsStateTriggeredAbility extends StateTriggeredAbility { public boolean checkTrigger(GameEvent event, Game game) { return !game.getBattlefield().getActivePermanents(filter, game.getControllerId(getSourceId()), game).isEmpty(); } - - @Override - public boolean checkInterveningIfClause(Game game) { - if (getSourcePermanentIfItStillExists(game) != null) { - return getSourcePermanentIfItStillExists(game).isEnchantment(game); - } - return false; - } - -} - -class HiddenPredatorsToken extends TokenImpl { - - public HiddenPredatorsToken() { - super("Beast", "4/4 Beast creature"); - cardType.add(CardType.CREATURE); - subtype.add(SubType.BEAST); - power = new MageInt(4); - toughness = new MageInt(4); - } - - private HiddenPredatorsToken(final HiddenPredatorsToken token) { - super(token); - } - - public HiddenPredatorsToken copy() { - return new HiddenPredatorsToken(this); - } } diff --git a/Mage.Sets/src/mage/cards/h/HiddenSpider.java b/Mage.Sets/src/mage/cards/h/HiddenSpider.java index 411be9b6210..4152cf08d32 100644 --- a/Mage.Sets/src/mage/cards/h/HiddenSpider.java +++ b/Mage.Sets/src/mage/cards/h/HiddenSpider.java @@ -1,30 +1,23 @@ - package mage.cards.h; -import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; -import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.SourceIsEnchantmentCondition; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; 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.constants.Duration; -import mage.filter.StaticFilters; +import mage.constants.SubType; import mage.filter.common.FilterCreatureSpell; import mage.filter.predicate.mageobject.AbilityPredicate; -import mage.game.permanent.token.TokenImpl; +import mage.game.permanent.token.custom.CreatureToken; import java.util.UUID; /** - * * @author LoneFox - * */ public final class HiddenSpider extends CardImpl { @@ -35,13 +28,17 @@ public final class HiddenSpider extends CardImpl { } public HiddenSpider(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{G}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{G}"); // When an opponent casts a creature spell with flying, if Hidden Spider is an enchantment, Hidden Spider becomes a 3/5 Spider creature with reach. - TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new HiddenSpiderToken(), null, Duration.WhileOnBattlefield), - filter, false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_PERMANENT_ENCHANTMENT), - "When an opponent casts a creature spell with flying, if {this} is an enchantment, {this} becomes a 3/5 Spider creature with reach.")); + this.addAbility(new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect( + new CreatureToken( + 3, 5, "3/5 Spider creature with reach", SubType.SPIDER + ).withAbility(ReachAbility.getInstance()), null, Duration.WhileOnBattlefield + ), filter, false) + .withInterveningIf(SourceIsEnchantmentCondition.instance) + .withRuleTextReplacement(true) + .setTriggerPhrase("When an opponent casts a creature spell with flying, ")); } private HiddenSpider(final HiddenSpider card) { @@ -53,22 +50,3 @@ public final class HiddenSpider extends CardImpl { return new HiddenSpider(this); } } - -class HiddenSpiderToken extends TokenImpl { - - public HiddenSpiderToken() { - super("Spider", "3/5 Spider creature with reach"); - cardType.add(CardType.CREATURE); - subtype.add(SubType.SPIDER); - power = new MageInt(3); - toughness = new MageInt(5); - this.addAbility(ReachAbility.getInstance()); - } - private HiddenSpiderToken(final HiddenSpiderToken token) { - super(token); - } - - public HiddenSpiderToken copy() { - return new HiddenSpiderToken(this); - } -} diff --git a/Mage.Sets/src/mage/cards/h/HiddenStag.java b/Mage.Sets/src/mage/cards/h/HiddenStag.java index 6533d548937..7b4764c98e1 100644 --- a/Mage.Sets/src/mage/cards/h/HiddenStag.java +++ b/Mage.Sets/src/mage/cards/h/HiddenStag.java @@ -1,13 +1,11 @@ package mage.cards.h; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.ControllerPlaysLandTriggeredAbility; import mage.abilities.common.OpponentPlaysLandTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.SourceIsEnchantmentCondition; import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.effects.common.continuous.BecomesEnchantmentSourceEffect; import mage.cards.CardImpl; @@ -18,28 +16,33 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.StaticFilters; import mage.game.permanent.token.TokenImpl; +import mage.game.permanent.token.custom.CreatureToken; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class HiddenStag extends CardImpl { + private static final Condition condition = new SourceMatchesFilterCondition( + "this permanent is a creature", StaticFilters.FILTER_PERMANENT_CREATURE + ); + public HiddenStag(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); // Whenever an opponent plays a land, if Hidden Stag is an enchantment, Hidden Stag becomes a 3/2 Elk Beast creature. - Effect effect = new BecomesCreatureSourceEffect(new ElkBeastToken(), null, Duration.WhileOnBattlefield); - TriggeredAbility ability = new OpponentPlaysLandTriggeredAbility(Zone.BATTLEFIELD, effect, false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_PERMANENT_ENCHANTMENT), - "Whenever an opponent plays a land, if Hidden Stag is an enchantment, Hidden Stag becomes a 3/2 Elk Beast creature.")); + this.addAbility(new OpponentPlaysLandTriggeredAbility(new BecomesCreatureSourceEffect( + new CreatureToken( + 3, 2, "3/2 Elk Beast creature", SubType.ELK, SubType.BEAST + ), null, Duration.WhileOnBattlefield + ), false).withInterveningIf(SourceIsEnchantmentCondition.instance).withRuleTextReplacement(true)); // Whenever you play a land, if Hidden Stag is a creature, Hidden Stag becomes an enchantment. - Effect effect2 = new BecomesEnchantmentSourceEffect(); - TriggeredAbility ability2 = new ControllerPlaysLandTriggeredAbility(Zone.BATTLEFIELD, effect2, false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability2, new SourceMatchesFilterCondition(StaticFilters.FILTER_PERMANENT_CREATURE), - "Whenever you play a land, if Hidden Stag is a creature, Hidden Stag becomes an enchantment.")); - + this.addAbility(new ControllerPlaysLandTriggeredAbility( + Zone.BATTLEFIELD, new BecomesEnchantmentSourceEffect(), false + ).withInterveningIf(condition).withRuleTextReplacement(true)); } private HiddenStag(final HiddenStag card) { diff --git a/Mage.Sets/src/mage/cards/h/HideousEnd.java b/Mage.Sets/src/mage/cards/h/HideousEnd.java index 49c15b446f2..d6f7654d76a 100644 --- a/Mage.Sets/src/mage/cards/h/HideousEnd.java +++ b/Mage.Sets/src/mage/cards/h/HideousEnd.java @@ -7,8 +7,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author North @@ -19,7 +22,7 @@ public final class HideousEnd extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{B}{B}"); // Destroy target nonblack creature. Its controller loses 2 life. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); this.getSpellAbility().addEffect(new LoseLifeTargetControllerEffect(2)); } diff --git a/Mage.Sets/src/mage/cards/h/HighFaeNegotiator.java b/Mage.Sets/src/mage/cards/h/HighFaeNegotiator.java index 2d2a92c6cd6..babd14b39ab 100644 --- a/Mage.Sets/src/mage/cards/h/HighFaeNegotiator.java +++ b/Mage.Sets/src/mage/cards/h/HighFaeNegotiator.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.BargainedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.LoseLifeOpponentsEffect; import mage.abilities.keyword.BargainAbility; @@ -36,12 +35,9 @@ public final class HighFaeNegotiator extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When High Fae Negotiator enters the battlefield, if it was bargained, each opponent loses 3 life and you gain 3 life. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new LoseLifeOpponentsEffect(3)), - BargainedCondition.instance, "When {this} enters, " + - "if it was bargained, each opponent loses 3 life and you gain 3 life." - ); - ability.addEffect(new GainLifeEffect(3)); + Ability ability = new EntersBattlefieldTriggeredAbility(new LoseLifeOpponentsEffect(3)) + .withInterveningIf(BargainedCondition.instance); + ability.addEffect(new GainLifeEffect(3).concatBy("and")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HigureTheStillWind.java b/Mage.Sets/src/mage/cards/h/HigureTheStillWind.java index d04baeffddf..5336720e886 100644 --- a/Mage.Sets/src/mage/cards/h/HigureTheStillWind.java +++ b/Mage.Sets/src/mage/cards/h/HigureTheStillWind.java @@ -18,6 +18,7 @@ import mage.constants.SuperType; import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetCreaturePermanent; @@ -52,7 +53,7 @@ public final class HigureTheStillWind extends CardImpl { // {2}: Target Ninja creature can't be blocked this turn. Ability ability = new SimpleActivatedAbility(new CantBeBlockedTargetEffect(), new GenericManaCost(2)); - ability.addTarget(new TargetCreaturePermanent(filterCreature)); + ability.addTarget(new TargetPermanent(filterCreature)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HiredHexblade.java b/Mage.Sets/src/mage/cards/h/HiredHexblade.java index 14f5eebe5a3..520aa5b3e35 100644 --- a/Mage.Sets/src/mage/cards/h/HiredHexblade.java +++ b/Mage.Sets/src/mage/cards/h/HiredHexblade.java @@ -4,14 +4,12 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TreasureSpentToCastCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.LoseLifeSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.watchers.common.ManaPaidSourceWatcher; import java.util.UUID; @@ -29,12 +27,9 @@ public final class HiredHexblade extends CardImpl { this.toughness = new MageInt(2); // When Hired Hexblade enters the battlefield, if mana from a Treasure was spent to cast it, you draw a card and you lose 1 life. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)), - TreasureSpentToCastCondition.instance, "When {this} enters, " + - "if mana from a Treasure was spent to cast it, you draw a card and you lose 1 life." - ); - ability.addEffect(new LoseLifeSourceControllerEffect(1)); + Ability ability = new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1, true)) + .withInterveningIf(TreasureSpentToCastCondition.instance); + ability.addEffect(new LoseLifeSourceControllerEffect(1).concatBy("and")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HistorianOfZhalfir.java b/Mage.Sets/src/mage/cards/h/HistorianOfZhalfir.java index 1891f27128a..9a2553851e5 100644 --- a/Mage.Sets/src/mage/cards/h/HistorianOfZhalfir.java +++ b/Mage.Sets/src/mage/cards/h/HistorianOfZhalfir.java @@ -4,13 +4,11 @@ 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; @@ -20,8 +18,9 @@ import java.util.UUID; */ public final class HistorianOfZhalfir extends CardImpl { - private static final FilterPermanent filter = new FilterControlledPlaneswalkerPermanent(SubType.TEFERI); - private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPlaneswalkerPermanent(SubType.TEFERI, "you control a Teferi planeswalker") + ); public HistorianOfZhalfir(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{U}"); @@ -32,10 +31,7 @@ public final class HistorianOfZhalfir extends CardImpl { 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." - )); + this.addAbility(new AttacksTriggeredAbility(new DrawCardSourceControllerEffect(1), false).withInterveningIf(condition)); } private HistorianOfZhalfir(final HistorianOfZhalfir card) { diff --git a/Mage.Sets/src/mage/cards/h/HistoriansWisdom.java b/Mage.Sets/src/mage/cards/h/HistoriansWisdom.java index c618a02cc7a..62a78cb5fde 100644 --- a/Mage.Sets/src/mage/cards/h/HistoriansWisdom.java +++ b/Mage.Sets/src/mage/cards/h/HistoriansWisdom.java @@ -1,33 +1,32 @@ package mage.cards.h; -import java.util.UUID; - +import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.AttachedToMatchesFilterCondition; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; +import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.continuous.BoostEnchantedEffect; -import mage.constants.ComparisonType; -import mage.constants.SubType; -import mage.abilities.effects.common.AttachEffect; -import mage.constants.Outcome; -import mage.filter.StaticFilters; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.PowerPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.target.TargetPermanent; 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.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; + +import java.util.Optional; +import java.util.UUID; /** - * * @author weirddan455 */ public final class HistoriansWisdom extends CardImpl { @@ -46,17 +45,13 @@ public final class HistoriansWisdom extends CardImpl { this.addAbility(new EnchantAbility(auraTarget)); // When Historian's Wisdom enters the battlefield, if enchanted permanent is a creature with the greatest power among creatures on the battlefield, draw a card. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)), - HistoriansWisdomCondition.instance, - "When {this} enters, if enchanted permanent is a creature with the greatest power among creatures on the battlefield, draw a card." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)) + .withInterveningIf(HistoriansWisdomCondition.instance).addHint(GreatestAmongPermanentsValue.POWER_ALL_CREATURES.getHint())); // As long as enchanted permanent is a creature, it gets +2/+1. this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect( - new BoostEnchantedEffect(2, 1), - creatureCondition, - "As long as enchanted permanent is a creature, it gets +2/+1" + new BoostEnchantedEffect(2, 1), creatureCondition, + "as long as enchanted permanent is a creature, it gets +2/+1" ))); } @@ -75,21 +70,19 @@ enum HistoriansWisdomCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - //game.applyEffects(); // Make sure +2/+1 buff gets applied first - // TODO: not appropriate to call here - investigate where in the engine to apply effects to solve bug - Permanent enchantment = source.getSourcePermanentIfItStillExists(game); - if (enchantment == null) { - return false; - } - Permanent creature = game.getPermanent(enchantment.getAttachedTo()); - if (creature == null) { - return false; - } - if (!creature.isCreature(game)) { - return false; - } - FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(new PowerPredicate(ComparisonType.MORE_THAN, creature.getPower().getValue())); - return game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game).isEmpty(); + return Optional + .ofNullable(source.getSourcePermanentIfItStillExists(game)) + .map(Permanent::getAttachedTo) + .map(game::getPermanent) + .filter(permanent -> permanent.isCreature(game)) + .map(MageObject::getPower) + .map(MageInt::getValue) + .filter(x -> x >= GreatestAmongPermanentsValue.POWER_ALL_CREATURES.calculate(game, source, null)) + .isPresent(); + } + + @Override + public String toString() { + return "enchanted permanent is a creature with the greatest power among creatures on the battlefield"; } } diff --git a/Mage.Sets/src/mage/cards/h/HixusPrisonWarden.java b/Mage.Sets/src/mage/cards/h/HixusPrisonWarden.java index 4fe5e3243fa..2146bba744b 100644 --- a/Mage.Sets/src/mage/cards/h/HixusPrisonWarden.java +++ b/Mage.Sets/src/mage/cards/h/HixusPrisonWarden.java @@ -3,7 +3,6 @@ package mage.cards.h; import mage.MageInt; import mage.abilities.common.DealsDamageToYouAllTriggeredAbility; import mage.abilities.condition.common.SourceEnteredThisTurnCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ExileUntilSourceLeavesEffect; import mage.abilities.keyword.FlashAbility; import mage.cards.CardImpl; @@ -16,13 +15,12 @@ import mage.filter.StaticFilters; import java.util.UUID; /** - * * @author LevelX2 */ public final class HixusPrisonWarden extends CardImpl { public HixusPrisonWarden(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.SOLDIER); @@ -33,11 +31,9 @@ public final class HixusPrisonWarden extends CardImpl { this.addAbility(FlashAbility.getInstance()); // Whenever a creature deals combat damage to you, if Hixus, Prison Warden entered the battlefield this turn, exile that creature until Hixus leaves the battlefield. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new DealsDamageToYouAllTriggeredAbility( + this.addAbility(new DealsDamageToYouAllTriggeredAbility( StaticFilters.FILTER_PERMANENT_CREATURE, new ExileUntilSourceLeavesEffect(), true - ).setTriggerPhrase("Whenever a creature deals combat damage to you, if {this} entered the battlefield this turn, "), - SourceEnteredThisTurnCondition.DID, null - )); + ).withInterveningIf(SourceEnteredThisTurnCondition.DID)); } private HixusPrisonWarden(final HixusPrisonWarden card) { diff --git a/Mage.Sets/src/mage/cards/h/HollowbornBarghest.java b/Mage.Sets/src/mage/cards/h/HollowbornBarghest.java index a693c55dce1..9ce3f80da92 100644 --- a/Mage.Sets/src/mage/cards/h/HollowbornBarghest.java +++ b/Mage.Sets/src/mage/cards/h/HollowbornBarghest.java @@ -1,35 +1,27 @@ package mage.cards.h; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.TriggeredAbility; -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInHandCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.condition.common.HellbentCondition; +import mage.abilities.effects.common.LoseLifeOpponentsEffect; import mage.abilities.effects.common.LoseLifeTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.ComparisonType; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.players.Player; -import mage.target.targetpointer.FixedTarget; +import mage.constants.SubType; +import mage.constants.TargetController; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class HollowbornBarghest extends CardImpl { - private static final String rule = "At the beginning of your upkeep, if you have no cards in hand, each opponent loses 2 life."; + private static final Condition condition = new CardsInHandCondition(ComparisonType.EQUAL_TO, 0, TargetController.ACTIVE); public HollowbornBarghest(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{B}{B}"); @@ -40,17 +32,13 @@ public final class HollowbornBarghest extends CardImpl { this.toughness = new MageInt(6); // At the beginning of your upkeep, if you have no cards in hand, each opponent loses 2 life. - Condition condition = new CardsInHandCondition(ComparisonType.EQUAL_TO, 0); - TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility( - new HollowbornBarghestEffect() - ); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - ability, - condition, - rule)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new LoseLifeOpponentsEffect(2)) + .withInterveningIf(HellbentCondition.instance)); // At the beginning of each opponent's upkeep, if that player has no cards in hand, they lose 2 life. - this.addAbility(new HollowbornBarghestTriggeredAbility()); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + TargetController.OPPONENT, new LoseLifeTargetEffect(2).setText("they lose 2 life"), false + ).withInterveningIf(condition)); } private HollowbornBarghest(final HollowbornBarghest card) { @@ -62,70 +50,3 @@ public final class HollowbornBarghest extends CardImpl { return new HollowbornBarghest(this); } } - -class HollowbornBarghestEffect extends OneShotEffect { - - HollowbornBarghestEffect() { - super(Outcome.Benefit); - staticText = "Each opponent loses 2 life"; - } - - private HollowbornBarghestEffect(final HollowbornBarghestEffect 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) { - game.getPlayer(opponentId).loseLife(2, game, source, false); - } - } - return true; - } - - @Override - public HollowbornBarghestEffect copy() { - return new HollowbornBarghestEffect(this); - } - -} - -class HollowbornBarghestTriggeredAbility extends TriggeredAbilityImpl { - - public HollowbornBarghestTriggeredAbility() { - super(Zone.BATTLEFIELD, new LoseLifeTargetEffect(2)); - } - - private HollowbornBarghestTriggeredAbility(final HollowbornBarghestTriggeredAbility ability) { - super(ability); - } - - @Override - public HollowbornBarghestTriggeredAbility copy() { - return new HollowbornBarghestTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.UPKEEP_STEP_PRE - && game.getOpponents(controllerId).contains(event.getPlayerId()); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - Player opponent = game.getPlayer(event.getPlayerId()); - if (opponent != null - && opponent.getHand().isEmpty()) { - this.getEffects().get(0).setTargetPointer(new FixedTarget(opponent.getId())); - return true; - } - return false; - } - - @Override - public String getRule() { - return "At the beginning of each opponent's upkeep, if that player has no cards in hand, they lose 2 life."; - } -} diff --git a/Mage.Sets/src/mage/cards/h/HollowhengeScavenger.java b/Mage.Sets/src/mage/cards/h/HollowhengeScavenger.java index 0f617393711..50d49eb4428 100644 --- a/Mage.Sets/src/mage/cards/h/HollowhengeScavenger.java +++ b/Mage.Sets/src/mage/cards/h/HollowhengeScavenger.java @@ -1,37 +1,33 @@ - package mage.cards.h; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.MorbidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.hint.common.MorbidHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; +import java.util.UUID; + /** - * * @author nantuko */ public final class HollowhengeScavenger extends CardImpl { - private static final String staticText = "Morbid — When {this} enters, if a creature died this turn, you gain 5 life."; - public HollowhengeScavenger(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}"); this.color.setGreen(true); this.subtype.add(SubType.ELEMENTAL); this.power = new MageInt(4); this.toughness = new MageInt(5); // Morbid — When Hollowhenge Scavenger enters the battlefield, if a creature died this turn, you gain 5 life. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new GainLifeEffect(5)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, MorbidCondition.instance, staticText).addHint(MorbidHint.instance)); + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(5)) + .withInterveningIf(MorbidCondition.instance).setAbilityWord(AbilityWord.MORBID).addHint(MorbidHint.instance)); } private HollowhengeScavenger(final HollowhengeScavenger card) { diff --git a/Mage.Sets/src/mage/cards/h/HomaridShaman.java b/Mage.Sets/src/mage/cards/h/HomaridShaman.java index e954f1ed0da..c49b89824b4 100644 --- a/Mage.Sets/src/mage/cards/h/HomaridShaman.java +++ b/Mage.Sets/src/mage/cards/h/HomaridShaman.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,7 +39,7 @@ public final class HomaridShaman extends CardImpl { // {U}: Tap target green creature. Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new ManaCostsImpl<>("{U}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HomicidalBrute.java b/Mage.Sets/src/mage/cards/h/HomicidalBrute.java index 8fbe94b9423..e9a45b2582c 100644 --- a/Mage.Sets/src/mage/cards/h/HomicidalBrute.java +++ b/Mage.Sets/src/mage/cards/h/HomicidalBrute.java @@ -1,28 +1,32 @@ package mage.cards.h; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.TriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.common.AttackedThisTurnSourceCondition; import mage.abilities.effects.common.TapSourceEffect; import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; 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.watchers.Watcher; + +import java.util.UUID; /** * @author nantuko */ public final class HomicidalBrute extends CardImpl { + private static final Condition condition = new InvertCondition( + AttackedThisTurnSourceCondition.instance, "{this} didn't attack this turn" + ); + public HomicidalBrute(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},""); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.MUTANT); @@ -34,7 +38,9 @@ public final class HomicidalBrute extends CardImpl { this.toughness = new MageInt(1); // At the beginning of your end step, if Homicidal Brute didn't attack this turn, tap Homicidal Brute, then transform it. - this.addAbility(new HomicidalBruteTriggeredAbility(), new HomicidalBruteWatcher()); + TriggeredAbility ability = new BeginningOfEndStepTriggeredAbility(new TapSourceEffect()); + ability.addEffect(new TransformSourceEffect().setText(", then transform it")); + this.addAbility(ability.withInterveningIf(condition)); } private HomicidalBrute(final HomicidalBrute card) { @@ -47,58 +53,3 @@ public final class HomicidalBrute extends CardImpl { } } - -class HomicidalBruteTriggeredAbility extends TriggeredAbilityImpl { - - public HomicidalBruteTriggeredAbility() { - super(Zone.BATTLEFIELD, new TapSourceEffect(), false); - addEffect(new TransformSourceEffect()); - } - - private HomicidalBruteTriggeredAbility(final HomicidalBruteTriggeredAbility ability) { - super(ability); - } - - @Override - public HomicidalBruteTriggeredAbility copy() { - return new HomicidalBruteTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.END_TURN_STEP_PRE; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getPlayerId().equals(this.controllerId)) { - Watcher watcher = game.getState().getWatcher(HomicidalBruteWatcher.class, sourceId); - if (watcher == null || !watcher.conditionMet()) { - return true; - } - } - return false; - } - - @Override - public String getRule() { - return "At the beginning of your end step, if {this} didn't attack this turn, tap {this}, then transform it."; - } -} - -class HomicidalBruteWatcher extends Watcher { - - public HomicidalBruteWatcher() { - super(WatcherScope.CARD); - } - - @Override - public void watch(GameEvent event, Game game) { - if (condition) { - return; - } - if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED && event.getSourceId().equals(sourceId)) { - condition = true; - } - } -} diff --git a/Mage.Sets/src/mage/cards/h/HonoredHierarch.java b/Mage.Sets/src/mage/cards/h/HonoredHierarch.java index ee5d1b50931..ce7bd5aecf2 100644 --- a/Mage.Sets/src/mage/cards/h/HonoredHierarch.java +++ b/Mage.Sets/src/mage/cards/h/HonoredHierarch.java @@ -1,13 +1,10 @@ - package mage.cards.h; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.RenownedSourceCondition; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.RenownAbility; import mage.abilities.keyword.VigilanceAbility; @@ -15,18 +12,18 @@ import mage.abilities.mana.AnyColorManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class HonoredHierarch extends CardImpl { public HonoredHierarch(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.DRUID); this.power = new MageInt(1); @@ -36,18 +33,15 @@ public final class HonoredHierarch extends CardImpl { this.addAbility(new RenownAbility(1)); // As long as Honored Hierarch is renowned, it has vigilance and "{T}: Add one mana of any color." - Effect effect = new ConditionalContinuousEffect( + Ability ability = new SimpleStaticAbility(new ConditionalContinuousEffect( new GainAbilitySourceEffect(VigilanceAbility.getInstance(), Duration.WhileOnBattlefield), - RenownedSourceCondition.instance, - "As long as {this} is renowned, it has vigilance"); - Ability ability = new SimpleStaticAbility(effect); - effect = new ConditionalContinuousEffect( + RenownedSourceCondition.THIS, "as long as {this} is renowned, it has vigilance" + )); + ability.addEffect(new ConditionalContinuousEffect( new GainAbilitySourceEffect(new AnyColorManaAbility(), Duration.WhileOnBattlefield), - RenownedSourceCondition.instance, - "and \"{T}: Add one mana of any color.\""); - ability.addEffect(effect); - this.addAbility(ability); - + RenownedSourceCondition.THIS, "and \"{T}: Add one mana of any color.\"" + )); + this.addAbility(ability); } private HonoredHierarch(final HonoredHierarch card) { diff --git a/Mage.Sets/src/mage/cards/h/HoofSkulkin.java b/Mage.Sets/src/mage/cards/h/HoofSkulkin.java index 8f333f5b79b..1807ef2ff62 100644 --- a/Mage.Sets/src/mage/cards/h/HoofSkulkin.java +++ b/Mage.Sets/src/mage/cards/h/HoofSkulkin.java @@ -16,6 +16,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -36,7 +37,7 @@ public final class HoofSkulkin extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(1, 1, Duration.EndOfTurn), new GenericManaCost(3)); - ability.addTarget(new TargetCreaturePermanent(filterGreenCreature)); + ability.addTarget(new TargetPermanent(filterGreenCreature)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HoofprintsOfTheStag.java b/Mage.Sets/src/mage/cards/h/HoofprintsOfTheStag.java index 3c7458d5d71..88615cac9b5 100644 --- a/Mage.Sets/src/mage/cards/h/HoofprintsOfTheStag.java +++ b/Mage.Sets/src/mage/cards/h/HoofprintsOfTheStag.java @@ -8,12 +8,10 @@ import mage.abilities.costs.common.RemoveCountersSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; -import mage.abilities.hint.common.MyTurnHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.counters.CounterType; import mage.game.permanent.token.WhiteElementalToken; @@ -29,12 +27,16 @@ public final class HoofprintsOfTheStag extends CardImpl { this.subtype.add(SubType.ELEMENTAL); // Whenever you draw a card, you may put a hoofprint counter on Hoofprints of the Stag. - this.addAbility(new DrawCardControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.HOOFPRINT.createInstance(1)), true)); + this.addAbility(new DrawCardControllerTriggeredAbility( + new AddCountersSourceEffect(CounterType.HOOFPRINT.createInstance(1)), true + )); // {2}{w}, Remove four hoofprint counters from Hoofprints of the Stag: Create a 4/4 white Elemental creature token with flying. Activate this ability only during your turn. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new WhiteElementalToken(), 1), new ManaCostsImpl<>("{2}{W}"), MyTurnCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new CreateTokenEffect(new WhiteElementalToken(), 1), + new ManaCostsImpl<>("{2}{W}"), MyTurnCondition.instance + ); ability.addCost(new RemoveCountersSourceCost(CounterType.HOOFPRINT.createInstance(4))); - ability.addHint(MyTurnHint.instance); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HopeAndGlory.java b/Mage.Sets/src/mage/cards/h/HopeAndGlory.java index 5beaad2d784..2eaaebf0829 100644 --- a/Mage.Sets/src/mage/cards/h/HopeAndGlory.java +++ b/Mage.Sets/src/mage/cards/h/HopeAndGlory.java @@ -1,7 +1,5 @@ - package mage.cards.h; -import java.util.UUID; import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.cards.CardImpl; @@ -10,15 +8,15 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author Plopman */ public final class HopeAndGlory extends CardImpl { public HopeAndGlory(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W}"); - + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}"); // Untap two target creatures. Each of them gets +1/+1 until end of turn. this.getSpellAbility().addEffect(new UntapTargetEffect()); diff --git a/Mage.Sets/src/mage/cards/h/HopeEstheim.java b/Mage.Sets/src/mage/cards/h/HopeEstheim.java index 0b53b059cb2..e0fa4b4199c 100644 --- a/Mage.Sets/src/mage/cards/h/HopeEstheim.java +++ b/Mage.Sets/src/mage/cards/h/HopeEstheim.java @@ -11,6 +11,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; import mage.constants.TargetController; +import mage.watchers.common.PlayerGainedLifeWatcher; import java.util.UUID; @@ -34,7 +35,7 @@ public final class HopeEstheim extends CardImpl { // At the beginning of your end step, each opponent mills X cards, where X is the amount of life you gained this turn. this.addAbility(new BeginningOfEndStepTriggeredAbility(new MillCardsEachPlayerEffect( ControllerGainedLifeCount.instance, TargetController.OPPONENT - ))); + )), new PlayerGainedLifeWatcher()); } private HopeEstheim(final HopeEstheim card) { diff --git a/Mage.Sets/src/mage/cards/h/HopefulInitiate.java b/Mage.Sets/src/mage/cards/h/HopefulInitiate.java index 01197fc5adf..9a2d8e2e2b7 100644 --- a/Mage.Sets/src/mage/cards/h/HopefulInitiate.java +++ b/Mage.Sets/src/mage/cards/h/HopefulInitiate.java @@ -1,24 +1,24 @@ package mage.cards.h; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.RemoveCounterCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.DestroyTargetEffect; -import mage.constants.SubType; import mage.abilities.keyword.TrainingAbility; 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.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; +import java.util.UUID; + /** - * * @author weirddan455 */ public final class HopefulInitiate extends CardImpl { @@ -37,8 +37,7 @@ public final class HopefulInitiate extends CardImpl { // {2}{W}, Remove two +1/+1 counters from among creatures you control: Destroy target artifact or enchantment. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new ManaCostsImpl<>("{2}{W}")); ability.addCost(new RemoveCounterCost( - new TargetControlledCreaturePermanent(1, 2, StaticFilters.FILTER_CONTROLLED_CREATURES, true), - CounterType.P1P1, 2 + new TargetControlledCreaturePermanent(1, 2), CounterType.P1P1, 2 ).setText("Remove two +1/+1 counters from among creatures you control")); ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/h/HornOfTheMark.java b/Mage.Sets/src/mage/cards/h/HornOfTheMark.java index 5b171cc7533..b59d54fb0bf 100644 --- a/Mage.Sets/src/mage/cards/h/HornOfTheMark.java +++ b/Mage.Sets/src/mage/cards/h/HornOfTheMark.java @@ -1,18 +1,14 @@ package mage.cards.h; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility; import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.PutCards; +import mage.constants.SetTargetPointer; import mage.constants.SuperType; -import mage.constants.Zone; import mage.filter.StaticFilters; -import mage.game.Controllable; -import mage.game.Game; -import mage.game.events.DefenderAttackedEvent; -import mage.game.events.GameEvent; import java.util.UUID; @@ -27,7 +23,9 @@ public final class HornOfTheMark extends CardImpl { this.supertype.add(SuperType.LEGENDARY); // Whenever two or more creatures you control attack a player, look at the top five cards of your library. You may reveal a creature 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 HornOfTheMarkTriggeredAbility()); + this.addAbility(new AttacksPlayerWithCreaturesTriggeredAbility( + new LookLibraryAndPickControllerEffect(5, 1, StaticFilters.FILTER_CARD_CREATURE_A, PutCards.HAND, PutCards.BOTTOM_RANDOM), + 2, StaticFilters.FILTER_CONTROLLED_CREATURES, SetTargetPointer.NONE, false)); } private HornOfTheMark(final HornOfTheMark card) { @@ -39,39 +37,3 @@ public final class HornOfTheMark extends CardImpl { return new HornOfTheMark(this); } } - -class HornOfTheMarkTriggeredAbility extends TriggeredAbilityImpl { - - HornOfTheMarkTriggeredAbility() { - super(Zone.BATTLEFIELD, new LookLibraryAndPickControllerEffect( - 5, 1, StaticFilters.FILTER_CARD_CREATURE_A, PutCards.HAND, PutCards.BOTTOM_RANDOM - )); - this.setTriggerPhrase("Whenever two or more creatures you control attack a player, "); - } - - private HornOfTheMarkTriggeredAbility(final HornOfTheMarkTriggeredAbility ability) { - super(ability); - } - - @Override - public HornOfTheMarkTriggeredAbility copy() { - return new HornOfTheMarkTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DEFENDER_ATTACKED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - DefenderAttackedEvent dEvent = ((DefenderAttackedEvent) event); - return game.getPlayer(dEvent.getTargetId()) != null - && dEvent - .getAttackers(game) - .stream() - .map(Controllable::getControllerId) - .filter(this::isControlledBy) - .count() >= 2; - } -} diff --git a/Mage.Sets/src/mage/cards/h/HorobisWhisper.java b/Mage.Sets/src/mage/cards/h/HorobisWhisper.java index f26312d400b..70c2b4cc48d 100644 --- a/Mage.Sets/src/mage/cards/h/HorobisWhisper.java +++ b/Mage.Sets/src/mage/cards/h/HorobisWhisper.java @@ -12,11 +12,14 @@ import mage.constants.SubType; import mage.filter.FilterCard; import mage.filter.StaticFilters; import mage.filter.common.FilterLandPermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author LevelX2 @@ -36,7 +39,7 @@ public final class HorobisWhisper extends CardImpl { // If you control a Swamp, destroy target nonblack creature. this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new DestroyTargetEffect(), new PermanentsOnTheBattlefieldCondition(filterCondition),"If you control a Swamp, destroy target nonblack creature")); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK).withChooseHint("destroy if you control a Swamp")); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK).withChooseHint("destroy if you control a Swamp")); // Splice onto Arcane-Exile four cards from your graveyard. this.addAbility(new SpliceAbility(SpliceAbility.ARCANE, new ExileFromGraveCost(new TargetCardInYourGraveyard(4,4, new FilterCard("cards"))))); diff --git a/Mage.Sets/src/mage/cards/h/HorrorOfHorrors.java b/Mage.Sets/src/mage/cards/h/HorrorOfHorrors.java index 989f256ab96..5e2b61d33a8 100644 --- a/Mage.Sets/src/mage/cards/h/HorrorOfHorrors.java +++ b/Mage.Sets/src/mage/cards/h/HorrorOfHorrors.java @@ -15,6 +15,7 @@ import mage.constants.Zone; import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; @@ -38,7 +39,7 @@ public final class HorrorOfHorrors extends CardImpl { // Sacrifice a Swamp: Regenerate target black creature. Ability ability = new SimpleActivatedAbility(new RegenerateTargetEffect(), new SacrificeTargetCost(filter1)); - ability.addTarget(new TargetCreaturePermanent(filter2)); + ability.addTarget(new TargetPermanent(filter2)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HostileTakeover.java b/Mage.Sets/src/mage/cards/h/HostileTakeover.java index 1f46d00b90b..58bc4554208 100644 --- a/Mage.Sets/src/mage/cards/h/HostileTakeover.java +++ b/Mage.Sets/src/mage/cards/h/HostileTakeover.java @@ -1,7 +1,5 @@ package mage.cards.h; -import java.util.UUID; - import mage.abilities.effects.common.DamageAllEffect; import mage.abilities.effects.common.continuous.SetBasePowerToughnessTargetEffect; import mage.cards.CardImpl; @@ -9,41 +7,33 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.filter.StaticFilters; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.other.AnotherTargetPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.SecondTargetPointer; +import java.util.UUID; + /** - * * @author weirddan455 */ public final class HostileTakeover extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other target creature"); - - static { - filter.add(new AnotherTargetPredicate(2)); - } - public HostileTakeover(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{U}{B}{R}"); // Up to one target creature has base power and toughness 1/1 until end of turn. Up to one other target creature has base power and toughness 4/4 until end of turn. Then Hostile Takeover deals 3 damage to each creature. this.getSpellAbility().addEffect(new SetBasePowerToughnessTargetEffect(1, 1, Duration.EndOfTurn)); - TargetCreaturePermanent target1 = new TargetCreaturePermanent(0, 1); - target1.setTargetTag(1); - this.getSpellAbility().addTarget(target1.withChooseHint("1/1")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 1).setTargetTag(1).withChooseHint("1/1")); this.getSpellAbility().addEffect(new SetBasePowerToughnessTargetEffect(4, 4, Duration.EndOfTurn) .setTargetPointer(new SecondTargetPointer()) .setText("up to one other target creature has base power and toughness 4/4 until end of turn")); - TargetCreaturePermanent target2 = new TargetCreaturePermanent(0, 1, filter, false); - target2.setTargetTag(2); - this.getSpellAbility().addTarget(target2.withChooseHint("4/4")); - - this.getSpellAbility().addEffect(new DamageAllEffect(3, StaticFilters.FILTER_PERMANENT_CREATURE) - .concatBy("Then")); + this.getSpellAbility().addTarget(new TargetPermanent( + 0, 1, StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2 + ).setTargetTag(2).withChooseHint("4/4")); + this.getSpellAbility().addEffect(new DamageAllEffect( + 3, StaticFilters.FILTER_PERMANENT_CREATURE + ).concatBy("Then")); } private HostileTakeover(final HostileTakeover card) { diff --git a/Mage.Sets/src/mage/cards/h/HowlOfTheHunt.java b/Mage.Sets/src/mage/cards/h/HowlOfTheHunt.java index ee56e741fcd..85745107d0d 100644 --- a/Mage.Sets/src/mage/cards/h/HowlOfTheHunt.java +++ b/Mage.Sets/src/mage/cards/h/HowlOfTheHunt.java @@ -4,7 +4,7 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.AttachedToMatchesFilterCondition; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.UntapAttachedEffect; import mage.abilities.effects.common.continuous.BoostEnchantedEffect; @@ -14,9 +14,12 @@ import mage.abilities.keyword.FlashAbility; import mage.abilities.keyword.VigilanceAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; @@ -27,6 +30,17 @@ import java.util.UUID; */ public final class HowlOfTheHunt extends CardImpl { + private static final FilterPermanent filter = new FilterPermanent("enchanted creature is a Wolf or Werewolf"); + + static { + filter.add(Predicates.or( + SubType.WOLF.getPredicate(), + SubType.WEREWOLF.getPredicate() + )); + } + + private static final Condition condition = new AttachedToMatchesFilterCondition(filter); + public HowlOfTheHunt(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); @@ -39,20 +53,17 @@ public final class HowlOfTheHunt extends CardImpl { TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // When Howl of the Hunt enters the battlefield, if enchanted creature is a Wolf or Werewolf, untap that creature. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new UntapAttachedEffect()), - HowlOfTheHuntCondition.instance, "When {this} enters, " + - "if enchanted creature is a Wolf or Werewolf, untap that creature." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new UntapAttachedEffect().setText("untap that creature") + ).withInterveningIf(condition)); // Enchanted creature gets +2/+2 and has vigilance. - ability = new SimpleStaticAbility(new BoostEnchantedEffect(2, 2)); + Ability ability = new SimpleStaticAbility(new BoostEnchantedEffect(2, 2)); ability.addEffect(new GainAbilityAttachedEffect( - VigilanceAbility.getInstance(), AttachmentType.AURA, Duration.WhileOnBattlefield + VigilanceAbility.getInstance(), AttachmentType.AURA ).setText("and has vigilance")); this.addAbility(ability); } @@ -66,22 +77,3 @@ public final class HowlOfTheHunt extends CardImpl { return new HowlOfTheHunt(this); } } - -enum HowlOfTheHuntCondition implements Condition { - instance; - - @Override - public boolean apply(Game game, Ability source) { - Permanent enchantment = source.getSourcePermanentIfItStillExists(game); - if (enchantment == null) { - return false; - } - Permanent creature = game.getPermanent(enchantment.getAttachedTo()); - return creature != null && creature.hasSubtype(SubType.WOLF, game) || creature.hasSubtype(SubType.WEREWOLF, game); - } - - @Override - public String toString() { - return ""; - } -} diff --git a/Mage.Sets/src/mage/cards/h/HuaTuoHonoredPhysician.java b/Mage.Sets/src/mage/cards/h/HuaTuoHonoredPhysician.java index 9b62ed46a62..173ab53fb89 100644 --- a/Mage.Sets/src/mage/cards/h/HuaTuoHonoredPhysician.java +++ b/Mage.Sets/src/mage/cards/h/HuaTuoHonoredPhysician.java @@ -1,7 +1,5 @@ - package mage.cards.h; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; @@ -13,12 +11,12 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; -import mage.constants.Zone; import mage.filter.StaticFilters; import mage.target.common.TargetCardInYourGraveyard; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class HuaTuoHonoredPhysician extends CardImpl { @@ -32,7 +30,10 @@ public final class HuaTuoHonoredPhysician extends CardImpl { this.toughness = new MageInt(2); // {tap}: Put target creature card from your graveyard on top of your library. Activate this ability only during your turn, before attackers are declared. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new PutOnLibraryTargetEffect(true), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new PutOnLibraryTargetEffect(true), new TapSourceCost(), + MyTurnBeforeAttackersDeclaredCondition.instance + ); ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HuatliDinosaurKnight.java b/Mage.Sets/src/mage/cards/h/HuatliDinosaurKnight.java index 32a647c58cf..904d47ffe53 100644 --- a/Mage.Sets/src/mage/cards/h/HuatliDinosaurKnight.java +++ b/Mage.Sets/src/mage/cards/h/HuatliDinosaurKnight.java @@ -7,27 +7,29 @@ import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.counters.CounterType; +import mage.filter.FilterPermanent; import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author TheElk801 */ public final class HuatliDinosaurKnight extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Dinosaur you control"); - private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("Dinosaurs"); - - static { - filter.add(SubType.DINOSAUR.getPredicate()); - filter.add(TargetController.YOU.getControllerPredicate()); - filter2.add(SubType.DINOSAUR.getPredicate()); - } + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.DINOSAUR); + private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent(SubType.DINOSAUR, "Dinosaurs"); public HuatliDinosaurKnight(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{4}{R}{W}"); @@ -41,13 +43,13 @@ public final class HuatliDinosaurKnight extends CardImpl { Ability ability = new LoyaltyAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance(2)) .setText("Put two +1/+1 counters on up to one target Dinosaur you control."), 2 ); - ability.addTarget(new TargetCreaturePermanent(0, 1, filter, false)); + ability.addTarget(new TargetPermanent(0, 1, filter)); this.addAbility(ability); // -3: Target Dinosaur you control deals damage equal to its power to target creature you don't control. ability = new LoyaltyAbility(new DamageWithPowerFromOneToAnotherTargetEffect(), -3); - ability.addTarget(new TargetCreaturePermanent(filter)); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + ability.addTarget(new TargetPermanent(filter)); + ability.addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.addAbility(ability); // -7: Dinosaurs you control get +4/+4 until end of turn. diff --git a/Mage.Sets/src/mage/cards/h/HumbleDefector.java b/Mage.Sets/src/mage/cards/h/HumbleDefector.java index c647ca1a29a..c09f361f792 100644 --- a/Mage.Sets/src/mage/cards/h/HumbleDefector.java +++ b/Mage.Sets/src/mage/cards/h/HumbleDefector.java @@ -7,12 +7,10 @@ import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.TargetPlayerGainControlSourceEffect; -import mage.abilities.hint.common.MyTurnHint; 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; @@ -30,13 +28,12 @@ public final class HumbleDefector extends CardImpl { this.toughness = new MageInt(1); // {T}: Draw two cards. Target opponent gains control of Humble Defector. Activate this ability only during your turn. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new DrawCardSourceControllerEffect(2), new TapSourceCost(), MyTurnCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new DrawCardSourceControllerEffect(2), new TapSourceCost(), MyTurnCondition.instance + ); ability.addEffect(new TargetPlayerGainControlSourceEffect()); ability.addTarget(new TargetOpponent()); - ability.addHint(MyTurnHint.instance); this.addAbility(ability); - } private HumbleDefector(final HumbleDefector card) { diff --git a/Mage.Sets/src/mage/cards/h/HumbleTheBrute.java b/Mage.Sets/src/mage/cards/h/HumbleTheBrute.java index be68937a031..4a3d0de5d16 100644 --- a/Mage.Sets/src/mage/cards/h/HumbleTheBrute.java +++ b/Mage.Sets/src/mage/cards/h/HumbleTheBrute.java @@ -10,6 +10,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -29,7 +30,7 @@ public final class HumbleTheBrute extends CardImpl { // Destroy target creature with power 4 or greater. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // Investigate. this.getSpellAbility().addEffect(new InvestigateEffect().concatBy("
")); diff --git a/Mage.Sets/src/mage/cards/h/HundredTalonStrike.java b/Mage.Sets/src/mage/cards/h/HundredTalonStrike.java index 2868cdbf4c6..8eee68b787e 100644 --- a/Mage.Sets/src/mage/cards/h/HundredTalonStrike.java +++ b/Mage.Sets/src/mage/cards/h/HundredTalonStrike.java @@ -2,7 +2,6 @@ package mage.cards.h; import mage.ObjectColor; import mage.abilities.costs.common.TapTargetCost; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.FirstStrikeAbility; @@ -13,40 +12,40 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; /** - * * @author LevelX2 */ public final class HundredTalonStrike extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped white creature you control"); + private static final FilterControlledPermanent filter = new FilterControlledCreaturePermanent("untapped white creature you control"); + static { filter.add(TappedPredicate.UNTAPPED); filter.add(new ColorPredicate(ObjectColor.WHITE)); } public HundredTalonStrike(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{W}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}"); this.subtype.add(SubType.ARCANE); // Target creature gets +1/+0 and gains first strike until end of turn. - Effect effect = new BoostTargetEffect(1,0, Duration.EndOfTurn); - effect.setText("Target creature gets +1/+0"); - this.getSpellAbility().addEffect(effect); - effect = new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn); - effect.setText("and gains first strike until end of turn"); - this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addEffect(new BoostTargetEffect(1, 0).setText("Target creature gets +1/+0")); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect( + FirstStrikeAbility.getInstance(), Duration.EndOfTurn + ).setText("and gains first strike until end of turn")); this.getSpellAbility().addTarget(new TargetCreaturePermanent().withChooseHint("+1/+0 and first strike")); + // Splice onto Arcane-Tap an untapped white creature you control. - this.addAbility(new SpliceAbility(SpliceAbility.ARCANE, new TapTargetCost(new TargetControlledCreaturePermanent(1,1,filter,false)))); + this.addAbility(new SpliceAbility(SpliceAbility.ARCANE, new TapTargetCost(new TargetControlledPermanent(filter)))); } private HundredTalonStrike(final HundredTalonStrike card) { diff --git a/Mage.Sets/src/mage/cards/h/HuntDown.java b/Mage.Sets/src/mage/cards/h/HuntDown.java index 7aacfd24871..d66059f3131 100644 --- a/Mage.Sets/src/mage/cards/h/HuntDown.java +++ b/Mage.Sets/src/mage/cards/h/HuntDown.java @@ -11,6 +11,7 @@ import mage.constants.Duration; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.watchers.common.BlockedAttackerWatcher; @@ -31,8 +32,8 @@ public final class HuntDown extends CardImpl { // Target creature blocks target creature this turn if able. this.getSpellAbility().addEffect(new HuntDownEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filterMustBlock)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filterToBeBlocked)); + this.getSpellAbility().addTarget(new TargetPermanent(filterMustBlock)); + this.getSpellAbility().addTarget(new TargetPermanent(filterToBeBlocked)); } diff --git a/Mage.Sets/src/mage/cards/h/HuntTheHunter.java b/Mage.Sets/src/mage/cards/h/HuntTheHunter.java index 8e17f86a2b8..dcaad9da873 100644 --- a/Mage.Sets/src/mage/cards/h/HuntTheHunter.java +++ b/Mage.Sets/src/mage/cards/h/HuntTheHunter.java @@ -1,35 +1,30 @@ - package mage.cards.h; -import java.util.UUID; import mage.ObjectColor; -import mage.abilities.effects.Effect; 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.constants.TargetController; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.common.FilterOpponentsCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; -import mage.target.Target; -import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class HuntTheHunter extends CardImpl { - private static final FilterControlledCreaturePermanent filterControlledGreen = new FilterControlledCreaturePermanent("green creature you control"); - private static final FilterCreaturePermanent filterOpponentGreen = new FilterCreaturePermanent("green creature an opponent controls"); + private static final FilterControlledPermanent filterControlledGreen = new FilterControlledCreaturePermanent("green creature you control"); + private static final FilterPermanent filterOpponentGreen = new FilterOpponentsCreaturePermanent("green creature an opponent controls"); static { filterControlledGreen.add(new ColorPredicate(ObjectColor.GREEN)); - filterOpponentGreen.add(TargetController.OPPONENT.getControllerPredicate()); filterOpponentGreen.add(new ColorPredicate(ObjectColor.GREEN)); } @@ -37,15 +32,10 @@ public final class HuntTheHunter extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{G}"); // Target green creature you control gets +2/+2 until end of turn. It fights target green creature an opponent controls. - Effect effect = new BoostTargetEffect(2, 2, Duration.EndOfTurn); - this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(1, 1, filterControlledGreen, false)); - - effect = new FightTargetsEffect(); - effect.setText("It fights target green creature an opponent controls"); - this.getSpellAbility().addEffect(effect); - Target target = new TargetCreaturePermanent(filterOpponentGreen); - this.getSpellAbility().addTarget(target); + this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2)); + this.getSpellAbility().addTarget(new TargetPermanent(filterControlledGreen)); + this.getSpellAbility().addEffect(new FightTargetsEffect().setText("It fights target green creature an opponent controls")); + this.getSpellAbility().addTarget(new TargetPermanent(filterOpponentGreen)); } private HuntTheHunter(final HuntTheHunter card) { diff --git a/Mage.Sets/src/mage/cards/h/HuntTheWeak.java b/Mage.Sets/src/mage/cards/h/HuntTheWeak.java index 7243ab70a31..e678cede5d2 100644 --- a/Mage.Sets/src/mage/cards/h/HuntTheWeak.java +++ b/Mage.Sets/src/mage/cards/h/HuntTheWeak.java @@ -7,11 +7,14 @@ 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 mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author LevelX2 */ @@ -27,7 +30,7 @@ public final class HuntTheWeak extends CardImpl { "(Each deals damage equal to its power to the other.)" )); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); } private HuntTheWeak(final HuntTheWeak card) { diff --git a/Mage.Sets/src/mage/cards/h/HunterOfEyeblights.java b/Mage.Sets/src/mage/cards/h/HunterOfEyeblights.java index 1656e05c8a3..a73d454e339 100644 --- a/Mage.Sets/src/mage/cards/h/HunterOfEyeblights.java +++ b/Mage.Sets/src/mage/cards/h/HunterOfEyeblights.java @@ -16,10 +16,13 @@ import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.CounterAnyPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author Styxo */ @@ -40,13 +43,13 @@ public final class HunterOfEyeblights extends CardImpl { // When Hunter of Eyeblights enters the battlefield, put a +1/+1 counter on target creature you don't control Ability ability = new EntersBattlefieldTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance())); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + ability.addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.addAbility(ability); //{B}{2},{T}: Destroy target creature with a counter on it. Ability ability2 = new SimpleActivatedAbility(new DestroyTargetEffect(), new ManaCostsImpl<>("{2}{B}")); ability2.addCost(new TapSourceCost()); - ability2.addTarget(new TargetCreaturePermanent(filter)); + ability2.addTarget(new TargetPermanent(filter)); this.addAbility(ability2); } diff --git a/Mage.Sets/src/mage/cards/h/HuntingDrake.java b/Mage.Sets/src/mage/cards/h/HuntingDrake.java index 2cf3e212de2..6e102407b8c 100644 --- a/Mage.Sets/src/mage/cards/h/HuntingDrake.java +++ b/Mage.Sets/src/mage/cards/h/HuntingDrake.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class HuntingDrake extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When Hunting Drake enters the battlefield, put target red or green creature on top of its owner's library. Ability ability = new EntersBattlefieldTriggeredAbility(new PutOnLibraryTargetEffect(true)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HuntingKavu.java b/Mage.Sets/src/mage/cards/h/HuntingKavu.java index 071d00b2bfc..42c90188b4d 100644 --- a/Mage.Sets/src/mage/cards/h/HuntingKavu.java +++ b/Mage.Sets/src/mage/cards/h/HuntingKavu.java @@ -18,6 +18,7 @@ import mage.constants.Zone; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; import mage.filter.common.FilterCreatureAttackingYou; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -43,7 +44,7 @@ public final class HuntingKavu extends CardImpl { Ability ability = new SimpleActivatedAbility(new ExileSourceEffect(), new ManaCostsImpl<>("{1}{R}{G}")); ability.addCost(new TapSourceCost()); ability.addEffect(new ExileTargetEffect().setText("and target creature without flying that's attacking you")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/Hydradoodle.java b/Mage.Sets/src/mage/cards/h/Hydradoodle.java index 2ac9d494f88..7b7d35c0bb2 100644 --- a/Mage.Sets/src/mage/cards/h/Hydradoodle.java +++ b/Mage.Sets/src/mage/cards/h/Hydradoodle.java @@ -1,9 +1,8 @@ - package mage.cards.h; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.ReachAbility; import mage.abilities.keyword.TrampleAbility; @@ -13,8 +12,6 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; import mage.counters.CounterType; -import mage.filter.FilterPermanent; -import mage.filter.predicate.permanent.CounterAnyPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -38,10 +35,8 @@ public final class Hydradoodle extends CardImpl { this.toughness = new MageInt(0); // As Hydradoodle enters the battlefield, roll X six-sided dice. Hydradoodle enters the battlefield with a number of +1/+1 counters on it equal to the total of those results. - this.addAbility(new EntersBattlefieldAbility(new HydradoodleEffect(), - null, - "As {this} enters, roll X six-sided dice. {this} enters with a number of +1/+1 counters on it equal to the total of those results", - null)); + this.addAbility(new AsEntersBattlefieldAbility(new HydradoodleEffect())); + // Reach this.addAbility(ReachAbility.getInstance()); @@ -61,12 +56,6 @@ public final class Hydradoodle extends CardImpl { class HydradoodleEffect extends OneShotEffect { - private static final FilterPermanent filter = new FilterPermanent("permanent with a counter"); - - static { - filter.add(CounterAnyPredicate.instance); - } - HydradoodleEffect() { super(Outcome.BoostCreature); this.staticText = "roll X six-sided dice. {this} enters with a number of +1/+1 counters on it equal to the total of those results"; diff --git a/Mage.Sets/src/mage/cards/h/Hypnox.java b/Mage.Sets/src/mage/cards/h/Hypnox.java index 2c35fc0b52d..8f3ebd248db 100644 --- a/Mage.Sets/src/mage/cards/h/Hypnox.java +++ b/Mage.Sets/src/mage/cards/h/Hypnox.java @@ -5,7 +5,6 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.LeavesBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromHandSourcePermanentCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ReturnFromExileForSourceEffect; import mage.abilities.keyword.FlyingAbility; @@ -39,11 +38,8 @@ public final class Hypnox extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When Hypnox enters the battlefield, if you cast it from your hand, exile all cards from target opponent's hand. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new HypnoxExileEffect()), - CastFromHandSourcePermanentCondition.instance, "When {this} enters, " + - "if you cast it from your hand, exile all cards from target opponent's hand." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new HypnoxExileEffect()) + .withInterveningIf(CastFromHandSourcePermanentCondition.instance); ability.addTarget(new TargetOpponent()); this.addAbility(ability, new CastFromHandWatcher()); @@ -66,7 +62,7 @@ class HypnoxExileEffect extends OneShotEffect { HypnoxExileEffect() { super(Outcome.Exile); - staticText = "Exile all cards from target opponent's hand"; + staticText = "exile all cards from target opponent's hand"; } private HypnoxExileEffect(final HypnoxExileEffect effect) { diff --git a/Mage.Sets/src/mage/cards/i/IanTheReckless.java b/Mage.Sets/src/mage/cards/i/IanTheReckless.java index 7375f219b0f..f809522becf 100644 --- a/Mage.Sets/src/mage/cards/i/IanTheReckless.java +++ b/Mage.Sets/src/mage/cards/i/IanTheReckless.java @@ -1,11 +1,10 @@ package mage.cards.i; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.SourcePermanentPowerValue; import mage.abilities.effects.common.DamageControllerEffect; import mage.abilities.effects.common.DamageTargetEffect; @@ -25,7 +24,7 @@ import java.util.UUID; */ public final class IanTheReckless extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent(); + private static final FilterPermanent filter = new FilterPermanent("it's modified"); static { filter.add(ModifiedPredicate.instance); @@ -43,12 +42,11 @@ public final class IanTheReckless extends CardImpl { this.toughness = new MageInt(1); // Whenever Ian the Reckless attacks, if it's modified, you may have it deal damage equal to its power to you and any target. - TriggeredAbility ability = new AttacksTriggeredAbility(new DamageControllerEffect( - SourcePermanentPowerValue.NOT_NEGATIVE).setText("have it deal damage equal to its power to you"), true); + Ability ability = new AttacksTriggeredAbility(new DamageControllerEffect(SourcePermanentPowerValue.NOT_NEGATIVE) + .setText("have it deal damage equal to its power to you"), true).withInterveningIf(condition); ability.addEffect(new DamageTargetEffect(SourcePermanentPowerValue.NOT_NEGATIVE).setText("and any target")); ability.addTarget(new TargetAnyTarget()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, condition, - "Whenever {this} attacks, if it's modified, you may have it deal damage equal to its power to you and any target.")); + this.addAbility(ability); } private IanTheReckless(final IanTheReckless card) { diff --git a/Mage.Sets/src/mage/cards/i/IcatianLieutenant.java b/Mage.Sets/src/mage/cards/i/IcatianLieutenant.java index c86b7a5b6e2..31c9d479699 100644 --- a/Mage.Sets/src/mage/cards/i/IcatianLieutenant.java +++ b/Mage.Sets/src/mage/cards/i/IcatianLieutenant.java @@ -14,6 +14,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -37,7 +38,7 @@ public final class IcatianLieutenant extends CardImpl { // {1}{W}: Target Soldier creature gets +1/+0 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl<>("{1}{W}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/i/IcatianMoneychanger.java b/Mage.Sets/src/mage/cards/i/IcatianMoneychanger.java index 3c26f0ea22b..6be449221af 100644 --- a/Mage.Sets/src/mage/cards/i/IcatianMoneychanger.java +++ b/Mage.Sets/src/mage/cards/i/IcatianMoneychanger.java @@ -1,55 +1,53 @@ - package mage.cards.i; -import java.util.UUID; import mage.MageInt; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.SacrificeSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; import mage.abilities.dynamicvalue.common.CountersSourceCount; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DamageControllerEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.PhaseStep; -import mage.constants.Zone; import mage.counters.CounterType; +import java.util.UUID; + /** - * * @author fireshoes */ public final class IcatianMoneychanger extends CardImpl { public IcatianMoneychanger(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.power = new MageInt(0); this.toughness = new MageInt(2); // Icatian Moneychanger enters the battlefield with three credit counters on it. - Effect effect = new AddCountersSourceEffect(CounterType.CREDIT.createInstance(3)); - effect.setText("with three credit counters on it"); - this.addAbility(new EntersBattlefieldAbility(effect)); - + this.addAbility(new EntersBattlefieldAbility( + new AddCountersSourceEffect(CounterType.CREDIT.createInstance(3)) + .setText("with three credit counters on it") + )); + // When Icatian Moneychanger enters the battlefield, it deals 3 damage to you. - effect = new DamageControllerEffect(3); - effect.setText("it deals 3 damage to you"); - this.addAbility(new EntersBattlefieldTriggeredAbility(effect, false)); - + this.addAbility(new EntersBattlefieldTriggeredAbility(new DamageControllerEffect(3, "it"))); + // At the beginning of your upkeep, put a credit counter on Icatian Moneychanger. this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.CREDIT.createInstance()))); - + // Sacrifice Icatian Moneychanger: You gain 1 life for each credit counter on Icatian Moneychanger. Activate this ability only during your upkeep. - this.addAbility(new ConditionalActivatedAbility(Zone.BATTLEFIELD, - new GainLifeEffect(new CountersSourceCount(CounterType.CREDIT)), new SacrificeSourceCost(), new IsStepCondition(PhaseStep.UPKEEP))); + this.addAbility(new ActivateIfConditionActivatedAbility( + new GainLifeEffect(new CountersSourceCount(CounterType.CREDIT)) + .setText("you gain 1 life for each credit counter on this creature"), + new SacrificeSourceCost(), IsStepCondition.getMyUpkeep() + )); } private IcatianMoneychanger(final IcatianMoneychanger card) { diff --git a/Mage.Sets/src/mage/cards/i/IceCauldron.java b/Mage.Sets/src/mage/cards/i/IceCauldron.java index 5e85395a159..1980a525c01 100644 --- a/Mage.Sets/src/mage/cards/i/IceCauldron.java +++ b/Mage.Sets/src/mage/cards/i/IceCauldron.java @@ -10,7 +10,7 @@ import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.RemoveCountersSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.AsThoughEffect; import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.OneShotEffect; @@ -44,8 +44,8 @@ public final class IceCauldron extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); // {X}, {T}: Put a charge counter on Ice Cauldron and exile a nonland card from your hand. You may cast that card for as long as it remains exiled. Note the type and amount of mana spent to pay this activation cost. Activate this ability only if there are no charge counters on Ice Cauldron. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, new IceCauldronExileEffect(), new ManaCostsImpl<>("{X}"), condition + Ability ability = new ActivateIfConditionActivatedAbility( + new IceCauldronExileEffect(), new ManaCostsImpl<>("{X}"), condition ); ability.addEffect(new AddCountersSourceEffect(CounterType.CHARGE.createInstance(), true)); ability.addEffect(new IceCauldronNoteManaEffect()); @@ -78,7 +78,7 @@ class IceCauldronExileEffect extends OneShotEffect { public IceCauldronExileEffect() { super(Outcome.Benefit); - this.staticText = "and exile a nonland card from your hand. You may cast that card for as long as it remains exiled"; + this.staticText = "you may exile a nonland card from your hand. You may cast that card for as long as it remains exiled"; } private IceCauldronExileEffect(final IceCauldronExileEffect effect) { @@ -157,7 +157,7 @@ class IceCauldronNoteManaEffect extends OneShotEffect { public IceCauldronNoteManaEffect() { super(Outcome.Benefit); - this.staticText = "Note the type and amount of mana spent to pay this activation cost"; + this.staticText = "and note the type and amount of mana spent to pay this activation cost"; } private IceCauldronNoteManaEffect(final IceCauldronNoteManaEffect effect) { diff --git a/Mage.Sets/src/mage/cards/i/IceFloe.java b/Mage.Sets/src/mage/cards/i/IceFloe.java index 2f3a53dcf35..3e3d91fff18 100644 --- a/Mage.Sets/src/mage/cards/i/IceFloe.java +++ b/Mage.Sets/src/mage/cards/i/IceFloe.java @@ -16,6 +16,7 @@ import mage.constants.Zone; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; import mage.filter.common.FilterCreatureAttackingYou; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -39,7 +40,7 @@ public final class IceFloe extends CardImpl { // {T}: Tap target creature without flying that's attacking you. It doesn't untap during its controller's untap step for as long as Ice Floe remains tapped. Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); ability.addEffect(new DontUntapAsLongAsSourceTappedEffect()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/i/IcefallRegent.java b/Mage.Sets/src/mage/cards/i/IcefallRegent.java index 4454729a6f6..dfe304b20f0 100644 --- a/Mage.Sets/src/mage/cards/i/IcefallRegent.java +++ b/Mage.Sets/src/mage/cards/i/IcefallRegent.java @@ -16,10 +16,13 @@ import mage.constants.SubType; import mage.constants.TargetController; import mage.filter.FilterCard; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * @author fireshoes */ @@ -38,7 +41,7 @@ public final class IcefallRegent extends CardImpl { // That creature doesn't untap during its controller's untap step for as long as you control Icefall Regent. Ability ability = new EntersBattlefieldTriggeredAbility(new TapTargetEffect(), false); ability.addEffect(new DontUntapInControllersUntapStepTargetEffect(Duration.WhileControlled)); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); // Spells your opponents cast that target Icefall Regent cost {2} more to cast. diff --git a/Mage.Sets/src/mage/cards/i/IcefeatherAven.java b/Mage.Sets/src/mage/cards/i/IcefeatherAven.java index 17026022fb1..9f8eced1780 100644 --- a/Mage.Sets/src/mage/cards/i/IcefeatherAven.java +++ b/Mage.Sets/src/mage/cards/i/IcefeatherAven.java @@ -14,8 +14,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * * @author LevelX2 @@ -36,7 +39,7 @@ public final class IcefeatherAven extends CardImpl { this.addAbility(new MorphAbility(this, new ManaCostsImpl<>("{1}{G}{U}"))); // When Icefeather Aven is turned face up, you may return another target creature to its owner's hand. Ability ability = new TurnedFaceUpSourceTriggeredAbility(new ReturnToHandTargetEffect(), false, true); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/i/IdentityThief.java b/Mage.Sets/src/mage/cards/i/IdentityThief.java index 1a9ecce99c8..437f949029b 100644 --- a/Mage.Sets/src/mage/cards/i/IdentityThief.java +++ b/Mage.Sets/src/mage/cards/i/IdentityThief.java @@ -3,26 +3,26 @@ package mage.cards.i; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CopyEffect; import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.permanent.TokenPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.targetpointer.FixedTarget; +import mage.util.CardUtil; import java.util.UUID; -import mage.abilities.effects.ContinuousEffect; -import mage.abilities.effects.common.CopyEffect; -import mage.util.CardUtil; /** * @author spjspj @@ -32,6 +32,7 @@ public final class IdentityThief extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("target nontoken creature"); static { + filter.add(AnotherPredicate.instance); filter.add(TokenPredicate.FALSE); } @@ -44,8 +45,8 @@ public final class IdentityThief extends CardImpl { // Whenever Identity Thief attacks, you may exile another target nontoken creature. // If you do, Identity Thief becomes a copy of that creature until end of turn. // Return the exiled card to the battlefield under its owner's control at the beginning of the next end step. - Ability ability = new IdentityThiefAbility(); - ability.addTarget(new TargetCreaturePermanent(0, 1, filter, false)); + Ability ability = new AttacksTriggeredAbility(new IdentityThiefEffect(), true); + ability.addTarget(new TargetPermanent(0, 1, filter)); this.addAbility(ability); } @@ -101,26 +102,28 @@ class IdentityThiefEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent targetPermanent = getTargetPointer().getFirstTargetPermanentOrLKI(game, source); Player controller = game.getPlayer(source.getControllerId()); - Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); - if (controller != null - && targetPermanent != null - && sourcePermanent != null) { - ContinuousEffect copyEffect = new CopyEffect(Duration.EndOfTurn, targetPermanent, source.getSourceId()); - copyEffect.setTargetPointer(new FixedTarget(sourcePermanent.getId(), game)); - game.addEffect(copyEffect, source); - - UUID exileZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); - if (controller.moveCardsToExile(targetPermanent, source, game, true, exileZoneId, sourcePermanent.getName())) { - Effect effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, true); - effect.setText("Return the exiled card to the battlefield under its owner's control at the beginning of the next end step"); - effect.setTargetPointer(new FixedTarget(source.getFirstTarget(), game)); - game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source); - } - return true; + Permanent targetPermanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (controller == null || targetPermanent == null) { + return false; } - return false; + controller.moveCardsToExile( + targetPermanent, source, game, true, + CardUtil.getExileZoneId(game, source), + CardUtil.getSourceName(game, source) + ); + game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility( + new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, true) + .setText("Return the exiled card to the battlefield under its owner's control at the beginning of the next end step") + .setTargetPointer(new FixedTarget(source.getFirstTarget(), game)) + ), source); + Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game); + if (sourcePermanent != null) { + game.addEffect(new CopyEffect( + Duration.EndOfTurn, targetPermanent, source.getSourceId() + ).setTargetPointer(new FixedTarget(sourcePermanent.getId(), game)), source); + } + return true; } @Override diff --git a/Mage.Sets/src/mage/cards/i/IdolOfOblivion.java b/Mage.Sets/src/mage/cards/i/IdolOfOblivion.java index 2dba9b17035..377142c4535 100644 --- a/Mage.Sets/src/mage/cards/i/IdolOfOblivion.java +++ b/Mage.Sets/src/mage/cards/i/IdolOfOblivion.java @@ -12,7 +12,6 @@ import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; import mage.game.permanent.token.EldraziToken; import mage.watchers.common.CreatedTokenWatcher; @@ -28,7 +27,7 @@ public final class IdolOfOblivion extends CardImpl { // {T}: Draw a card. Activate this ability only if you created a token this turn. this.addAbility(new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), + new DrawCardSourceControllerEffect(1), new TapSourceCost(), CreatedTokenThisTurnCondition.instance ).addHint(CreatedTokenThisTurnCondition.getHint()), new CreatedTokenWatcher()); diff --git a/Mage.Sets/src/mage/cards/i/IllithidHarvester.java b/Mage.Sets/src/mage/cards/i/IllithidHarvester.java index 3819725e282..06027dad520 100644 --- a/Mage.Sets/src/mage/cards/i/IllithidHarvester.java +++ b/Mage.Sets/src/mage/cards/i/IllithidHarvester.java @@ -14,6 +14,7 @@ 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.predicate.Predicate; import mage.filter.predicate.Predicates; @@ -23,6 +24,7 @@ import mage.filter.predicate.permanent.TokenPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetadjustment.XTargetsCountAdjuster; @@ -34,7 +36,7 @@ import java.util.UUID; */ public final class IllithidHarvester extends AdventureCard { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped nontoken creatures"); + private static final FilterPermanent filter = new FilterCreaturePermanent("tapped nontoken creatures"); static { filter.add(TappedPredicate.TAPPED); @@ -50,7 +52,7 @@ public final class IllithidHarvester extends AdventureCard { // Ceremorphosis — When Illithid Harvester enters the battlefield, turn any number // of target tapped nontoken creatures face down. They're 2/2 Horror creatures. Ability ability = new EntersBattlefieldTriggeredAbility(new IllithidHarvesterEffect()); - ability.addTarget(new TargetCreaturePermanent(0, Integer.MAX_VALUE, filter, false)); + ability.addTarget(new TargetPermanent(0, Integer.MAX_VALUE, filter)); this.addAbility(ability.withFlavorWord("Ceremorphosis")); // Plant Tadpoles diff --git a/Mage.Sets/src/mage/cards/i/IllusionistsStratagem.java b/Mage.Sets/src/mage/cards/i/IllusionistsStratagem.java index 5c4992102ba..139d721d8c0 100644 --- a/Mage.Sets/src/mage/cards/i/IllusionistsStratagem.java +++ b/Mage.Sets/src/mage/cards/i/IllusionistsStratagem.java @@ -5,7 +5,6 @@ import mage.abilities.effects.common.ExileThenReturnTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.StaticFilters; import mage.target.common.TargetControlledCreaturePermanent; import java.util.UUID; @@ -20,8 +19,7 @@ public final class IllusionistsStratagem extends CardImpl { // Exile up to two target creatures you control, then return those cards to the battlefield under their owner's control. this.getSpellAbility().addEffect(new ExileThenReturnTargetEffect(false, true)); - this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, 2, - StaticFilters.FILTER_CONTROLLED_CREATURES, false)); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, 2)); // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("
")); diff --git a/Mage.Sets/src/mage/cards/i/ImaginaryPet.java b/Mage.Sets/src/mage/cards/i/ImaginaryPet.java index 3a1ccda78f2..f99f97caef3 100644 --- a/Mage.Sets/src/mage/cards/i/ImaginaryPet.java +++ b/Mage.Sets/src/mage/cards/i/ImaginaryPet.java @@ -1,35 +1,33 @@ - package mage.cards.i; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.condition.common.CardsInHandCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.common.HellbentCondition; import mage.abilities.effects.common.ReturnToHandSourceEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.ComparisonType; + +import java.util.UUID; /** - * * @author LoneFox */ public final class ImaginaryPet extends CardImpl { + private static final Condition condition = new InvertCondition(HellbentCondition.instance, "you have a card in hand"); + public ImaginaryPet(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.ILLUSION); this.power = new MageInt(4); this.toughness = new MageInt(4); // At the beginning of your upkeep, if you have a card in hand, return Imaginary Pet to its owner's hand. - TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new ReturnToHandSourceEffect(true)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new CardsInHandCondition(ComparisonType.MORE_THAN, 0), - "At the beginning of your upkeep, if you have a card in hand, return {this} to its owner's hand.")); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new ReturnToHandSourceEffect(true)).withInterveningIf(condition)); } private ImaginaryPet(final ImaginaryPet card) { diff --git a/Mage.Sets/src/mage/cards/i/ImpendingDisaster.java b/Mage.Sets/src/mage/cards/i/ImpendingDisaster.java index a584f8cedcf..f11fc9d4897 100644 --- a/Mage.Sets/src/mage/cards/i/ImpendingDisaster.java +++ b/Mage.Sets/src/mage/cards/i/ImpendingDisaster.java @@ -1,36 +1,37 @@ package mage.cards.i; -import mage.abilities.TriggeredAbility; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.Ability; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyAllEffect; import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.StaticFilters; +import mage.filter.common.FilterLandPermanent; import java.util.UUID; /** - * * @author Plopman */ public final class ImpendingDisaster extends CardImpl { - private static final Condition condition = new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_LAND, ComparisonType.OR_GREATER, 7, false); + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterLandPermanent("there are seven or more lands on the battlefield"), + ComparisonType.OR_GREATER, 7, false + ); public ImpendingDisaster(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}"); // At the beginning of your upkeep, if there are seven or more lands on the battlefield, sacrifice Impending Disaster and destroy all lands. - TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceEffect()); - ability.addEffect(new DestroyAllEffect(StaticFilters.FILTER_LANDS)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, condition, - "At the beginning of your upkeep, if there are seven or more lands on the battlefield, sacrifice {this} and destroy all lands")); + Ability ability = new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceEffect()).withInterveningIf(condition); + ability.addEffect(new DestroyAllEffect(StaticFilters.FILTER_LANDS).concatBy("and")); + this.addAbility(ability); } private ImpendingDisaster(final ImpendingDisaster card) { diff --git a/Mage.Sets/src/mage/cards/i/ImperialAerosaur.java b/Mage.Sets/src/mage/cards/i/ImperialAerosaur.java index 0a974072b93..f77cc637d2d 100644 --- a/Mage.Sets/src/mage/cards/i/ImperialAerosaur.java +++ b/Mage.Sets/src/mage/cards/i/ImperialAerosaur.java @@ -1,9 +1,7 @@ package mage.cards.i; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.FlyingAbility; @@ -13,10 +11,11 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.filter.StaticFilters; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class ImperialAerosaur extends CardImpl { @@ -32,13 +31,13 @@ public final class ImperialAerosaur extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When Imperial Aerosaur enters the battlefield, another target creature you control gets +1/+1 and gains flying until end of turn. - Effect effect = new BoostTargetEffect(1, 1, Duration.EndOfTurn); - effect.setText("another target creature you control gets +1/+1"); - EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(effect); - effect = new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn); - effect.setText("and gains flying until end of turn"); - ability.addEffect(effect); - ability.addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_ANOTHER_CREATURE_YOU_CONTROL)); + EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility( + new BoostTargetEffect(1, 1).setText("another target creature you control gets +1/+1") + ); + ability.addEffect(new GainAbilityTargetEffect( + FlyingAbility.getInstance(), Duration.EndOfTurn + ).setText("and gains flying until end of turn")); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_CREATURE_YOU_CONTROL)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/i/ImperialMask.java b/Mage.Sets/src/mage/cards/i/ImperialMask.java index fca7bfa7cce..3142da97e8c 100644 --- a/Mage.Sets/src/mage/cards/i/ImperialMask.java +++ b/Mage.Sets/src/mage/cards/i/ImperialMask.java @@ -2,15 +2,14 @@ package mage.cards.i; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.continuous.GainAbilityControllerEffect; import mage.abilities.keyword.HexproofAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; import mage.filter.FilterPermanent; import mage.filter.predicate.permanent.TokenPredicate; @@ -21,23 +20,22 @@ import java.util.UUID; */ public final class ImperialMask extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent(); + private static final FilterPermanent filter = new FilterPermanent("it's not a token"); static { filter.add(TokenPredicate.FALSE); } + private static final Condition condition = new SourceMatchesFilterCondition(filter); + public ImperialMask(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{W}"); // When Imperial Mask enters the battlefield, if it's not a token, each of your teammates puts a token that's a copy of Imperial Mask onto the battlefield. // No implementation of teammates currently, so no effect needed - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new InfoEffect(""), false), - new SourceMatchesFilterCondition(filter), - "When {this} enters, if it's not a token, " - + "each of your teammates creates a token that's a copy of {this}" - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new InfoEffect( + "each of your teammates creates a token that's a copy of {this}" + ), false).withInterveningIf(condition)); // You have hexproof. this.addAbility(new SimpleStaticAbility(new GainAbilityControllerEffect(HexproofAbility.getInstance()))); diff --git a/Mage.Sets/src/mage/cards/i/ImpetuousDevils.java b/Mage.Sets/src/mage/cards/i/ImpetuousDevils.java index 0d98b477525..c25814320f6 100644 --- a/Mage.Sets/src/mage/cards/i/ImpetuousDevils.java +++ b/Mage.Sets/src/mage/cards/i/ImpetuousDevils.java @@ -1,26 +1,21 @@ package mage.cards.i; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; +import mage.abilities.TriggeredAbility; +import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.effects.common.combat.MustBeBlockedByTargetSourceEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; 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.Zone; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.game.events.GameEvent; +import mage.constants.*; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster; + +import java.util.UUID; /** * @@ -39,7 +34,12 @@ public final class ImpetuousDevils extends CardImpl { // Haste this.addAbility(HasteAbility.getInstance()); // When Impetuous Devils attacks, up to one target creature defending player controls blocks it this combat if able. - this.addAbility(new ImpetuousDevilsAbility()); + TriggeredAbility ability = new AttacksTriggeredAbility(new MustBeBlockedByTargetSourceEffect(Duration.EndOfCombat) + .setText("up to one target creature defending player controls blocks it this combat if able"), false, null, SetTargetPointer.PLAYER); + ability.setTriggerPhrase("When {this} attacks, "); + ability.addTarget(new TargetCreaturePermanent(0, 1)); + ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster()); + this.addAbility(ability); // At the beginning of the end step, sacrifice Impetuous Devils. this.addAbility(new BeginningOfEndStepTriggeredAbility(TargetController.NEXT, new SacrificeSourceEffect(), false)); @@ -54,44 +54,3 @@ public final class ImpetuousDevils extends CardImpl { return new ImpetuousDevils(this); } } - -class ImpetuousDevilsAbility extends TriggeredAbilityImpl { - - public ImpetuousDevilsAbility() { - super(Zone.BATTLEFIELD, new MustBeBlockedByTargetSourceEffect(Duration.EndOfCombat), false); - } - - private ImpetuousDevilsAbility(final ImpetuousDevilsAbility ability) { - super(ability); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ATTACKER_DECLARED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getSourceId().equals(this.getSourceId())) { - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); - UUID defenderId = game.getCombat().getDefendingPlayerId(sourceId, game); - filter.add(new ControllerIdPredicate(defenderId)); - - this.getTargets().clear(); - TargetCreaturePermanent target = new TargetCreaturePermanent(0, 1, filter, false); - this.addTarget(target); - return true; - } - return false; - } - - @Override - public String getRule() { - return "When {this} attacks, up to one target creature defending player controls blocks it this combat if able."; - } - - @Override - public ImpetuousDevilsAbility copy() { - return new ImpetuousDevilsAbility(this); - } -} diff --git a/Mage.Sets/src/mage/cards/i/ImposingSovereign.java b/Mage.Sets/src/mage/cards/i/ImposingSovereign.java index 34ca08ba114..07c91d643ae 100644 --- a/Mage.Sets/src/mage/cards/i/ImposingSovereign.java +++ b/Mage.Sets/src/mage/cards/i/ImposingSovereign.java @@ -26,7 +26,7 @@ public final class ImposingSovereign extends CardImpl { // Creatures your opponents control enter the battlefield tapped. this.addAbility(new SimpleStaticAbility(new PermanentsEnterBattlefieldTappedEffect( StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE - ).setText("creatures your opponents control enter the battlefield tapped"))); + ).setText("creatures your opponents control enter tapped"))); } private ImposingSovereign(final ImposingSovereign card) { diff --git a/Mage.Sets/src/mage/cards/i/ImposterMech.java b/Mage.Sets/src/mage/cards/i/ImposterMech.java index 032a5d3ae73..4061536b07d 100644 --- a/Mage.Sets/src/mage/cards/i/ImposterMech.java +++ b/Mage.Sets/src/mage/cards/i/ImposterMech.java @@ -42,7 +42,7 @@ public final class ImposterMech extends CardImpl { // You may have Imposter Mech enter the battlefield as a copy of a creature an opponent controls, except its a Vehicle artifact with crew 3 and it loses all other card types. this.addAbility(new EntersBattlefieldAbility( new CopyPermanentEffect(StaticFilters.FILTER_OPPONENTS_PERMANENT_A_CREATURE, applier), true, - null, "You may have {this} enter the battlefield as a copy of a creature " + + null, "You may have {this} enter as a copy of a creature " + "an opponent controls, except it's a Vehicle artifact with crew 3 and it loses all other card types.", null )); diff --git a/Mage.Sets/src/mage/cards/i/InactionInjunction.java b/Mage.Sets/src/mage/cards/i/InactionInjunction.java index 11703b984be..cf98a54f3b7 100644 --- a/Mage.Sets/src/mage/cards/i/InactionInjunction.java +++ b/Mage.Sets/src/mage/cards/i/InactionInjunction.java @@ -1,40 +1,37 @@ - package mage.cards.i; - -import java.util.UUID; + import mage.abilities.effects.common.DetainTargetEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.StaticFilters; -import mage.target.common.TargetCreaturePermanent; - +import mage.target.common.TargetOpponentsCreaturePermanent; + +import java.util.UUID; + /** - * * @author LevelX2 */ public final class InactionInjunction extends CardImpl { - + public InactionInjunction(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{U}"); - + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}"); + // Detain target creature an opponent controls. // (Until your next turn, that creature can't attack or block and its activated abilities can't be activated.) this.getSpellAbility().addEffect(new DetainTargetEffect()); - TargetCreaturePermanent target = new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE); - this.getSpellAbility().addTarget(target); - + this.getSpellAbility().addTarget(new TargetOpponentsCreaturePermanent()); + // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("
")); } - + private InactionInjunction(final InactionInjunction card) { super(card); } - + @Override public InactionInjunction copy() { return new InactionInjunction(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/i/InallaArchmageRitualist.java b/Mage.Sets/src/mage/cards/i/InallaArchmageRitualist.java index 28fe07109de..c57570a5c7a 100644 --- a/Mage.Sets/src/mage/cards/i/InallaArchmageRitualist.java +++ b/Mage.Sets/src/mage/cards/i/InallaArchmageRitualist.java @@ -1,31 +1,20 @@ - package mage.cards.i; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.DelayedTriggeredAbility; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.condition.common.SourceOnBattlefieldOrCommandZoneCondition; import mage.abilities.costs.common.TapTargetCost; -import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.DoIfCostPaid; -import mage.abilities.effects.common.ExileTargetEffect; -import mage.abilities.effects.common.LoseLifeTargetEffect; import mage.abilities.effects.common.CreateTokenCopyTargetEffect; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.LoseLifeTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AbilityWord; -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.constants.*; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.permanent.TappedPredicate; @@ -34,22 +23,20 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPlayer; import mage.target.common.TargetControlledPermanent; -import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class InallaArchmageRitualist extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent("another nontoken Wizard"); - private static final FilterControlledPermanent filter2 = new FilterControlledPermanent("untapped Wizards you control"); + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.WIZARD, "another nontoken Wizard you control"); + private static final FilterControlledPermanent filter2 = new FilterControlledPermanent(SubType.WIZARD, "untapped Wizards you control"); static { - filter.add(SubType.WIZARD.getPredicate()); filter.add(TokenPredicate.FALSE); filter.add(AnotherPredicate.instance); - filter2.add(SubType.WIZARD.getPredicate()); filter2.add(TappedPredicate.UNTAPPED); } @@ -63,20 +50,19 @@ public final class InallaArchmageRitualist extends CardImpl { this.toughness = new MageInt(5); // Eminence - Whenever another nontoken Wizard you control enters, if Inalla, Archmage Ritualist is in the command zone or on the battlefield, you may pay {1}. If you do, create a token that's a copy of that Wizard. The token gains haste. Exile it at the beginning of the next end step. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldControlledTriggeredAbility(Zone.ALL, new DoIfCostPaid( - new InallaArchmageRitualistEffect(), new ManaCostsImpl<>("{1}"), "Pay {1} to create a token copy?"), - filter, false, SetTargetPointer.PERMANENT), - SourceOnBattlefieldOrCommandZoneCondition.instance, - "Whenever another nontoken Wizard you control enters, " - + "if {this} is in the command zone or on the battlefield, " - + "you may pay {1}. If you do, create a token that's a copy of that Wizard. " - + "The token gains haste. Exile it at the beginning of the next end step"); - ability.setAbilityWord(AbilityWord.EMINENCE); - this.addAbility(ability); + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + Zone.ALL, + new DoIfCostPaid( + new InallaArchmageRitualistEffect(), new GenericManaCost(1), + "Pay {1} to create a token copy?" + ), filter, false, SetTargetPointer.PERMANENT + ).withInterveningIf(SourceOnBattlefieldOrCommandZoneCondition.instance).setAbilityWord(AbilityWord.EMINENCE)); // Tap five untapped Wizards you control: Target player loses 7 life. - ability = new SimpleActivatedAbility(new LoseLifeTargetEffect(7), new TapTargetCost(new TargetControlledPermanent(5, 5, filter2, true))); + Ability ability = new SimpleActivatedAbility( + new LoseLifeTargetEffect(7), + new TapTargetCost(new TargetControlledPermanent(5, filter2)) + ); ability.addTarget(new TargetPlayer()); this.addAbility(ability); } @@ -95,7 +81,7 @@ class InallaArchmageRitualistEffect extends OneShotEffect { InallaArchmageRitualistEffect() { super(Outcome.PutCreatureInPlay); - this.staticText = "create a token that's a copy of that Wizard. That token gains haste. Exile it at the beginning of the next end step"; + this.staticText = "create a token that's a copy of that Wizard. The token gains haste. Exile it at the beginning of the next end step"; } private InallaArchmageRitualistEffect(final InallaArchmageRitualistEffect effect) { @@ -109,21 +95,14 @@ class InallaArchmageRitualistEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = getTargetPointer().getFirstTargetPermanentOrLKI(game, source); - if (permanent != null) { - CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(null, null, true); - effect.setTargetPointer(this.getTargetPointer().copy()); - if (effect.apply(game, source)) { - for (Permanent tokenPermanent : effect.getAddedPermanents()) { - ExileTargetEffect exileEffect = new ExileTargetEffect(); - exileEffect.setTargetPointer(new FixedTarget(tokenPermanent, game)); - DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect); - game.addDelayedTriggeredAbility(delayedAbility, source); - } - return true; - } + Permanent permanent = (Permanent) getValue("permanentEnteringBattlefield"); + if (permanent == null) { + return false; } - - return false; + CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(null, null, true); + effect.setSavedPermanent(permanent); + effect.apply(game, source); + effect.exileTokensCreatedAtNextEndStep(game, source); + return true; } } diff --git a/Mage.Sets/src/mage/cards/i/InameAsOne.java b/Mage.Sets/src/mage/cards/i/InameAsOne.java index 6bbdde2369c..cc98884af02 100644 --- a/Mage.Sets/src/mage/cards/i/InameAsOne.java +++ b/Mage.Sets/src/mage/cards/i/InameAsOne.java @@ -1,14 +1,11 @@ - package mage.cards.i; -import java.util.UUID; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromHandSourcePermanentCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ExileSourceEffect; @@ -29,8 +26,9 @@ import mage.target.common.TargetCardInYourGraveyard; import mage.target.targetpointer.FixedTarget; import mage.watchers.common.CastFromHandWatcher; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class InameAsOne extends CardImpl { @@ -42,18 +40,16 @@ public final class InameAsOne extends CardImpl { } public InameAsOne(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{8}{B}{B}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{8}{B}{B}{G}{G}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.SPIRIT); this.power = new MageInt(8); this.toughness = new MageInt(8); // 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), - CastFromHandSourcePermanentCondition.instance, - "When {this} enters, if you cast it from your hand, you may search your library for a Spirit permanent card, put it onto the battlefield, then shuffle."), - new CastFromHandWatcher()); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter)), true + ).withInterveningIf(CastFromHandSourcePermanentCondition.instance), 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 DiesSourceTriggeredAbility(new InameAsOneEffect(), false); diff --git a/Mage.Sets/src/mage/cards/i/IncisorGlider.java b/Mage.Sets/src/mage/cards/i/IncisorGlider.java index 20c35591e40..afbc4d58ec5 100644 --- a/Mage.Sets/src/mage/cards/i/IncisorGlider.java +++ b/Mage.Sets/src/mage/cards/i/IncisorGlider.java @@ -1,19 +1,18 @@ package mage.cards.i; -import java.util.UUID; - import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.CorruptedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostControlledEffect; -import mage.constants.AbilityWord; -import mage.constants.Duration; -import mage.constants.SubType; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; + +import java.util.UUID; /** * @author TheElk801 @@ -32,11 +31,9 @@ public final class IncisorGlider extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Corrupted -- Whenever Incisor Glider attacks, if an opponent has three or more poison counters, creatures you control get +1/+1 until end of turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new BoostControlledEffect(1, 1, Duration.EndOfTurn)), - CorruptedCondition.instance, "Whenever {this} attacks, if an opponent has three or " + - "more poison counters, creatures you control get +1/+1 until end of turn." - ).setAbilityWord(AbilityWord.CORRUPTED).addHint(CorruptedCondition.getHint())); + this.addAbility(new AttacksTriggeredAbility( + new BoostControlledEffect(1, 1, Duration.EndOfTurn) + ).withInterveningIf(CorruptedCondition.instance).setAbilityWord(AbilityWord.CORRUPTED).addHint(CorruptedCondition.getHint())); } private IncisorGlider(final IncisorGlider card) { diff --git a/Mage.Sets/src/mage/cards/i/IncrementalBlight.java b/Mage.Sets/src/mage/cards/i/IncrementalBlight.java index b6559225a3f..343a3e7f036 100644 --- a/Mage.Sets/src/mage/cards/i/IncrementalBlight.java +++ b/Mage.Sets/src/mage/cards/i/IncrementalBlight.java @@ -1,49 +1,44 @@ package mage.cards.i; -import java.util.UUID; -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.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.other.AnotherTargetPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.SecondTargetPointer; +import mage.target.targetpointer.ThirdTargetPointer; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class IncrementalBlight extends CardImpl { - public IncrementalBlight(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{B}{B}"); + private static final FilterPermanent filter = new FilterCreaturePermanent("another creature"); + static { + filter.add(new AnotherTargetPredicate(3)); + } + + public IncrementalBlight(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}{B}"); // Put a -1/-1 counter on target creature, two -1/-1 counters on another target creature, and three -1/-1 counters on a third target creature. - this.getSpellAbility().addEffect(new IncrementalBlightEffect()); - - FilterCreaturePermanent filter1 = new FilterCreaturePermanent("creature (gets a -1/-1 counter)"); - TargetCreaturePermanent target1 = new TargetCreaturePermanent(filter1); - target1.setTargetTag(1); - this.getSpellAbility().addTarget(target1); - - FilterCreaturePermanent filter2 = new FilterCreaturePermanent("another creature (gets two -1/-1 counters)"); - filter2.add(new AnotherTargetPredicate(2)); - TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter2); - target2.setTargetTag(2); - this.getSpellAbility().addTarget(target2); - - FilterCreaturePermanent filter3 = new FilterCreaturePermanent("another creature (gets three -1/-1 counters)"); - filter3.add(new AnotherTargetPredicate(3)); - TargetCreaturePermanent target3 = new TargetCreaturePermanent(filter3); - target3.setTargetTag(3); - this.getSpellAbility().addTarget(target3); + this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.M1M1.createInstance())); + this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.M1M1.createInstance(2)) + .setTargetPointer(new SecondTargetPointer()).setText(", two -1/-1 counters on another target creature")); + this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.M1M1.createInstance(3)) + .setTargetPointer(new ThirdTargetPointer()).setText(", and three -1/-1 counters on a third target creature")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent().withChooseHint("gets a -1/-1 counter").setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2).withChooseHint("gets two -1/-1 counters").setTargetTag(2)); + this.getSpellAbility().addTarget(new TargetPermanent(filter).withChooseHint("gets three -1/-1 counters").setTargetTag(3)); } private IncrementalBlight(final IncrementalBlight card) { @@ -55,32 +50,3 @@ public final class IncrementalBlight extends CardImpl { return new IncrementalBlight(this); } } -class IncrementalBlightEffect extends OneShotEffect { - - public IncrementalBlightEffect() { - super(Outcome.UnboostCreature); - this.staticText = "Put a -1/-1 counter on target creature, two -1/-1 counters on another target creature, and three -1/-1 counters on a third target creature"; - } - - private IncrementalBlightEffect(final IncrementalBlightEffect effect) { - super(effect); - } - - @Override - public IncrementalBlightEffect copy() { - return new IncrementalBlightEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - int i = 0; - for (Target target : source.getTargets()) { - i++; - Permanent creature = game.getPermanent(target.getFirstTarget()); - if (creature != null) { - creature.addCounters(CounterType.M1M1.createInstance(i), source.getControllerId(), source, game); - } - } - return false; - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/i/IncrementalGrowth.java b/Mage.Sets/src/mage/cards/i/IncrementalGrowth.java index 96ca91cb9d1..b36efc9a4f6 100644 --- a/Mage.Sets/src/mage/cards/i/IncrementalGrowth.java +++ b/Mage.Sets/src/mage/cards/i/IncrementalGrowth.java @@ -1,49 +1,45 @@ package mage.cards.i; -import java.util.UUID; -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.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.other.AnotherTargetPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.SecondTargetPointer; +import mage.target.targetpointer.ThirdTargetPointer; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class IncrementalGrowth extends CardImpl { + private static final FilterPermanent filter = new FilterCreaturePermanent("another creature"); + + static { + filter.add(new AnotherTargetPredicate(3)); + } + public IncrementalGrowth(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}{G}"); // Put a +1/+1 counter on target creature, two +1/+1 counters on another target // creature, and three +1/+1 counters on a third target creature. - this.getSpellAbility().addEffect(new IncrementalGrowthEffect()); - - FilterCreaturePermanent filter1 = new FilterCreaturePermanent("creature (gets a +1/+1 counter)"); - TargetCreaturePermanent target1 = new TargetCreaturePermanent(filter1); - target1.setTargetTag(1); - this.getSpellAbility().addTarget(target1); - - FilterCreaturePermanent filter2 = new FilterCreaturePermanent("another creature (gets two +1/+1 counters)"); - filter2.add(new AnotherTargetPredicate(2)); - TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter2); - target2.setTargetTag(2); - this.getSpellAbility().addTarget(target2); - - FilterCreaturePermanent filter3 = new FilterCreaturePermanent("another creature (gets three +1/+1 counters)"); - filter3.add(new AnotherTargetPredicate(3)); - TargetCreaturePermanent target3 = new TargetCreaturePermanent(filter3); - target3.setTargetTag(3); - this.getSpellAbility().addTarget(target3); + this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance())); + this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance(2)) + .setTargetPointer(new SecondTargetPointer()).setText(", two +1/+1 counters on another target creature")); + this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance(3)) + .setTargetPointer(new ThirdTargetPointer()).setText(", and three +1/+1 counters on a third target creature")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent().withChooseHint("gets a +1/+1 counter").setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2).withChooseHint("gets two +1/+1 counters").setTargetTag(2)); + this.getSpellAbility().addTarget(new TargetPermanent(filter).withChooseHint("gets three +1/+1 counters").setTargetTag(3)); } private IncrementalGrowth(final IncrementalGrowth card) { @@ -55,35 +51,3 @@ public final class IncrementalGrowth extends CardImpl { return new IncrementalGrowth(this); } } - -class IncrementalGrowthEffect extends OneShotEffect { - - IncrementalGrowthEffect() { - super(Outcome.Benefit); - this.staticText = "Put a +1/+1 counter on target creature, " - + "two +1/+1 counters on another target creature, " - + "and three +1/+1 counters on a third target creature"; - } - - private IncrementalGrowthEffect(final IncrementalGrowthEffect effect) { - super(effect); - } - - @Override - public IncrementalGrowthEffect copy() { - return new IncrementalGrowthEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - int i = 0; - for (Target target : source.getTargets()) { - i++; - Permanent creature = game.getPermanent(target.getFirstTarget()); - if (creature != null) { - creature.addCounters(CounterType.P1P1.createInstance(i), source.getControllerId(), source, game); - } - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/i/IndulgingPatrician.java b/Mage.Sets/src/mage/cards/i/IndulgingPatrician.java index 5c6e1417d83..0334027bf0b 100644 --- a/Mage.Sets/src/mage/cards/i/IndulgingPatrician.java +++ b/Mage.Sets/src/mage/cards/i/IndulgingPatrician.java @@ -1,15 +1,14 @@ package mage.cards.i; import mage.MageInt; -import mage.abilities.triggers.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.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -25,7 +24,7 @@ import java.util.UUID; 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"); + private static final Hint hint = new ConditionHint(condition); public IndulgingPatrician(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{B}"); @@ -42,12 +41,8 @@ public final class IndulgingPatrician extends CardImpl { 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) - ), 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()); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new LoseLifeOpponentsEffect(3)) + .withInterveningIf(condition).addHint(hint), new PlayerGainedLifeWatcher()); } private IndulgingPatrician(final IndulgingPatrician card) { diff --git a/Mage.Sets/src/mage/cards/i/InexorableBlob.java b/Mage.Sets/src/mage/cards/i/InexorableBlob.java index 10feef7ff39..977258dfe90 100644 --- a/Mage.Sets/src/mage/cards/i/InexorableBlob.java +++ b/Mage.Sets/src/mage/cards/i/InexorableBlob.java @@ -1,19 +1,19 @@ package mage.cards.i; -import java.util.UUID; - import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.DeliriumCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; import mage.game.permanent.token.InexorableBlobOozeToken; +import java.util.UUID; + /** * @author fireshoes */ @@ -27,11 +27,9 @@ public final class InexorableBlob extends CardImpl { // Delirium — Whenever Inexorable Blob attacks, if there are four or more card types among cards // in your graveyard, create a 3/3 green Ooze creature token that’s tapped and attacking. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new AttacksTriggeredAbility(new CreateTokenEffect(new InexorableBlobOozeToken(), 1, true, true), false), - DeliriumCondition.instance, - "Delirium — Whenever {this} attacks, if there are four or more card types among cards in your graveyard, " + - "create a 3/3 green Ooze creature token that's tapped and attacking.") - .addHint(CardTypesInGraveyardCount.YOU.getHint())); + this.addAbility(new AttacksTriggeredAbility(new CreateTokenEffect( + new InexorableBlobOozeToken(), 1, true, true + )).withInterveningIf(DeliriumCondition.instance).setAbilityWord(AbilityWord.DELIRIUM).addHint(CardTypesInGraveyardCount.YOU.getHint())); } private InexorableBlob(final InexorableBlob card) { diff --git a/Mage.Sets/src/mage/cards/i/InfectedVermin.java b/Mage.Sets/src/mage/cards/i/InfectedVermin.java index 78c9ce5884f..61c6499c2cc 100644 --- a/Mage.Sets/src/mage/cards/i/InfectedVermin.java +++ b/Mage.Sets/src/mage/cards/i/InfectedVermin.java @@ -4,7 +4,7 @@ import mage.MageInt; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.ThresholdCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DamageEverythingEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -30,7 +30,7 @@ public final class InfectedVermin extends CardImpl { this.addAbility(new SimpleActivatedAbility(new DamageEverythingEffect(1), new ManaCostsImpl<>("{2}{B}"))); // Threshold - {3}{B}: Infected Vermin deals 3 damage to each creature and each player. Activate this ability only if seven or more cards are in your graveyard. - this.addAbility(new ConditionalActivatedAbility( + this.addAbility(new ActivateIfConditionActivatedAbility( new DamageEverythingEffect(3), new ManaCostsImpl<>("{3}{B}"), ThresholdCondition.instance ).setAbilityWord(AbilityWord.THRESHOLD)); } diff --git a/Mage.Sets/src/mage/cards/i/InfectiousBite.java b/Mage.Sets/src/mage/cards/i/InfectiousBite.java index 3d77ad7eab2..b163633f2d3 100644 --- a/Mage.Sets/src/mage/cards/i/InfectiousBite.java +++ b/Mage.Sets/src/mage/cards/i/InfectiousBite.java @@ -8,11 +8,14 @@ import mage.constants.CardType; import mage.constants.TargetController; import mage.counters.CounterType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author TheElk801 */ @@ -24,7 +27,7 @@ public final class InfectiousBite extends CardImpl { // Target creature you control deals damage equal to its power to target creature you don't control. Each opponent gets a poison counter. this.getSpellAbility().addEffect(new DamageWithPowerFromOneToAnotherTargetEffect()); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.getSpellAbility().addEffect(new AddCountersPlayersEffect( CounterType.POISON.createInstance(), TargetController.OPPONENT )); diff --git a/Mage.Sets/src/mage/cards/i/InfernalDenizen.java b/Mage.Sets/src/mage/cards/i/InfernalDenizen.java index 1f2ce602ea9..8b9b07987c2 100644 --- a/Mage.Sets/src/mage/cards/i/InfernalDenizen.java +++ b/Mage.Sets/src/mage/cards/i/InfernalDenizen.java @@ -1,40 +1,36 @@ package mage.cards.i; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.condition.common.SourceOnBattlefieldCondition; -import mage.abilities.condition.common.SourceRemainsInZoneCondition; +import mage.abilities.costs.Cost; +import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; -import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.SacrificeControllerEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.constants.Zone; import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; +import mage.target.TargetPlayer; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetOpponent; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class InfernalDenizen extends CardImpl { @@ -50,11 +46,11 @@ public final class InfernalDenizen extends CardImpl { this.addAbility(new BeginningOfUpkeepTriggeredAbility(new InfernalDenizenEffect())); // {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), - new SourceRemainsInZoneCondition(Zone.BATTLEFIELD), - "gain control of target creature for as long as {this} remains on the battlefield"); - Ability ability = new SimpleActivatedAbility(effect, new TapSourceCost()); + Ability ability = new SimpleActivatedAbility( + new GainControlTargetEffect(Duration.UntilSourceLeavesBattlefield, true) + .setText("gain control of target creature for as long as {this} remains on the battlefield"), + new TapSourceCost() + ); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } @@ -71,12 +67,7 @@ public final class InfernalDenizen extends CardImpl { class InfernalDenizenEffect extends OneShotEffect { - private static final FilterPermanent filter = new FilterPermanent(); - - static { - filter.add(SubType.SWAMP.getPredicate()); - filter.add(TargetController.YOU.getControllerPredicate()); - } + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.SWAMP); InfernalDenizenEffect() { super(Outcome.Benefit); @@ -96,41 +87,36 @@ class InfernalDenizenEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent creature = game.getPermanent(source.getSourceId()); - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - DynamicValue swamps = new PermanentsOnBattlefieldCount(filter); - boolean canSac = swamps.calculate(game, source, this) > 1; - Effect effect = new SacrificeControllerEffect(filter, 2, "Sacrifice two Swamps"); - effect.apply(game, source); - if (!canSac) { - if (creature != null) { - creature.tap(source, game); - } - TargetOpponent targetOpp = new TargetOpponent(true); - if (targetOpp.canChoose(player.getId(), source, game) - && targetOpp.choose(Outcome.Detriment, player.getId(), source.getSourceId(), source, game)) { - Player opponent = game.getPlayer(targetOpp.getFirstTarget()); - if (opponent != null) { - FilterCreaturePermanent filter2 = new FilterCreaturePermanent("creature controlled by " + player.getLogName()); - filter2.add(new ControllerIdPredicate(player.getId())); - TargetCreaturePermanent targetCreature = new TargetCreaturePermanent(1, 1, filter2, true); - targetCreature.setTargetController(opponent.getId()); - if (targetCreature.canChoose(source.getControllerId(), source, game) - && opponent.chooseUse(Outcome.GainControl, "Gain control of a creature?", source, game) - && opponent.chooseTarget(Outcome.GainControl, targetCreature, source, game)) { - ConditionalContinuousEffect giveEffect = new ConditionalContinuousEffect( - new GainControlTargetEffect(Duration.Custom, true, opponent.getId()), - SourceOnBattlefieldCondition.instance, - ""); - giveEffect.setTargetPointer(new FixedTarget(targetCreature.getFirstTarget(), game)); - game.addEffect(giveEffect, source); - return true; - } - } - } - } + Cost cost = new SacrificeTargetCost(filter); + if (cost.canPay(source, source, source.getControllerId(), game) + && cost.pay(source, game, source, source.getControllerId(), true)) { + return true; } - return false; + Permanent creature = source.getSourcePermanentIfItStillExists(game); + if (creature == null) { + return false; + } + creature.tap(source, game); + TargetPlayer targetPlayer = new TargetOpponent(true); + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return true; + } + player.choose(outcome, targetPlayer, source, game); + Player opponent = game.getPlayer(targetPlayer.getFirstTarget()); + if (opponent == null) { + return true; + } + FilterPermanent filterPermanent = new FilterCreaturePermanent("creature controlled by " + player.getName()); + filterPermanent.add(new ControllerIdPredicate(player.getId())); + TargetPermanent target = new TargetPermanent(0, 1, filterPermanent, true); + opponent.choose(outcome, target, source, game); + Permanent permanent = game.getPermanent(target.getFirstTarget()); + if (permanent != null) { + game.addEffect(new GainControlTargetEffect( + Duration.UntilSourceLeavesBattlefield, true, opponent.getId() + ).setTargetPointer(new FixedTarget(permanent, game)), source); + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/i/InfernalSpawnOfEvil.java b/Mage.Sets/src/mage/cards/i/InfernalSpawnOfEvil.java index fed4b3f46ec..d4f5c352f5f 100644 --- a/Mage.Sets/src/mage/cards/i/InfernalSpawnOfEvil.java +++ b/Mage.Sets/src/mage/cards/i/InfernalSpawnOfEvil.java @@ -1,6 +1,5 @@ package mage.cards.i; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; @@ -16,21 +15,21 @@ import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.PhaseStep; import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetOpponentOrPlaneswalker; +import java.util.UUID; + /** - * * @author Ketsuban */ public final class InfernalSpawnOfEvil extends CardImpl { public InfernalSpawnOfEvil(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[] { CardType.CREATURE }, "{6}{B}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{B}{B}{B}"); this.subtype.add(SubType.BEAST); this.power = new MageInt(7); @@ -47,13 +46,13 @@ public final class InfernalSpawnOfEvil extends CardImpl { // Activate this ability only during your upkeep and only once each turn. Ability ability = new LimitedTimesPerTurnActivatedAbility(Zone.HAND, new DamageTargetEffect(1), new CompositeCost( - new ManaCostsImpl<>("{1}{B}"), - new CompositeCost( - new RevealSourceFromYourHandCost(), - new SayCost("It's coming!"), - "Reveal {this} from your hand, Say \"It's coming!\""), - "{1}{B}, Reveal {this} from your hand, Say \"It's coming!\""), - 1, new IsStepCondition(PhaseStep.UPKEEP, true)); + new ManaCostsImpl<>("{1}{B}"), + new CompositeCost( + new RevealSourceFromYourHandCost(), + new SayCost("It's coming!"), + "Reveal {this} from your hand, Say \"It's coming!\""), + "{1}{B}, Reveal {this} from your hand, Say \"It's coming!\""), + 1, IsStepCondition.getMyUpkeep()); ability.addTarget(new TargetOpponentOrPlaneswalker()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/i/InfernalVessel.java b/Mage.Sets/src/mage/cards/i/InfernalVessel.java index 5050807b7ba..1517b016807 100644 --- a/Mage.Sets/src/mage/cards/i/InfernalVessel.java +++ b/Mage.Sets/src/mage/cards/i/InfernalVessel.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldWithCounterTargetEffect; import mage.abilities.effects.common.continuous.AddCardSubTypeTargetEffect; @@ -22,26 +21,21 @@ import mage.util.CardUtil; import java.util.UUID; /** - * * @author ciaccona007 */ public final class InfernalVessel extends CardImpl { public InfernalVessel(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); - + this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.CLERIC); this.power = new MageInt(2); this.toughness = new MageInt(1); // When this creature dies, if it wasn't a Demon, return it to the battlefield under its owner's control with two +1/+1 counters on it. It's a Demon in addition to its other types. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new DiesSourceTriggeredAbility(new InfernalVesselReturnEffect()), - InfernalVesselCondition.instance, - "When this creature dies, if it wasn't a Demon, return it to the battlefield under its owner's control " - + "with two +1/+1 counters on it. It's a Demon in addition to its other types" - )); + this.addAbility(new DiesSourceTriggeredAbility(new InfernalVesselReturnEffect()) + .withInterveningIf(InfernalVesselCondition.instance)); } private InfernalVessel(final InfernalVessel card) { @@ -59,8 +53,15 @@ enum InfernalVesselCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = (Permanent) source.getEffects().get(0).getValue("permanentLeftBattlefield"); - return permanent != null && !permanent.hasSubtype(SubType.DEMON, game); + return CardUtil + .getEffectValueFromAbility(source, "permanentLeftBattlefield", Permanent.class) + .filter(permanent -> !permanent.hasSubtype(SubType.DEMON, game)) + .isPresent(); + } + + @Override + public String toString() { + return "it wasn't a Demon"; } } @@ -68,6 +69,7 @@ class InfernalVesselReturnEffect extends OneShotEffect { InfernalVesselReturnEffect() { super(Outcome.PutCreatureInPlay); + staticText = "return it to the battlefield under its owner's control with two +1/+1 counters on it. It's a Demon in addition to its other types"; } private InfernalVesselReturnEffect(final InfernalVesselReturnEffect effect) { diff --git a/Mage.Sets/src/mage/cards/i/InfernoHellion.java b/Mage.Sets/src/mage/cards/i/InfernoHellion.java index 8546f4673cb..b660716c70f 100644 --- a/Mage.Sets/src/mage/cards/i/InfernoHellion.java +++ b/Mage.Sets/src/mage/cards/i/InfernoHellion.java @@ -1,25 +1,24 @@ package mage.cards.i; -import java.util.UUID; import mage.MageInt; import mage.MageObjectReference; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ShuffleIntoLibrarySourceEffect; -import mage.constants.SubType; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SubType; import mage.constants.TargetController; import mage.game.Game; import mage.watchers.common.AttackedThisTurnWatcher; import mage.watchers.common.BlockedThisTurnWatcher; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class InfernoHellion extends CardImpl { @@ -35,18 +34,10 @@ public final class InfernoHellion extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // At the beginning of each end step, if Inferno Hellion attacked or blocked this turn, its owner shuffles it into their library. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - TargetController.ANY, new ShuffleIntoLibrarySourceEffect(), - false - ), - InfernoHellionCondition.instance, - "At the beginning of each end step, " - + "if {this} attacked or blocked this turn, " - + "its owner shuffles it into their library." - ); - ability.addWatcher(new BlockedThisTurnWatcher()); - this.addAbility(ability); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.ANY, new ShuffleIntoLibrarySourceEffect(), + false, InfernoHellionCondition.instance + ), new BlockedThisTurnWatcher()); } private InfernoHellion(final InfernoHellion card) { @@ -60,7 +51,6 @@ public final class InfernoHellion extends CardImpl { } enum InfernoHellionCondition implements Condition { - instance; @Override @@ -74,4 +64,9 @@ enum InfernoHellionCondition implements Condition { return watcherAttacked.getAttackedThisTurnCreatures().contains(mor) || watcherBlocked.getBlockedThisTurnCreatures().contains(mor); } + + @Override + public String toString() { + return "{this} attacked or blocked this turn"; + } } diff --git a/Mage.Sets/src/mage/cards/i/InfiniteHourglass.java b/Mage.Sets/src/mage/cards/i/InfiniteHourglass.java index b7219ba551a..794d4a13062 100644 --- a/Mage.Sets/src/mage/cards/i/InfiniteHourglass.java +++ b/Mage.Sets/src/mage/cards/i/InfiniteHourglass.java @@ -1,33 +1,35 @@ - package mage.cards.i; -import java.util.UUID; -import mage.abilities.ActivatedAbility; import mage.abilities.common.ActivateIfConditionActivatedAbility; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.common.continuous.BoostAllEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.PhaseStep; import mage.constants.TargetController; -import mage.constants.Zone; import mage.counters.CounterType; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class InfiniteHourglass extends CardImpl { + private static final DynamicValue xValue = new CountersSourceCount(CounterType.TIME); + private static final Condition condition = new IsStepCondition(PhaseStep.UPKEEP, false); + public InfiniteHourglass(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); @@ -35,23 +37,14 @@ public final class InfiniteHourglass extends CardImpl { this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.TIME.createInstance()))); // All creatures get +1/+0 for each time counter on Infinite Hourglass. - this.addAbility(new SimpleStaticAbility( - new BoostAllEffect( - new CountersSourceCount(CounterType.TIME), - StaticValue.get(0), - Duration.WhileOnBattlefield - ) - )); + this.addAbility(new SimpleStaticAbility(new BoostAllEffect( + xValue, StaticValue.get(0), Duration.WhileOnBattlefield + ))); // {3}: Remove a time counter from Infinite Hourglass. Any player may activate this ability but only during any upkeep step. - ActivatedAbility ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, - new RemoveCounterSourceEffect(CounterType.TIME.createInstance()), - new GenericManaCost(3), - new IsStepCondition(PhaseStep.UPKEEP, false) - ); - ability.setMayActivate(TargetController.ANY); - this.addAbility(ability); + this.addAbility(new ActivateIfConditionActivatedAbility( + new RemoveCounterSourceEffect(CounterType.TIME.createInstance()), new GenericManaCost(3), condition + ).withConditionText("any player may activate this ability but only during any upkeep step").setMayActivate(TargetController.ANY)); } private InfiniteHourglass(final InfiniteHourglass card) { diff --git a/Mage.Sets/src/mage/cards/i/IngeniousProdigy.java b/Mage.Sets/src/mage/cards/i/IngeniousProdigy.java index 2fb2158a51c..a03f3440b5d 100644 --- a/Mage.Sets/src/mage/cards/i/IngeniousProdigy.java +++ b/Mage.Sets/src/mage/cards/i/IngeniousProdigy.java @@ -1,16 +1,15 @@ package mage.cards.i; import mage.MageInt; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.RemoveCountersSourceCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect; import mage.abilities.keyword.SkulkAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -41,15 +40,10 @@ public final class IngeniousProdigy extends CardImpl { this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.P1P1.createInstance()))); // At the beginning of your upkeep, if Ingenious Prodigy has one or more +1/+1 counters on it, you may remove a +1/+1 counter from it. If you do, draw a card. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility( - new DoIfCostPaid( - new DrawCardSourceControllerEffect(1), - new RemoveCountersSourceCost(CounterType.P1P1.createInstance()) - ), false - ), condition, "At the beginning of your upkeep, if {this} has one or more " + - "+1/+1 counters on it, you may remove a +1/+1 counter from it. If you do, draw a card." - )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DoIfCostPaid( + new DrawCardSourceControllerEffect(1), + new RemoveCountersSourceCost(CounterType.P1P1.createInstance()).setText("remove a +1/+1 counter from it") + )).withInterveningIf(condition)); } private IngeniousProdigy(final IngeniousProdigy card) { diff --git a/Mage.Sets/src/mage/cards/i/IngeniousSmith.java b/Mage.Sets/src/mage/cards/i/IngeniousSmith.java index 109dbd3b1ee..2e1f731c96d 100644 --- a/Mage.Sets/src/mage/cards/i/IngeniousSmith.java +++ b/Mage.Sets/src/mage/cards/i/IngeniousSmith.java @@ -1,8 +1,7 @@ package mage.cards.i; -import java.util.UUID; import mage.MageInt; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -12,16 +11,18 @@ import mage.constants.CardType; import mage.constants.PutCards; import mage.constants.SubType; import mage.counters.CounterType; +import mage.filter.FilterPermanent; import mage.filter.StaticFilters; -import mage.filter.common.FilterArtifactPermanent; +import mage.filter.common.FilterControlledArtifactPermanent; + +import java.util.UUID; /** - * * @author weirddan455 */ public final class IngeniousSmith extends CardImpl { - private static final FilterArtifactPermanent filter = new FilterArtifactPermanent("one or more artifacts"); + private static final FilterPermanent filter = new FilterControlledArtifactPermanent("one or more artifacts you control"); public IngeniousSmith(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); @@ -34,12 +35,16 @@ public final class IngeniousSmith extends CardImpl { // When Ingenious Smith enters the battlefield, look at the top four cards of your library. // You may reveal an artifact 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 EntersBattlefieldTriggeredAbility(new LookLibraryAndPickControllerEffect( - 4, 1, StaticFilters.FILTER_CARD_ARTIFACT_AN, PutCards.HAND, PutCards.BOTTOM_RANDOM))); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new LookLibraryAndPickControllerEffect( + 4, 1, StaticFilters.FILTER_CARD_ARTIFACT_AN, + PutCards.HAND, PutCards.BOTTOM_RANDOM + ) + )); // Whenever one or more artifacts enter the battlefield under your control, put a +1/+1 counter on Ingenious Smith. // This ability triggers only once each turn. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + this.addAbility(new EntersBattlefieldAllTriggeredAbility( new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filter ).setTriggersLimitEachTurn(1)); } diff --git a/Mage.Sets/src/mage/cards/i/InnerFire.java b/Mage.Sets/src/mage/cards/i/InnerFire.java index 1e286f7e104..dcaabe61dd1 100644 --- a/Mage.Sets/src/mage/cards/i/InnerFire.java +++ b/Mage.Sets/src/mage/cards/i/InnerFire.java @@ -20,7 +20,7 @@ public final class InnerFire extends CardImpl { // Add {R} for each card in your hand. - this.getSpellAbility().addEffect(new DynamicManaEffect(Mana.RedMana(1), CardsInControllerHandCount.ANY)); + this.getSpellAbility().addEffect(new DynamicManaEffect(Mana.RedMana(1), CardsInControllerHandCount.ANY_SINGULAR)); } private InnerFire(final InnerFire card) { diff --git a/Mage.Sets/src/mage/cards/i/InquisitorsFlail.java b/Mage.Sets/src/mage/cards/i/InquisitorsFlail.java index 03205bc4cf1..e52c817ec8f 100644 --- a/Mage.Sets/src/mage/cards/i/InquisitorsFlail.java +++ b/Mage.Sets/src/mage/cards/i/InquisitorsFlail.java @@ -3,12 +3,14 @@ package mage.cards.i; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.keyword.EquipAbility; 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.game.events.DamageEvent; import mage.game.events.GameEvent; @@ -16,7 +18,6 @@ import mage.game.permanent.Permanent; import mage.util.CardUtil; import java.util.UUID; -import mage.target.common.TargetControlledCreaturePermanent; /** * @author nantuko @@ -32,7 +33,7 @@ public final class InquisitorsFlail extends CardImpl { this.addAbility(new SimpleStaticAbility(new InquisitorsFlailEffect())); // Equip {2} - this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(2), new TargetControlledCreaturePermanent(), false)); + this.addAbility(new EquipAbility(2, false)); } private InquisitorsFlail(final InquisitorsFlail card) { @@ -49,7 +50,7 @@ class InquisitorsFlailEffect extends ReplacementEffectImpl { InquisitorsFlailEffect() { super(Duration.WhileOnBattlefield, Outcome.Damage); - staticText = "If equipped creature would deal combat damage, it deals double that damage instead. \n" + staticText = "If equipped creature would deal combat damage, it deals double that damage instead.
" + "If another creature would deal combat damage to equipped creature, it deals double that damage to equipped creature instead"; } diff --git a/Mage.Sets/src/mage/cards/i/InscriptionOfAbundance.java b/Mage.Sets/src/mage/cards/i/InscriptionOfAbundance.java index 0e0c67f2563..5568a081e94 100644 --- a/Mage.Sets/src/mage/cards/i/InscriptionOfAbundance.java +++ b/Mage.Sets/src/mage/cards/i/InscriptionOfAbundance.java @@ -16,6 +16,7 @@ import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.game.Game; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.TargetPlayer; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; @@ -23,6 +24,8 @@ import mage.target.common.TargetCreaturePermanent; import java.util.Objects; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author TheElk801 */ @@ -49,7 +52,7 @@ public final class InscriptionOfAbundance extends CardImpl { // • Target creature you control fights target creature you don't control. mode = new Mode(new FightTargetsEffect(false)); mode.addTarget(new TargetControlledCreaturePermanent().withChooseHint("fights")); - mode.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL).withChooseHint("fights")); + mode.addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL).withChooseHint("fights")); this.getSpellAbility().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/i/IntimidationTactics.java b/Mage.Sets/src/mage/cards/i/IntimidationTactics.java index 29f8234c272..79b2c04a6d7 100644 --- a/Mage.Sets/src/mage/cards/i/IntimidationTactics.java +++ b/Mage.Sets/src/mage/cards/i/IntimidationTactics.java @@ -7,6 +7,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.common.TargetOpponent; import java.util.UUID; @@ -20,6 +21,7 @@ public final class IntimidationTactics extends CardImpl { // Target opponent reveals their hand. You choose an artifact or creature card from it. Exile that card. this.getSpellAbility().addEffect(new ExileCardYouChooseTargetOpponentEffect(StaticFilters.FILTER_CARD_ARTIFACT_OR_CREATURE)); + this.getSpellAbility().addTarget(new TargetOpponent()); // Cycling {3} this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{3}"))); diff --git a/Mage.Sets/src/mage/cards/i/IntrepidHero.java b/Mage.Sets/src/mage/cards/i/IntrepidHero.java index a22cf92ce3d..eea2276794b 100644 --- a/Mage.Sets/src/mage/cards/i/IntrepidHero.java +++ b/Mage.Sets/src/mage/cards/i/IntrepidHero.java @@ -15,6 +15,7 @@ import mage.constants.ComparisonType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -39,7 +40,7 @@ public final class IntrepidHero extends CardImpl { // {tap}: Destroy target creature with power 4 or greater. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/i/InventorsFair.java b/Mage.Sets/src/mage/cards/i/InventorsFair.java index be5427e89b1..38dda972622 100644 --- a/Mage.Sets/src/mage/cards/i/InventorsFair.java +++ b/Mage.Sets/src/mage/cards/i/InventorsFair.java @@ -1,7 +1,6 @@ package mage.cards.i; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.costs.common.SacrificeSourceCost; @@ -11,15 +10,12 @@ import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; import mage.abilities.hint.common.MetalcraftHint; import mage.abilities.mana.ColorlessManaAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SuperType; -import mage.constants.Zone; import mage.filter.StaticFilters; -import mage.filter.common.FilterArtifactPermanent; -import mage.game.Game; -import mage.game.events.GameEvent; import mage.target.common.TargetCardInLibrary; import java.util.UUID; @@ -34,19 +30,20 @@ public final class InventorsFair extends CardImpl { this.supertype.add(SuperType.LEGENDARY); // At the beginning of your upkeep, if you control three or more artifacts, you gain 1 life. - this.addAbility(new InventorsFairAbility()); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new GainLifeEffect(1)) + .withInterveningIf(MetalcraftCondition.instance)); // {t}: Add {C}. this.addAbility(new ColorlessManaAbility()); // {4}, {T}, Sacrifice Inventors' Fair: Search your library for an artifact card, reveal it, put it into your hand, then shuffle your library. // Activate this ability only if you control threeor more artifacts. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new SearchLibraryPutInHandEffect(new TargetCardInLibrary(StaticFilters.FILTER_CARD_ARTIFACT), true), - new GenericManaCost(4), MetalcraftCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility(new SearchLibraryPutInHandEffect( + new TargetCardInLibrary(StaticFilters.FILTER_CARD_ARTIFACT), true + ), new GenericManaCost(4), MetalcraftCondition.instance); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); - ability.addHint(MetalcraftHint.instance); - this.addAbility(ability); + this.addAbility(ability.addHint(MetalcraftHint.instance)); } private InventorsFair(final InventorsFair card) { @@ -58,41 +55,3 @@ public final class InventorsFair extends CardImpl { return new InventorsFair(this); } } - -class InventorsFairAbility extends TriggeredAbilityImpl { - - private FilterArtifactPermanent filter = new FilterArtifactPermanent(); - - public InventorsFairAbility() { - super(Zone.BATTLEFIELD, new GainLifeEffect(1)); - } - - private InventorsFairAbility(final InventorsFairAbility ability) { - super(ability); - } - - @Override - public InventorsFairAbility copy() { - return new InventorsFairAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.UPKEEP_STEP_PRE; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return event.getPlayerId().equals(this.controllerId); - } - - @Override - public boolean checkInterveningIfClause(Game game) { - return game.getBattlefield().countAll(filter, this.controllerId, game) >= 3; - } - - @Override - public String getRule() { - return "At the beginning of your upkeep, if you control three or more artifacts, you gain 1 life."; - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/i/InventoryManagement.java b/Mage.Sets/src/mage/cards/i/InventoryManagement.java new file mode 100644 index 00000000000..ecaf2f9f119 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/InventoryManagement.java @@ -0,0 +1,109 @@ +package mage.cards.i; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.SplitSecondAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.Predicates; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetImpl; +import mage.target.TargetPermanent; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * @author TheElk801 + */ +public final class InventoryManagement extends CardImpl { + + public InventoryManagement(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}{W}"); + + // Split second + this.addAbility(new SplitSecondAbility()); + + // For each Aura and Equipment you control, you may attach it to a creature you control. + this.getSpellAbility().addEffect(new InventoryManagementEffect()); + } + + private InventoryManagement(final InventoryManagement card) { + super(card); + } + + @Override + public InventoryManagement copy() { + return new InventoryManagement(this); + } +} + +class InventoryManagementEffect extends OneShotEffect { + + private static final FilterPermanent filter = new FilterControlledPermanent("Aura or Equipment you control"); + + static { + filter.add(Predicates.or( + SubType.AURA.getPredicate(), + SubType.EQUIPMENT.getPredicate() + )); + } + + InventoryManagementEffect() { + super(Outcome.Benefit); + staticText = "for each Aura and Equipment you control, you may attach it to a creature you control"; + } + + private InventoryManagementEffect(final InventoryManagementEffect effect) { + super(effect); + } + + @Override + public InventoryManagementEffect copy() { + return new InventoryManagementEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null + || !game.getBattlefield().contains(filter, source, game, 1) + || !game.getBattlefield().contains(StaticFilters.FILTER_CONTROLLED_CREATURE, source, game, 1)) { + return false; + } + TargetPermanent target = new TargetPermanent(0, Integer.MAX_VALUE, filter, true); + target.withChooseHint("to attach to a creature you control"); + player.choose(outcome, target, source, game); + List permanents = target + .getTargets() + .stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + if (permanents.isEmpty()) { + return false; + } + for (Permanent permanent : permanents) { + TargetPermanent targetCreature = new TargetControlledCreaturePermanent(0, 1); + targetCreature.withNotTarget(true); + targetCreature.withChooseHint("to attach " + permanent.getLogName() + " to"); + Optional.ofNullable(targetCreature) + .map(TargetImpl::getFirstTarget) + .map(game::getPermanent) + .ifPresent(p -> p.addAttachment(permanent.getId(), source, game)); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/i/InvigoratedRampage.java b/Mage.Sets/src/mage/cards/i/InvigoratedRampage.java index 303332f0ace..3e6e9091032 100644 --- a/Mage.Sets/src/mage/cards/i/InvigoratedRampage.java +++ b/Mage.Sets/src/mage/cards/i/InvigoratedRampage.java @@ -1,9 +1,6 @@ - package mage.cards.i; -import java.util.UUID; import mage.abilities.Mode; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.TrampleAbility; @@ -13,8 +10,9 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author Styxo */ public final class InvigoratedRampage extends CardImpl { @@ -24,21 +22,15 @@ public final class InvigoratedRampage extends CardImpl { // Choose one // Target creature gets +4/+0 and gains trample until end of turn. - Effect effect = new BoostTargetEffect(4, 0, Duration.EndOfTurn); - effect.setText("Target creature gets +4/+0"); - this.getSpellAbility().addEffect(effect); - effect = new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn); - effect.setText("and gains trample until end of turn"); - this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addEffect(new BoostTargetEffect(4, 0).setText("target creature gets +4/+0")); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect( + TrampleAbility.getInstance(), Duration.EndOfTurn + ).setText("and gains trample until end of turn")); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); // Two target creatures each get +2/+0 and gain trample until end of turn. - effect = new BoostTargetEffect(2, 0, Duration.EndOfTurn); - effect.setText("Two target creatures each get +2/+0"); - Mode mode = new Mode(effect); - effect = new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn); - effect.setText("and gain trample until end of turn"); - mode.addEffect(effect); + Mode mode = new Mode(new BoostTargetEffect(2, 0).setText("two target creatures each get +2/+0")); + mode.addEffect(new GainAbilityTargetEffect(TrampleAbility.getInstance()).setText("and gain trample until end of turn")); mode.addTarget(new TargetCreaturePermanent(2)); this.getSpellAbility().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/i/IronApprentice.java b/Mage.Sets/src/mage/cards/i/IronApprentice.java index 0671b3432d1..3fc9dd21fc1 100644 --- a/Mage.Sets/src/mage/cards/i/IronApprentice.java +++ b/Mage.Sets/src/mage/cards/i/IronApprentice.java @@ -58,6 +58,7 @@ class IronApprenticeEffect extends OneShotEffect { IronApprenticeEffect() { super(Outcome.Benefit); + staticText = "put those counters on target creature you control"; } private IronApprenticeEffect(final IronApprenticeEffect effect) { diff --git a/Mage.Sets/src/mage/cards/i/IronFistOfTheEmpire.java b/Mage.Sets/src/mage/cards/i/IronFistOfTheEmpire.java index 80c03b2baec..2c4151e5365 100644 --- a/Mage.Sets/src/mage/cards/i/IronFistOfTheEmpire.java +++ b/Mage.Sets/src/mage/cards/i/IronFistOfTheEmpire.java @@ -1,23 +1,21 @@ - package mage.cards.i; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.TriggeredAbility; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.common.HateCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.TargetController; import mage.game.permanent.token.RoyalGuardToken; import mage.watchers.common.LifeLossOtherFromCombatWatcher; +import java.util.UUID; + /** - * * @author Styxo */ public final class IronFistOfTheEmpire extends CardImpl { @@ -26,13 +24,11 @@ public final class IronFistOfTheEmpire extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}{B}{R}"); // Hate — At the beggining of each end step, if opponent lost life from a source other than combat damage this turn, you gain 2 life and create a 2/2 red Soldier creature token with first strike name Royal Guard. - TriggeredAbility triggeredAbility = new BeginningOfEndStepTriggeredAbility(TargetController.ANY, new GainLifeEffect(2), false); - triggeredAbility.addEffect(new CreateTokenEffect(new RoyalGuardToken())); - Ability ability = new ConditionalInterveningIfTriggeredAbility( - triggeredAbility, - HateCondition.instance, - "Hate — At the beggining of each end step, if opponent lost life from a source other than combat damage this turn, you gain 1 life and create a 2/2 red Soldier creature token with first strike named Royal Guard."); - this.addAbility(ability, new LifeLossOtherFromCombatWatcher()); + Ability ability = new BeginningOfEndStepTriggeredAbility( + TargetController.ANY, new GainLifeEffect(2), false + ).withInterveningIf(HateCondition.instance); + ability.addEffect(new CreateTokenEffect(new RoyalGuardToken()).concatBy("and")); + this.addAbility(ability.setAbilityWord(AbilityWord.HATE), new LifeLossOtherFromCombatWatcher()); } private IronFistOfTheEmpire(final IronFistOfTheEmpire card) { diff --git a/Mage.Sets/src/mage/cards/i/IronHeartChimera.java b/Mage.Sets/src/mage/cards/i/IronHeartChimera.java index 799f7165b19..8ebc556645b 100644 --- a/Mage.Sets/src/mage/cards/i/IronHeartChimera.java +++ b/Mage.Sets/src/mage/cards/i/IronHeartChimera.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -45,7 +46,7 @@ public final class IronHeartChimera extends CardImpl { Ability ability = new SimpleActivatedAbility(new AddCountersTargetEffect(CounterType.P2P2.createInstance()), new SacrificeSourceCost()); ability.addEffect(new GainAbilityTargetEffect(VigilanceAbility.getInstance(), Duration.WhileOnBattlefield) .setText("It gains vigilance. (This effect lasts indefinitely.)")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/i/IshkanahGrafwidow.java b/Mage.Sets/src/mage/cards/i/IshkanahGrafwidow.java index cea21a63a50..eace7802f5b 100644 --- a/Mage.Sets/src/mage/cards/i/IshkanahGrafwidow.java +++ b/Mage.Sets/src/mage/cards/i/IshkanahGrafwidow.java @@ -6,15 +6,17 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.DeliriumCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.LoseLifeTargetEffect; +import mage.abilities.hint.Hint; import mage.abilities.hint.ValueHint; import mage.abilities.keyword.ReachAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; @@ -29,7 +31,10 @@ import java.util.UUID; */ public final class IshkanahGrafwidow extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.SPIDER, "Spider you control"); + private static final DynamicValue xValue = new PermanentsOnBattlefieldCount( + new FilterControlledPermanent(SubType.SPIDER, "Spider you control") + ); + private static final Hint hint = new ValueHint("Spiders you control", xValue); public IshkanahGrafwidow(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}"); @@ -43,20 +48,16 @@ public final class IshkanahGrafwidow extends CardImpl { // Delirium &mdash When Ishkanah, Grafwidow enters the battlefield, if there are four or more card types among cards in your graveyard, // create three 1/2 green Spider creature tokens with reach. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new SpiderToken(), 3), false), - DeliriumCondition.instance, - "Delirium — When {this} enters, if there are four or more card types among cards in your graveyard, " - + "create three 1/2 green Spider creature tokens with reach."); - ability.addHint(CardTypesInGraveyardCount.YOU.getHint()); - this.addAbility(ability); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new CreateTokenEffect(new SpiderToken(), 3), false + ).withInterveningIf(DeliriumCondition.instance) + .setAbilityWord(AbilityWord.DELIRIUM) + .addHint(CardTypesInGraveyardCount.YOU.getHint())); // {5}{B}: Target opponent loses 1 life for each Spider you control. - PermanentsOnBattlefieldCount count = new PermanentsOnBattlefieldCount(filter); - ability = new SimpleActivatedAbility(new LoseLifeTargetEffect(count), new ManaCostsImpl<>("{6}{B}")); + Ability ability = new SimpleActivatedAbility(new LoseLifeTargetEffect(xValue), new ManaCostsImpl<>("{6}{B}")); ability.addTarget(new TargetOpponent()); - ability.addHint(new ValueHint("Spiders you control", count)); - this.addAbility(ability); + this.addAbility(ability.addHint(hint)); } private IshkanahGrafwidow(final IshkanahGrafwidow card) { diff --git a/Mage.Sets/src/mage/cards/i/IslandOfWakWak.java b/Mage.Sets/src/mage/cards/i/IslandOfWakWak.java index 0b75eb02e36..fd027139515 100644 --- a/Mage.Sets/src/mage/cards/i/IslandOfWakWak.java +++ b/Mage.Sets/src/mage/cards/i/IslandOfWakWak.java @@ -18,6 +18,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -37,7 +38,7 @@ public final class IslandOfWakWak extends CardImpl { // {tap}: Target creature with flying has base power 0 until end of turn. Ability ability = new SimpleActivatedAbility(new IslandOfWakWakEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filterWithFlying)); + ability.addTarget(new TargetPermanent(filterWithFlying)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/i/IsolatedWatchtower.java b/Mage.Sets/src/mage/cards/i/IsolatedWatchtower.java index 7d0d9c4489e..c3119d300b2 100644 --- a/Mage.Sets/src/mage/cards/i/IsolatedWatchtower.java +++ b/Mage.Sets/src/mage/cards/i/IsolatedWatchtower.java @@ -1,11 +1,10 @@ package mage.cards.i; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.condition.Condition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.mana.ColorlessManaAbility; import mage.cards.Card; @@ -19,8 +18,9 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class IsolatedWatchtower extends CardImpl { @@ -32,11 +32,8 @@ public final class IsolatedWatchtower extends CardImpl { this.addAbility(new ColorlessManaAbility()); // {2}, {T}: Scry 1, then you may reveal the top card of your library. If a basic land card is revealed this way, put it onto the battlefield tapped. Activate this ability only if an opponent controls at least two more lands than you. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, - new IsolatedWatchtowerEffect(), - new GenericManaCost(2), - new IsolatedWatchtowerCondition() + Ability ability = new ActivateIfConditionActivatedAbility( + new IsolatedWatchtowerEffect(), new GenericManaCost(2), IsolatedWatchtowerCondition.instance ); ability.addCost(new TapSourceCost()); this.addAbility(ability); @@ -94,7 +91,8 @@ class IsolatedWatchtowerEffect extends OneShotEffect { } } -class IsolatedWatchtowerCondition implements Condition { +enum IsolatedWatchtowerCondition implements Condition { + instance; @Override public boolean apply(Game game, Ability source) { diff --git a/Mage.Sets/src/mage/cards/i/IsperiasSkywatch.java b/Mage.Sets/src/mage/cards/i/IsperiasSkywatch.java index 186570dd784..4ad79be3a97 100644 --- a/Mage.Sets/src/mage/cards/i/IsperiasSkywatch.java +++ b/Mage.Sets/src/mage/cards/i/IsperiasSkywatch.java @@ -1,7 +1,5 @@ - package mage.cards.i; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -11,17 +9,17 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.StaticFilters; -import mage.target.common.TargetCreaturePermanent; +import mage.target.common.TargetOpponentsCreaturePermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class IsperiasSkywatch extends CardImpl { - + public IsperiasSkywatch(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{U}"); this.subtype.add(SubType.VEDALKEN); this.subtype.add(SubType.KNIGHT); @@ -30,12 +28,11 @@ public final class IsperiasSkywatch extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); - + // When Isperia's Skywatch enters the battlefield, detain target creature an opponent controls. // (Until your next turn, that creature can't attack or block and its activated abilities can't be activated.) Ability ability = new EntersBattlefieldTriggeredAbility(new DetainTargetEffect()); - TargetCreaturePermanent target = new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE); - ability.addTarget(target); + ability.addTarget(new TargetOpponentsCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/i/ItlimocCradleOfTheSun.java b/Mage.Sets/src/mage/cards/i/ItlimocCradleOfTheSun.java index a1140a281d8..a9f5a6dffcc 100644 --- a/Mage.Sets/src/mage/cards/i/ItlimocCradleOfTheSun.java +++ b/Mage.Sets/src/mage/cards/i/ItlimocCradleOfTheSun.java @@ -1,11 +1,8 @@ package mage.cards.i; -import java.util.UUID; - import mage.Mana; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; +import mage.abilities.hint.common.CreaturesYouControlHint; import mage.abilities.mana.DynamicManaAbility; import mage.abilities.mana.GreenManaAbility; import mage.cards.CardImpl; @@ -14,19 +11,16 @@ import mage.constants.CardType; import mage.constants.SuperType; import mage.filter.StaticFilters; +import java.util.UUID; + /** - * * @author JRHerlehy */ public final class ItlimocCradleOfTheSun extends CardImpl { - private static final Hint hint = new ValueHint( - "Number of creatures you control", new PermanentsOnBattlefieldCount(StaticFilters.FILTER_PERMANENT_CREATURE_CONTROLLED) - ); - public ItlimocCradleOfTheSun(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); - + this.supertype.add(SuperType.LEGENDARY); // (Transforms from Growing Rites of Itlimoc.)/ @@ -36,7 +30,7 @@ public final class ItlimocCradleOfTheSun extends CardImpl { this.addAbility(new GreenManaAbility()); // {T}: Add {G} for each creature you control. - this.addAbility(new DynamicManaAbility(Mana.GreenMana(1), new PermanentsOnBattlefieldCount(StaticFilters.FILTER_PERMANENT_CREATURE_CONTROLLED)).addHint(hint)); + this.addAbility(new DynamicManaAbility(Mana.GreenMana(1), new PermanentsOnBattlefieldCount(StaticFilters.FILTER_PERMANENT_CREATURE_CONTROLLED)).addHint(CreaturesYouControlHint.instance)); } private ItlimocCradleOfTheSun(final ItlimocCradleOfTheSun card) { diff --git a/Mage.Sets/src/mage/cards/i/ItzquinthFirstbornOfGishath.java b/Mage.Sets/src/mage/cards/i/ItzquinthFirstbornOfGishath.java index 3f0183fb6f5..07410694410 100644 --- a/Mage.Sets/src/mage/cards/i/ItzquinthFirstbornOfGishath.java +++ b/Mage.Sets/src/mage/cards/i/ItzquinthFirstbornOfGishath.java @@ -16,6 +16,7 @@ import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.other.AnotherTargetPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; @@ -47,7 +48,7 @@ public final class ItzquinthFirstbornOfGishath extends CardImpl { // When Itzquinth enters the battlefield, you may pay {2}. When you do, target Dinosaur you control deals damage equal to its power to another target creature. ReflexiveTriggeredAbility reflexive = new ReflexiveTriggeredAbility(new DamageWithPowerFromOneToAnotherTargetEffect(), false); reflexive.addTarget(new TargetControlledPermanent(filter1).setTargetTag(1)); // may not be a creature. Don't ask me why. - reflexive.addTarget(new TargetCreaturePermanent(filter2).setTargetTag(2)); + reflexive.addTarget(new TargetPermanent(filter2).setTargetTag(2)); this.addAbility(new EntersBattlefieldTriggeredAbility( new DoWhenCostPaid(reflexive, new GenericManaCost(2), "Pay {2}?") )); diff --git a/Mage.Sets/src/mage/cards/i/IvoryCraneNetsuke.java b/Mage.Sets/src/mage/cards/i/IvoryCraneNetsuke.java index 18a83c4c14a..3b08be2f2af 100644 --- a/Mage.Sets/src/mage/cards/i/IvoryCraneNetsuke.java +++ b/Mage.Sets/src/mage/cards/i/IvoryCraneNetsuke.java @@ -1,31 +1,28 @@ - package mage.cards.i; -import java.util.UUID; -import mage.abilities.TriggeredAbility; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInHandCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class IvoryCraneNetsuke extends CardImpl { + private static final Condition condition = new CardsInHandCondition(ComparisonType.MORE_THAN, 6); + public IvoryCraneNetsuke(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); // At the beginning of your upkeep, if you have seven or more cards in hand, you gain 4 life. - TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new GainLifeEffect(4)); - CardsInHandCondition condition = new CardsInHandCondition(ComparisonType.MORE_THAN, 6); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, condition, "At the beginning of your upkeep, if you have seven or more cards in hand, you gain 4 life.")); - + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new GainLifeEffect(4)).withInterveningIf(condition)); } private IvoryCraneNetsuke(final IvoryCraneNetsuke card) { diff --git a/Mage.Sets/src/mage/cards/i/IvoryMask.java b/Mage.Sets/src/mage/cards/i/IvoryMask.java index 1d8d3eb5d0c..c178f6ad089 100644 --- a/Mage.Sets/src/mage/cards/i/IvoryMask.java +++ b/Mage.Sets/src/mage/cards/i/IvoryMask.java @@ -1,4 +1,3 @@ - package mage.cards.i; import java.util.UUID; @@ -19,7 +18,6 @@ public final class IvoryMask extends CardImpl { public IvoryMask(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}{W}"); - // You have shroud. this.addAbility(new SimpleStaticAbility(new GainAbilityControllerEffect(ShroudAbility.getInstance()))); } diff --git a/Mage.Sets/src/mage/cards/i/IxidorRealitySculptor.java b/Mage.Sets/src/mage/cards/i/IxidorRealitySculptor.java index 97c3b1ccba2..3fa598cc4f3 100644 --- a/Mage.Sets/src/mage/cards/i/IxidorRealitySculptor.java +++ b/Mage.Sets/src/mage/cards/i/IxidorRealitySculptor.java @@ -14,6 +14,7 @@ import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.card.FaceDownPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -44,7 +45,7 @@ public final class IxidorRealitySculptor extends CardImpl { // {2}{U}: Turn target face-down creature face up. Ability ability = new SimpleActivatedAbility(new TurnFaceUpTargetEffect(), new ManaCostsImpl<>("{2}{U}")); - ability.addTarget(new TargetCreaturePermanent(filterTarget)); + ability.addTarget(new TargetPermanent(filterTarget)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/j/JabarisInfluence.java b/Mage.Sets/src/mage/cards/j/JabarisInfluence.java index e93b88a110c..c8d546de0e8 100644 --- a/Mage.Sets/src/mage/cards/j/JabarisInfluence.java +++ b/Mage.Sets/src/mage/cards/j/JabarisInfluence.java @@ -20,6 +20,7 @@ import mage.filter.predicate.mageobject.ColorPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.watchers.Watcher; @@ -48,7 +49,7 @@ public final class JabarisInfluence extends CardImpl { // Gain control of target nonartifact, nonblack creature that attacked you this turn and put a -1/-0 counter on it. this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.Custom)); this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.M1M0.createInstance()).setText("and put a -1/-0 counter on it")); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addWatcher(new JabarisInfluenceWatcher()); } diff --git a/Mage.Sets/src/mage/cards/j/JaceIngeniousMindMage.java b/Mage.Sets/src/mage/cards/j/JaceIngeniousMindMage.java index 65ac048d787..d3181fdce1c 100644 --- a/Mage.Sets/src/mage/cards/j/JaceIngeniousMindMage.java +++ b/Mage.Sets/src/mage/cards/j/JaceIngeniousMindMage.java @@ -1,7 +1,5 @@ - package mage.cards.j; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; @@ -10,14 +8,15 @@ 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.filter.StaticFilters; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class JaceIngeniousMindMage extends CardImpl { @@ -38,7 +37,7 @@ public final class JaceIngeniousMindMage extends CardImpl { // -9: Gain control of up to three target creatures. Ability ability = new LoyaltyAbility(new GainControlTargetEffect(Duration.Custom), -9); - ability.addTarget(new TargetCreaturePermanent(0, 3, StaticFilters.FILTER_PERMANENT_CREATURES, false)); + ability.addTarget(new TargetCreaturePermanent(0, 3)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/j/JaceMirrorMage.java b/Mage.Sets/src/mage/cards/j/JaceMirrorMage.java index cfb398ddb63..f221f75e324 100644 --- a/Mage.Sets/src/mage/cards/j/JaceMirrorMage.java +++ b/Mage.Sets/src/mage/cards/j/JaceMirrorMage.java @@ -4,7 +4,6 @@ import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenCopyTargetEffect; import mage.abilities.effects.keyword.ScryEffect; @@ -41,11 +40,7 @@ public final class JaceMirrorMage extends CardImpl { this.addAbility(new KickerAbility("{2}")); // When Jace, Mirror Mage enters the battlefield, if Jace was kicked, create a token that's a copy of Jace, Mirror Mage except it's not legendary and its starting loyalty is 1. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new JaceMirrorMageCopyEffect()), - KickedCondition.ONCE, "When {this} enters, if {this} was kicked, " + - "create a token that's a copy of {this}, except it's not legendary and its starting loyalty is 1." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new JaceMirrorMageCopyEffect()).withInterveningIf(KickedCondition.ONCE)); // +1: Scry 2. this.addAbility(new LoyaltyAbility(new ScryEffect(2), 1)); @@ -68,6 +63,7 @@ class JaceMirrorMageCopyEffect extends OneShotEffect { JaceMirrorMageCopyEffect() { super(Outcome.Benefit); + staticText = "create a token that's a copy of {this}, except it's not legendary and its starting loyalty is 1."; } private JaceMirrorMageCopyEffect(final JaceMirrorMageCopyEffect effect) { diff --git a/Mage.Sets/src/mage/cards/j/JackdawSavior.java b/Mage.Sets/src/mage/cards/j/JackdawSavior.java index f5db76b14ee..dfddc7a096e 100644 --- a/Mage.Sets/src/mage/cards/j/JackdawSavior.java +++ b/Mage.Sets/src/mage/cards/j/JackdawSavior.java @@ -1,25 +1,25 @@ package mage.cards.j; import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; import mage.abilities.common.DiesThisOrAnotherTriggeredAbility; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; 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.FilterCreatureCard; -import mage.filter.predicate.Predicates; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.filter.predicate.mageobject.AbilityPredicate; -import mage.filter.predicate.mageobject.MageObjectReferencePredicate; -import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; import mage.target.common.TargetCardInYourGraveyard; +import mage.util.CardUtil; import java.util.UUID; @@ -27,6 +27,14 @@ import java.util.UUID; * @author notgreat */ public final class JackdawSavior extends CardImpl { + private static final FilterControlledCreaturePermanent flyingFilter = new FilterControlledCreaturePermanent("creature you control with flying"); + private static final FilterCard filterCard = new FilterCreatureCard("another target creature card with lesser mana value from your graveyard"); + + static { + flyingFilter.add(new AbilityPredicate(FlyingAbility.class)); + filterCard.add(JackdawSaviorPredicate.instance); + } + public JackdawSavior(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); @@ -39,7 +47,9 @@ public final class JackdawSavior extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Whenever Jackdaw Savior or another creature you control with flying dies, return another target creature card with lesser mana value from your graveyard to the battlefield. - this.addAbility(new JackdawSaviorDiesThisOrAnotherTriggeredAbility()); + Ability ability = new DiesThisOrAnotherTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect(), false, flyingFilter); + ability.addTarget(new TargetCardInYourGraveyard(filterCard)); + this.addAbility(ability); } private JackdawSavior(final JackdawSavior card) { @@ -52,40 +62,14 @@ public final class JackdawSavior extends CardImpl { } } -class JackdawSaviorDiesThisOrAnotherTriggeredAbility extends DiesThisOrAnotherTriggeredAbility { - private static final FilterControlledCreaturePermanent flyingFilter = new FilterControlledCreaturePermanent("creature you control with flying"); - - static { - flyingFilter.add(new AbilityPredicate(FlyingAbility.class)); - } - - public JackdawSaviorDiesThisOrAnotherTriggeredAbility() { - super(new ReturnFromGraveyardToBattlefieldTargetEffect().setText( - "return another target creature card with lesser mana value from your graveyard to the battlefield"), - false, flyingFilter); - } - - protected JackdawSaviorDiesThisOrAnotherTriggeredAbility(final JackdawSaviorDiesThisOrAnotherTriggeredAbility ability) { - super(ability); - } +enum JackdawSaviorPredicate implements ObjectSourcePlayerPredicate { + instance; @Override - public JackdawSaviorDiesThisOrAnotherTriggeredAbility copy() { - return new JackdawSaviorDiesThisOrAnotherTriggeredAbility(this); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (super.checkTrigger(event, game)) { - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - FilterCard filter = new FilterCreatureCard(); - filter.add(Predicates.not(new MageObjectReferencePredicate(zEvent.getTargetId(), game))); - filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, zEvent.getTarget().getManaValue())); - filter.setMessage("target creature card other than "+zEvent.getTarget().getLogName()+" with mana value less than "+zEvent.getTarget().getManaValue()); - this.getTargets().clear(); - this.addTarget(new TargetCardInYourGraveyard(filter)); - return true; - } - return false; + public boolean apply(ObjectSourcePlayer input, Game game) { + Permanent diedCreature = CardUtil.getEffectValueFromAbility(input.getSource(), "creatureDied", Permanent.class).orElse(null); + return diedCreature != null + && !input.getObject().getId().equals(diedCreature.getId()) + && input.getObject().getManaValue() < diedCreature.getManaValue(); } } diff --git a/Mage.Sets/src/mage/cards/j/JaddiLifestrider.java b/Mage.Sets/src/mage/cards/j/JaddiLifestrider.java index 128d48d778b..7d95d82d972 100644 --- a/Mage.Sets/src/mage/cards/j/JaddiLifestrider.java +++ b/Mage.Sets/src/mage/cards/j/JaddiLifestrider.java @@ -15,7 +15,7 @@ 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 mage.target.TargetPermanent; import java.util.UUID; @@ -67,7 +67,7 @@ class JaddiLifestriderEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { int tappedAmount = 0; Player you = game.getPlayer(source.getControllerId()); - TargetCreaturePermanent target = new TargetCreaturePermanent(0, Integer.MAX_VALUE, filter, true); + TargetPermanent target = new TargetPermanent(0, Integer.MAX_VALUE, filter, true); if (target.canChoose(source.getControllerId(), source, game) && target.choose(Outcome.Tap, source.getControllerId(), source.getSourceId(), source, game)) { for (UUID creatureId : target.getTargets()) { Permanent creature = game.getPermanent(creatureId); diff --git a/Mage.Sets/src/mage/cards/j/JadeStatue.java b/Mage.Sets/src/mage/cards/j/JadeStatue.java index e46a4729cc0..d735909a470 100644 --- a/Mage.Sets/src/mage/cards/j/JadeStatue.java +++ b/Mage.Sets/src/mage/cards/j/JadeStatue.java @@ -1,33 +1,35 @@ - package mage.cards.j; -import java.util.UUID; -import mage.MageInt; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.IsPhaseCondition; -import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; 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.TurnPhase; -import mage.constants.Zone; -import mage.game.permanent.token.TokenImpl; +import mage.game.permanent.token.custom.CreatureToken; + +import java.util.UUID; /** - * * @author anonymous */ public final class JadeStatue extends CardImpl { + private static final Condition condition = new IsPhaseCondition(TurnPhase.COMBAT); + public JadeStatue(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); - // {2}: Jade Statue becomes a 3/6 Golem artifact creature until end of combat. Activate this ability only during combat. - this.addAbility(new ConditionalActivatedAbility(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect (new JadeStatueToken(), CardType.ARTIFACT, Duration.EndOfCombat), new ManaCostsImpl<>("{2}"), new IsPhaseCondition(TurnPhase.COMBAT), "{2}: {this} becomes a 3/6 Golem artifact creature until end of combat. Activate only during combat.")); + this.addAbility(new ActivateIfConditionActivatedAbility(new BecomesCreatureSourceEffect( + new CreatureToken(3, 6, "3/6 Golem artifact creature", SubType.GOLEM) + .withType(CardType.ARTIFACT), CardType.ARTIFACT, Duration.EndOfCombat + ), new GenericManaCost(2), condition)); } private JadeStatue(final JadeStatue card) { @@ -38,22 +40,4 @@ public final class JadeStatue extends CardImpl { public JadeStatue copy() { return new JadeStatue(this); } - - private static class JadeStatueToken extends TokenImpl { - JadeStatueToken() { - super("", "3/6 Golem artifact creature"); - cardType.add(CardType.ARTIFACT); - cardType.add(CardType.CREATURE); - this.subtype.add(SubType.GOLEM); - power = new MageInt(3); - toughness = new MageInt(6); - } - private JadeStatueToken(final JadeStatueToken token) { - super(token); - } - - public JadeStatueToken copy() { - return new JadeStatueToken(this); - } - } } diff --git a/Mage.Sets/src/mage/cards/j/JadedSellSword.java b/Mage.Sets/src/mage/cards/j/JadedSellSword.java index 1baeb5240f7..29cf15c604d 100644 --- a/Mage.Sets/src/mage/cards/j/JadedSellSword.java +++ b/Mage.Sets/src/mage/cards/j/JadedSellSword.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TreasureSpentToCastCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.HasteAbility; @@ -13,7 +12,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.watchers.common.ManaPaidSourceWatcher; import java.util.UUID; @@ -31,15 +29,12 @@ public final class JadedSellSword extends CardImpl { this.toughness = new MageInt(3); // When Jaded Sell-Sword enters the battlefield, if mana from a Treasure was spent to cast it, it gains first strike and haste until end of turn. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new GainAbilitySourceEffect( - FirstStrikeAbility.getInstance(), Duration.EndOfTurn - )), TreasureSpentToCastCondition.instance, "When {this} enters, " + - "if mana from a Treasure was spent to cast it, it gains first strike and haste until end of turn." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new GainAbilitySourceEffect( + FirstStrikeAbility.getInstance(), Duration.EndOfTurn + ).setText("it gains first strike")).withInterveningIf(TreasureSpentToCastCondition.instance); ability.addEffect(new GainAbilitySourceEffect( HasteAbility.getInstance(), Duration.EndOfTurn - )); + ).setText("and haste until end of turn")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/j/JaggedLightning.java b/Mage.Sets/src/mage/cards/j/JaggedLightning.java index 490a278ec21..0da793f9011 100644 --- a/Mage.Sets/src/mage/cards/j/JaggedLightning.java +++ b/Mage.Sets/src/mage/cards/j/JaggedLightning.java @@ -1,16 +1,14 @@ - package mage.cards.j; -import java.util.UUID; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.StaticFilters; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LoneFox */ public final class JaggedLightning extends CardImpl { @@ -20,7 +18,7 @@ public final class JaggedLightning extends CardImpl { // Jagged Lightning deals 3 damage to each of two target creatures. this.getSpellAbility().addEffect(new DamageTargetEffect(3, true, "each of two target creatures")); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(2, 2, StaticFilters.FILTER_PERMANENT_CREATURE, false)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(2)); } private JaggedLightning(final JaggedLightning card) { diff --git a/Mage.Sets/src/mage/cards/j/JaggedPoppet.java b/Mage.Sets/src/mage/cards/j/JaggedPoppet.java index ce1ca657e24..e01eeb0da47 100644 --- a/Mage.Sets/src/mage/cards/j/JaggedPoppet.java +++ b/Mage.Sets/src/mage/cards/j/JaggedPoppet.java @@ -1,12 +1,9 @@ package mage.cards.j; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.common.DealtDamageToSourceTriggeredAbility; import mage.abilities.condition.common.HellbentCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.SavedDamageValue; import mage.abilities.effects.common.discard.DiscardControllerEffect; import mage.abilities.effects.common.discard.DiscardTargetEffect; @@ -16,8 +13,9 @@ import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; +import java.util.UUID; + /** - * * @author jerekwilson */ public final class JaggedPoppet extends CardImpl { @@ -31,15 +29,16 @@ public final class JaggedPoppet extends CardImpl { this.toughness = new MageInt(4); // Whenever Jagged Poppet is dealt damage, discard that many cards. - this.addAbility(new DealtDamageToSourceTriggeredAbility(new DiscardControllerEffect(SavedDamageValue.MANY), false)); + this.addAbility(new DealtDamageToSourceTriggeredAbility( + new DiscardControllerEffect(SavedDamageValue.MANY), false + )); // Hellbent - Whenever Jagged Poppet deals combat damage to a player, if you have no cards in hand, that player discards cards equal to the damage. - Ability hellbentAbility = new ConditionalInterveningIfTriggeredAbility( - new DealsCombatDamageToAPlayerTriggeredAbility(new DiscardTargetEffect(SavedDamageValue.MANY), false, true), - HellbentCondition.instance, - "Whenever {this} deals combat damage to a player, if you have no cards in hand, that player discards cards equal to the damage."); - hellbentAbility.setAbilityWord(AbilityWord.HELLBENT); - this.addAbility(hellbentAbility); + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility( + new DiscardTargetEffect(SavedDamageValue.MANY) + .setText("that player discards cards equal to the damage"), + false, true + ).withInterveningIf(HellbentCondition.instance).setAbilityWord(AbilityWord.HELLBENT)); } private JaggedPoppet(final JaggedPoppet card) { diff --git a/Mage.Sets/src/mage/cards/j/JaggedScarArchers.java b/Mage.Sets/src/mage/cards/j/JaggedScarArchers.java index f7f1b8944a1..28d11bf11bf 100644 --- a/Mage.Sets/src/mage/cards/j/JaggedScarArchers.java +++ b/Mage.Sets/src/mage/cards/j/JaggedScarArchers.java @@ -18,6 +18,7 @@ import mage.constants.Zone; import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -47,7 +48,7 @@ public final class JaggedScarArchers extends CardImpl { this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetBasePowerToughnessSourceEffect(new PermanentsOnBattlefieldCount(controlledElvesFilter)))); // {tap}: Jagged-Scar Archers deals damage equal to its power to target creature with flying. Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(SourcePermanentPowerValue.NOT_NEGATIVE).setText("{this} deals damage equal to its power to target creature with flying"), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(flyingCreatureFilter)); + ability.addTarget(new TargetPermanent(flyingCreatureFilter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/j/JandorsRing.java b/Mage.Sets/src/mage/cards/j/JandorsRing.java index de04870fd54..a14b0737ec6 100644 --- a/Mage.Sets/src/mage/cards/j/JandorsRing.java +++ b/Mage.Sets/src/mage/cards/j/JandorsRing.java @@ -1,44 +1,46 @@ - package mage.cards.j; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.condition.Condition; +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.decorator.ConditionalActivatedAbility; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.discard.DiscardCardYouChooseTargetEffect; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.WatcherScope; -import mage.constants.Zone; import mage.filter.FilterCard; -import mage.filter.predicate.mageobject.CardIdPredicate; +import mage.filter.predicate.Predicate; import mage.game.Game; import mage.game.events.GameEvent; -import mage.players.Player; +import mage.target.common.TargetCardInHand; import mage.watchers.Watcher; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + /** * @author MarcoMarin */ public final class JandorsRing extends CardImpl { + private static final FilterCard filter = new FilterCard("the last card you drew this turn"); + + static { + filter.add(JandorsRingPredicate.instance); + } + public JandorsRing(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}"); - Watcher watcher = new JandorsRingWatcher(); // {2}, {tap}, Discard the last card you drew this turn: Draw a card. - // TODO: discard has to be a cost not a payment during resolution - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new JandorsRingEffect(), new ManaCostsImpl<>("{2}"), WatchedCardInHandCondition.instance, "{2}, {T}, Discard the last card you drew this turn: Draw a card."); + Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new GenericManaCost(2)); ability.addCost(new TapSourceCost()); - this.addAbility(ability, watcher); + ability.addCost(new DiscardTargetCost(new TargetCardInHand(filter)).setText("discard the last card you drew this turn")); + this.addAbility(ability, new JandorsRingWatcher()); } private JandorsRing(final JandorsRing card) { @@ -51,86 +53,42 @@ public final class JandorsRing extends CardImpl { } } -class JandorsRingEffect extends OneShotEffect { - - JandorsRingEffect() { - super(Outcome.Discard); - staticText = "Draw a card"; - } - - private JandorsRingEffect(final JandorsRingEffect effect) { - super(effect); - } +enum JandorsRingPredicate implements Predicate { + instance; @Override - public JandorsRingEffect copy() { - return new JandorsRingEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - JandorsRingWatcher watcher = game.getState().getWatcher(JandorsRingWatcher.class); - if (watcher != null) { - UUID cardId = watcher.getLastDrewCard(source.getControllerId()); - Card card = game.getCard(cardId); - if (card != null) { - FilterCard filter = new FilterCard(card.getName()); - filter.add(new CardIdPredicate(card.getId())); - DiscardCardYouChooseTargetEffect effect = new DiscardCardYouChooseTargetEffect(filter); - if (effect.apply(game, source)) {//Conditional was already checked, card should be in hand, but if for some weird reason it fails, the card won't be drawn, although the cost will already be paid - Player controller = game.getPlayer(source.getControllerId()); - if(controller != null) { - controller.drawCards(1, source, game); - } - } - } - return true; - } - return false; + public boolean apply(Card input, Game game) { + return JandorsRingWatcher.checkCard(input, game); } } class JandorsRingWatcher extends Watcher { - private Map lastDrawnCards = new HashMap<>(); + private final Set set = new HashSet<>(); - public JandorsRingWatcher() { + JandorsRingWatcher() { super(WatcherScope.GAME); } @Override public void watch(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.DREW_CARD) { - lastDrawnCards.putIfAbsent(event.getPlayerId(), event.getTargetId()); + set.add(event.getTargetId()); } } @Override public void reset() { super.reset(); - lastDrawnCards.clear(); + set.clear(); } - public UUID getLastDrewCard(UUID playerId) { - return lastDrawnCards.get(playerId); + static boolean checkCard(Card card, Game game) { + return card != null + && game + .getState() + .getWatcher(JandorsRingWatcher.class) + .set + .contains(card.getId()); } } - -enum WatchedCardInHandCondition implements Condition { - - instance; - - @Override - public boolean apply(Game game, Ability source) { - JandorsRingWatcher watcher = game.getState().getWatcher(JandorsRingWatcher.class); - - return watcher != null - && game.getPlayer(source.getControllerId()).getHand().contains(watcher.getLastDrewCard(source.getControllerId())); - } - - @Override - public String toString() { - return "if last drawn card is still in hand"; - } - -} diff --git a/Mage.Sets/src/mage/cards/j/JasperaSentinel.java b/Mage.Sets/src/mage/cards/j/JasperaSentinel.java index 3e6f97cf6e3..4c206e94aef 100644 --- a/Mage.Sets/src/mage/cards/j/JasperaSentinel.java +++ b/Mage.Sets/src/mage/cards/j/JasperaSentinel.java @@ -1,32 +1,23 @@ package mage.cards.j; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.costs.common.TapTargetCost; -import mage.abilities.mana.AnyColorManaAbility; -import mage.constants.SubType; import mage.abilities.keyword.ReachAbility; +import mage.abilities.mana.AnyColorManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.constants.SubType; +import mage.filter.StaticFilters; + +import java.util.UUID; /** - * * @author weirddan455 */ public final class JasperaSentinel extends CardImpl { - private static final FilterControlledCreaturePermanent filter - = new FilterControlledCreaturePermanent("an untapped creature you control"); - - static { - filter.add(TappedPredicate.UNTAPPED); - } - public JasperaSentinel(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}"); @@ -40,7 +31,7 @@ public final class JasperaSentinel extends CardImpl { // {T}, Tap an untapped creature you control: Add one mana of any color. Ability ability = new AnyColorManaAbility(); - ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(filter))); + ability.addCost(new TapTargetCost(StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/j/JawboneSkulkin.java b/Mage.Sets/src/mage/cards/j/JawboneSkulkin.java index ae1c7205381..395983aea33 100644 --- a/Mage.Sets/src/mage/cards/j/JawboneSkulkin.java +++ b/Mage.Sets/src/mage/cards/j/JawboneSkulkin.java @@ -17,6 +17,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -36,7 +37,7 @@ public final class JawboneSkulkin extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn), new GenericManaCost(2)); - ability.addTarget(new TargetCreaturePermanent(filterRedCreature)); + ability.addTarget(new TargetPermanent(filterRedCreature)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/j/JediInstructor.java b/Mage.Sets/src/mage/cards/j/JediInstructor.java index 6b14794a12f..f5da94d0668 100644 --- a/Mage.Sets/src/mage/cards/j/JediInstructor.java +++ b/Mage.Sets/src/mage/cards/j/JediInstructor.java @@ -13,8 +13,11 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.counters.CounterType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * * @author Styxo @@ -30,7 +33,7 @@ public final class JediInstructor extends CardImpl { // When Jedi Instructor enters the battlefield, you may put a +1/+1 counter on another target creature. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), true); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); // Meditate {1}{W} diff --git a/Mage.Sets/src/mage/cards/j/JediSentinel.java b/Mage.Sets/src/mage/cards/j/JediSentinel.java index fdf53233d97..7b824dd5e5f 100644 --- a/Mage.Sets/src/mage/cards/j/JediSentinel.java +++ b/Mage.Sets/src/mage/cards/j/JediSentinel.java @@ -11,12 +11,14 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.EachTargetPointer; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author Styxo */ @@ -35,8 +37,8 @@ public final class JediSentinel extends CardImpl { // When Jedi Sentinel enters the battlefield, return another target creature you control and target creature you don't control to their owners' hands. Effect effect = new ReturnToHandTargetEffect().setTargetPointer(new EachTargetPointer()); Ability ability = new EntersBattlefieldTriggeredAbility(effect); - ability.addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); + ability.addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/j/JediStarfighter.java b/Mage.Sets/src/mage/cards/j/JediStarfighter.java index 4d2935cbafb..906fb5824ef 100644 --- a/Mage.Sets/src/mage/cards/j/JediStarfighter.java +++ b/Mage.Sets/src/mage/cards/j/JediStarfighter.java @@ -1,7 +1,6 @@ package mage.cards.j; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; @@ -15,10 +14,11 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author Styxo */ public final class JediStarfighter extends CardImpl { @@ -27,11 +27,11 @@ public final class JediStarfighter extends CardImpl { static { filter.add(SubType.JEDI.getPredicate()); - filter.add(TargetController.YOU.getControllerPredicate()); + filter.add(TargetController.YOU.getControllerPredicate()); } public JediStarfighter(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{2}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}{W}{W}"); this.subtype.add(SubType.JEDI); this.subtype.add(SubType.STARSHIP); this.power = new MageInt(2); @@ -42,7 +42,7 @@ public final class JediStarfighter extends CardImpl { // When Jedi Starfighter enters the battlefield, up to two Jedi creatures you control gain spaceflight until end of turn. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new GainAbilityTargetEffect(SpaceflightAbility.getInstance(), Duration.EndOfTurn)); - ability.addTarget(new TargetCreaturePermanent(0, 2, filter, true)); + ability.addTarget(new TargetPermanent(0, 2, filter, true)); this.addAbility(ability); // Meditate {1}{W} diff --git a/Mage.Sets/src/mage/cards/j/JeeringInstigator.java b/Mage.Sets/src/mage/cards/j/JeeringInstigator.java index 61beb4fa0ec..08b77a67d25 100644 --- a/Mage.Sets/src/mage/cards/j/JeeringInstigator.java +++ b/Mage.Sets/src/mage/cards/j/JeeringInstigator.java @@ -3,10 +3,10 @@ package mage.cards.j; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.TurnedFaceUpSourceTriggeredAbility; -import mage.abilities.condition.common.MyTurnCondition; +import mage.abilities.condition.Condition; +import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.common.NotMyTurnCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; @@ -18,9 +18,8 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.AnotherPredicate; -import mage.target.common.TargetCreaturePermanent; +import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import java.util.UUID; @@ -29,11 +28,7 @@ import java.util.UUID; */ public final class JeeringInstigator extends CardImpl { - static final private FilterCreaturePermanent filter = new FilterCreaturePermanent(); - - static { - filter.add(AnotherPredicate.instance); - } + private static final Condition condition = new InvertCondition(NotMyTurnCondition.instance, "it's your turn"); public JeeringInstigator(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); @@ -47,20 +42,16 @@ public final class JeeringInstigator extends CardImpl { this.addAbility(new MorphAbility(this, new ManaCostsImpl<>("{2}{R}"))); // When Jeering Instigator is turned face up, if it's your turn, gain control of another target creature until end of turn. Untap it. That creature gains haste until end of turn. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new TurnedFaceUpSourceTriggeredAbility(new GainControlTargetEffect(Duration.EndOfTurn), false, false), - MyTurnCondition.instance, - "When {this} is turned face up, if it's your turn, gain control of another target creature until end of turn. Untap that creature. It gains haste until end of turn."); + Ability ability = new TurnedFaceUpSourceTriggeredAbility( + new GainControlTargetEffect(Duration.EndOfTurn), false, false + ).withInterveningIf(condition); + ability.addEffect(new UntapTargetEffect().setText("Untap that creature")); + ability.addEffect(new GainAbilityTargetEffect( + HasteAbility.getInstance(), Duration.EndOfTurn + ).setText("It gains haste until end of turn")); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); ability.setWorksFaceDown(true); - Effect effect = new UntapTargetEffect(); - effect.setText("Untap that creature"); - ability.addEffect(effect); - effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn); - effect.setText("It gains haste until end of turn"); - ability.addEffect(effect); - ability.addTarget(new TargetCreaturePermanent(filter)); - ability.addHint(MyTurnHint.instance); - this.addAbility(ability); + this.addAbility(ability.addHint(MyTurnHint.instance)); } private JeeringInstigator(final JeeringInstigator card) { diff --git a/Mage.Sets/src/mage/cards/j/JennyFlint.java b/Mage.Sets/src/mage/cards/j/JennyFlint.java index 5a026b5706f..ded14374a75 100644 --- a/Mage.Sets/src/mage/cards/j/JennyFlint.java +++ b/Mage.Sets/src/mage/cards/j/JennyFlint.java @@ -1,7 +1,7 @@ package mage.cards.j; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.SacrificePermanentTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.keyword.FirstStrikeAbility; @@ -16,7 +16,7 @@ import mage.counters.CounterType; import mage.filter.FilterPermanent; import mage.filter.StaticFilters; import mage.filter.predicate.Predicates; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -53,12 +53,11 @@ public final class JennyFlint extends CardImpl { this.addAbility(new TrainingAbility()); // Whenever you sacrifice a Clue or Food, put a +1/+1 counter on another target creature you control. - TriggeredAbility trigger = new SacrificePermanentTriggeredAbility( - new AddCountersTargetEffect(CounterType.P1P1.createInstance()), - filter + Ability ability = new SacrificePermanentTriggeredAbility( + new AddCountersTargetEffect(CounterType.P1P1.createInstance()), filter ); - trigger.addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); - this.addAbility(trigger); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); + this.addAbility(ability); } private JennyFlint(final JennyFlint card) { diff --git a/Mage.Sets/src/mage/cards/j/JeskaiBarricade.java b/Mage.Sets/src/mage/cards/j/JeskaiBarricade.java index 4df70be8bff..7987818b455 100644 --- a/Mage.Sets/src/mage/cards/j/JeskaiBarricade.java +++ b/Mage.Sets/src/mage/cards/j/JeskaiBarricade.java @@ -1,4 +1,3 @@ - package mage.cards.j; import mage.MageInt; @@ -12,31 +11,30 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; -import mage.target.Target; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; /** - * * @author fireshoes */ public final class JeskaiBarricade extends CardImpl { public JeskaiBarricade(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); this.toughness = new MageInt(4); // Flash this.addAbility(FlashAbility.getInstance()); + // Defender this.addAbility(DefenderAbility.getInstance()); + // When Jeskai Barricade enters the battlefield, you may return another target creature you control to its owner's hand. Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true); - Target target = new TargetControlledCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL); - ability.addTarget(target); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/j/JeweledAmulet.java b/Mage.Sets/src/mage/cards/j/JeweledAmulet.java index 995ff03bb1a..aa31f2d3f18 100644 --- a/Mage.Sets/src/mage/cards/j/JeweledAmulet.java +++ b/Mage.Sets/src/mage/cards/j/JeweledAmulet.java @@ -2,12 +2,12 @@ package mage.cards.j; import mage.Mana; import mage.abilities.Ability; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.RemoveCountersSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.mana.ManaEffect; @@ -37,7 +37,7 @@ public final class JeweledAmulet extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{0}"); // {1}, {tap}: Put a charge counter on Jeweled Amulet. Note the type of mana spent to pay this activation cost. Activate this ability only if there are no charge counters on Jeweled Amulet. - ConditionalActivatedAbility ability = new ConditionalActivatedAbility( + Ability ability = new ActivateIfConditionActivatedAbility( new AddCountersSourceEffect(CounterType.CHARGE.createInstance(), true), new GenericManaCost(1), condition ); ability.addEffect(new JeweledAmuletAddCounterEffect()); diff --git a/Mage.Sets/src/mage/cards/j/JhoirasToolbox.java b/Mage.Sets/src/mage/cards/j/JhoirasToolbox.java index e1609e6f9c9..d089bd97b86 100644 --- a/Mage.Sets/src/mage/cards/j/JhoirasToolbox.java +++ b/Mage.Sets/src/mage/cards/j/JhoirasToolbox.java @@ -13,6 +13,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -36,7 +37,7 @@ public final class JhoirasToolbox extends CardImpl { // {2}: Regenerate target artifact creature. Ability ability = new SimpleActivatedAbility(new RegenerateTargetEffect(), new ManaCostsImpl<>("{2}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/j/Jilt.java b/Mage.Sets/src/mage/cards/j/Jilt.java index 9051022f8ec..588eb9c2133 100644 --- a/Mage.Sets/src/mage/cards/j/Jilt.java +++ b/Mage.Sets/src/mage/cards/j/Jilt.java @@ -10,6 +10,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.other.AnotherTargetPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetadjustment.ConditionalTargetAdjuster; import mage.target.targetpointer.SecondTargetPointer; @@ -41,7 +42,7 @@ public final class Jilt extends CardImpl { .setTargetPointer(new SecondTargetPointer())); this.getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(1).withChooseHint("to return to hand")); this.getSpellAbility().setTargetAdjuster(new ConditionalTargetAdjuster(KickedCondition.ONCE, true, - new TargetCreaturePermanent(filter).setTargetTag(2).withChooseHint("to deal 2 damage"))); + new TargetPermanent(filter).setTargetTag(2).withChooseHint("to deal 2 damage"))); } private Jilt(final Jilt card) { diff --git a/Mage.Sets/src/mage/cards/j/JinGitaxias.java b/Mage.Sets/src/mage/cards/j/JinGitaxias.java index 4faee7085dc..6fd9909cef0 100644 --- a/Mage.Sets/src/mage/cards/j/JinGitaxias.java +++ b/Mage.Sets/src/mage/cards/j/JinGitaxias.java @@ -4,7 +4,7 @@ import mage.MageInt; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.common.CardsInHandCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.ExileAndReturnSourceEffect; import mage.abilities.keyword.TransformAbility; @@ -48,7 +48,7 @@ public class JinGitaxias extends CardImpl { //{3}{U}: Exile Jin-Gitaxias, then return it to the battlefield transformed under its owner’s control. Activate //only as a sorcery and only if you have seven or more cards in hand. this.addAbility(new TransformAbility()); - this.addAbility(new ConditionalActivatedAbility( + this.addAbility(new ActivateIfConditionActivatedAbility( new ExileAndReturnSourceEffect(PutCards.BATTLEFIELD_TRANSFORMED), new ManaCostsImpl<>("{3}{U}"), new CardsInHandCondition(ComparisonType.MORE_THAN, 6) diff --git a/Mage.Sets/src/mage/cards/j/JiwariTheEarthAflame.java b/Mage.Sets/src/mage/cards/j/JiwariTheEarthAflame.java index 40e1d750240..3bf6a41ed56 100644 --- a/Mage.Sets/src/mage/cards/j/JiwariTheEarthAflame.java +++ b/Mage.Sets/src/mage/cards/j/JiwariTheEarthAflame.java @@ -21,6 +21,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -46,7 +47,7 @@ public final class JiwariTheEarthAflame extends CardImpl { // {X}{R}, {tap}: Jiwari, the Earth Aflame deals X damage to target creature without flying. Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(GetXValue.instance), new ManaCostsImpl<>("{X}{R}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // Channel - {X}{R}{R}{R}, Discard Jiwari: Jiwari deals X damage to each creature without flying. diff --git a/Mage.Sets/src/mage/cards/j/JoragaAuxiliary.java b/Mage.Sets/src/mage/cards/j/JoragaAuxiliary.java index e207271ca52..c2d5bbbce5b 100644 --- a/Mage.Sets/src/mage/cards/j/JoragaAuxiliary.java +++ b/Mage.Sets/src/mage/cards/j/JoragaAuxiliary.java @@ -1,7 +1,5 @@ - package mage.cards.j; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -11,13 +9,13 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author fireshoes */ public final class JoragaAuxiliary extends CardImpl { @@ -29,7 +27,7 @@ public final class JoragaAuxiliary extends CardImpl { } public JoragaAuxiliary(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}{W}"); this.subtype.add(SubType.ELF); this.subtype.add(SubType.SOLDIER); this.subtype.add(SubType.ALLY); @@ -38,7 +36,7 @@ public final class JoragaAuxiliary extends CardImpl { // {4}{G}{W}: Support 2. (Put a +1/+1 counter on each of up to two other target creatures.) Ability ability = new SimpleActivatedAbility(new SupportEffect(this, 2, true), new ManaCostsImpl<>("{4}{G}{W}")); - ability.addTarget(new TargetCreaturePermanent(0, 2, filter, false)); + ability.addTarget(new TargetPermanent(0, 2, filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/j/JosuVessLichKnight.java b/Mage.Sets/src/mage/cards/j/JosuVessLichKnight.java index c5397acc96a..016e8be553d 100644 --- a/Mage.Sets/src/mage/cards/j/JosuVessLichKnight.java +++ b/Mage.Sets/src/mage/cards/j/JosuVessLichKnight.java @@ -3,7 +3,6 @@ package mage.cards.j; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.KickerAbility; import mage.abilities.keyword.MenaceAbility; @@ -18,7 +17,7 @@ import java.util.UUID; public final class JosuVessLichKnight extends CardImpl { - public JosuVessLichKnight(UUID ownerID, CardSetInfo cardSetInfo){ + public JosuVessLichKnight(UUID ownerID, CardSetInfo cardSetInfo) { super(ownerID, cardSetInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{B}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.ZOMBIE, SubType.KNIGHT); @@ -32,12 +31,12 @@ public final class JosuVessLichKnight extends CardImpl { this.addAbility(new MenaceAbility(false)); //When Josu Vess, Lich Knight enters the battlefield, if it was kicked, create eight 2/2 black Zombie Knight creature tokens with menace. - EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ZombieKnightToken(), 8)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.ONCE, - "When {this} enters, if it was kicked, create eight 2/2 black Zombie Knight creature tokens with menace.")); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new CreateTokenEffect(new ZombieKnightToken(), 8) + ).withInterveningIf(KickedCondition.ONCE)); } - private JosuVessLichKnight(final JosuVessLichKnight card){ + private JosuVessLichKnight(final JosuVessLichKnight card) { super(card); } diff --git a/Mage.Sets/src/mage/cards/j/JubilantMascot.java b/Mage.Sets/src/mage/cards/j/JubilantMascot.java index cceafa71a50..4f706c1c689 100644 --- a/Mage.Sets/src/mage/cards/j/JubilantMascot.java +++ b/Mage.Sets/src/mage/cards/j/JubilantMascot.java @@ -1,24 +1,24 @@ package mage.cards.j; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.counter.AddCountersTargetEffect; -import mage.constants.SubType; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SubType; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class JubilantMascot extends CardImpl { @@ -43,7 +43,7 @@ public final class JubilantMascot extends CardImpl { .setText("support 2"), new ManaCostsImpl<>("{3}{W}") )); - ability.addTarget(new TargetCreaturePermanent(0, 2, filter, false)); + ability.addTarget(new TargetPermanent(0, 2, filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/j/JuniperOrderRootweaver.java b/Mage.Sets/src/mage/cards/j/JuniperOrderRootweaver.java index 0e22e065f99..3c3beccdc97 100644 --- a/Mage.Sets/src/mage/cards/j/JuniperOrderRootweaver.java +++ b/Mage.Sets/src/mage/cards/j/JuniperOrderRootweaver.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -33,11 +32,9 @@ public final class JuniperOrderRootweaver extends CardImpl { this.addAbility(new KickerAbility("{G}")); // When Juniper Order Rootweaver enters the battlefield, if it was kicked, put a +1/+1 counter on target creature you control. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility( - new AddCountersTargetEffect(CounterType.P1P1.createInstance()) - ), KickedCondition.ONCE, "When {this} enters, " + - "if it was kicked, put a +1/+1 counter on target creature you control."); + Ability ability = new EntersBattlefieldTriggeredAbility( + new AddCountersTargetEffect(CounterType.P1P1.createInstance()) + ).withInterveningIf(KickedCondition.ONCE); ability.addTarget(new TargetControlledCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KamiOfCelebration.java b/Mage.Sets/src/mage/cards/k/KamiOfCelebration.java index 3ae960bcfd2..5c36864c75d 100644 --- a/Mage.Sets/src/mage/cards/k/KamiOfCelebration.java +++ b/Mage.Sets/src/mage/cards/k/KamiOfCelebration.java @@ -1,21 +1,17 @@ package mage.cards.k; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.AttacksCreatureYouControlTriggeredAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.effects.common.ExileTopXMayPlayUntilEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; 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.counters.CounterType; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.permanent.ModifiedPredicate; -import mage.game.Game; -import mage.game.events.GameEvent; import mage.target.common.TargetControlledCreaturePermanent; import java.util.UUID; @@ -45,7 +41,12 @@ public final class KamiOfCelebration extends CardImpl { )); // Whenever you cast a spell from exile, put a +1/+1 counter on target creature you control. - this.addAbility(new KamiOfCelebrationAbility()); + Ability ability = new SpellCastControllerTriggeredAbility( + Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.P1P1.createInstance()), null, + false, SetTargetPointer.NONE, Zone.EXILED + ); + ability.addTarget(new TargetControlledCreaturePermanent()); + this.addAbility(ability); } private KamiOfCelebration(final KamiOfCelebration card) { @@ -57,30 +58,3 @@ public final class KamiOfCelebration extends CardImpl { return new KamiOfCelebration(this); } } - -class KamiOfCelebrationAbility extends SpellCastControllerTriggeredAbility { - - KamiOfCelebrationAbility() { - super(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), false); - this.addTarget(new TargetControlledCreaturePermanent()); - } - - private KamiOfCelebrationAbility(final KamiOfCelebrationAbility ability) { - super(ability); - } - - @Override - public KamiOfCelebrationAbility copy() { - return new KamiOfCelebrationAbility(this); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return event.getZone() == Zone.EXILED && super.checkTrigger(event, game); - } - - @Override - public String getRule() { - return "Whenever you cast a spell from exile, put a +1/+1 counter on target creature you control."; - } -} diff --git a/Mage.Sets/src/mage/cards/k/KangeeAerieKeeper.java b/Mage.Sets/src/mage/cards/k/KangeeAerieKeeper.java index f33970abf0a..2fe9d2e2682 100644 --- a/Mage.Sets/src/mage/cards/k/KangeeAerieKeeper.java +++ b/Mage.Sets/src/mage/cards/k/KangeeAerieKeeper.java @@ -1,11 +1,10 @@ package mage.cards.k; import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.dynamicvalue.common.GetXValue; import mage.abilities.effects.common.continuous.BoostAllEffect; @@ -14,7 +13,10 @@ import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +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.mageobject.AnotherPredicate; @@ -33,6 +35,8 @@ public final class KangeeAerieKeeper extends CardImpl { filter.add(AnotherPredicate.instance); } + private static final DynamicValue xValue = new CountersSourceCount(CounterType.FEATHER); + public KangeeAerieKeeper(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{U}"); this.supertype.add(SuperType.LEGENDARY); @@ -49,11 +53,15 @@ public final class KangeeAerieKeeper extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When Kangee, Aerie Keeper enters the battlefield, if it was kicked, put X feather counters on it. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new AddCountersSourceEffect(CounterType.FEATHER.createInstance(), GetXValue.instance, true)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.ONCE, "When {this} enters, if it was kicked, put X feather counters on it.")); + this.addAbility(new EntersBattlefieldTriggeredAbility(new AddCountersSourceEffect( + CounterType.FEATHER.createInstance(), GetXValue.instance, true + )).withInterveningIf(KickedCondition.ONCE).withRuleTextReplacement(true)); // Other Bird creatures get +1/+1 for each feather counter on Kangee, Aerie Keeper. - this.addAbility(new SimpleStaticAbility(new BoostAllEffect(new CountersSourceCount(CounterType.FEATHER), new CountersSourceCount(CounterType.FEATHER), Duration.WhileOnBattlefield, filter, true, "Other Bird creatures get +1/+1 for each feather counter on {this}."))); + this.addAbility(new SimpleStaticAbility(new BoostAllEffect( + xValue, xValue, Duration.WhileOnBattlefield, filter, true, + "Other Bird creatures get +1/+1 for each feather counter on {this}." + ))); } private KangeeAerieKeeper(final KangeeAerieKeeper card) { diff --git a/Mage.Sets/src/mage/cards/k/Karakas.java b/Mage.Sets/src/mage/cards/k/Karakas.java index de9281807f1..c122c59fded 100644 --- a/Mage.Sets/src/mage/cards/k/Karakas.java +++ b/Mage.Sets/src/mage/cards/k/Karakas.java @@ -13,6 +13,7 @@ import mage.constants.CardType; import mage.constants.SuperType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -34,7 +35,7 @@ public final class Karakas extends CardImpl { this.addAbility(new WhiteManaAbility()); // {T}: Return target legendary creature to its owner's hand. Ability ability = new SimpleActivatedAbility(new ReturnToHandTargetEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KarazikarTheEyeTyrant.java b/Mage.Sets/src/mage/cards/k/KarazikarTheEyeTyrant.java index 368a9b6c0df..87999eba723 100644 --- a/Mage.Sets/src/mage/cards/k/KarazikarTheEyeTyrant.java +++ b/Mage.Sets/src/mage/cards/k/KarazikarTheEyeTyrant.java @@ -1,22 +1,20 @@ package mage.cards.k; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility; import mage.abilities.effects.common.*; import mage.abilities.effects.common.combat.GoadTargetEffect; 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.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.events.GameEvent; -import mage.players.Player; import mage.target.TargetPermanent; +import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster; import mage.target.targetpointer.FixedTarget; import java.util.Set; @@ -26,6 +24,7 @@ import java.util.UUID; * @author TheElk801 */ public final class KarazikarTheEyeTyrant extends CardImpl { + FilterPermanent filter = new FilterCreaturePermanent("creature that player controls"); public KarazikarTheEyeTyrant(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{R}"); @@ -36,7 +35,11 @@ public final class KarazikarTheEyeTyrant extends CardImpl { this.toughness = new MageInt(5); // Whenever you attack a player, tap target creature that player controls and goad it. - this.addAbility(new KarazikarTheEyeTyrantFirstTriggeredAbility()); + Ability ability = new AttacksPlayerWithCreaturesTriggeredAbility(new TapTargetEffect(), SetTargetPointer.PLAYER); + ability.addEffect(new GoadTargetEffect().setText("goad it. " + GoadTargetEffect.goadReminderText).concatBy("and")); + ability.addTarget(new TargetPermanent(filter)); + ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster()); + this.addAbility(ability); // Whenever an opponent attacks another one of your opponents, you and the attacking player each draw a card and lose 1 life. this.addAbility(new KarazikarTheEyeTyrantSecondTriggeredAbility()); @@ -52,49 +55,6 @@ public final class KarazikarTheEyeTyrant extends CardImpl { } } -class KarazikarTheEyeTyrantFirstTriggeredAbility extends TriggeredAbilityImpl { - - KarazikarTheEyeTyrantFirstTriggeredAbility() { - super(Zone.BATTLEFIELD, new TapTargetEffect(), false); - this.addEffect(new GoadTargetEffect()); - } - - private KarazikarTheEyeTyrantFirstTriggeredAbility(final KarazikarTheEyeTyrantFirstTriggeredAbility ability) { - super(ability); - } - - @Override - public KarazikarTheEyeTyrantFirstTriggeredAbility copy() { - return new KarazikarTheEyeTyrantFirstTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DEFENDER_ATTACKED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (!isControlledBy(event.getPlayerId())) { - return false; - } - Player player = game.getPlayer(event.getTargetId()); - if (player == null) { - return false; - } - FilterPermanent filter = new FilterCreaturePermanent("creature controlled by " + player.getName()); - filter.add(new ControllerIdPredicate(player.getId())); - this.getTargets().clear(); - this.addTarget(new TargetPermanent(filter)); - return true; - } - - @Override - public String getRule() { - return "Whenever you attack a player, tap target creature that player controls and goad it."; - } -} - class KarazikarTheEyeTyrantSecondTriggeredAbility extends TriggeredAbilityImpl { KarazikarTheEyeTyrantSecondTriggeredAbility() { diff --git a/Mage.Sets/src/mage/cards/k/KarlachFuryOfAvernus.java b/Mage.Sets/src/mage/cards/k/KarlachFuryOfAvernus.java index a606bfc31e4..0effa284293 100644 --- a/Mage.Sets/src/mage/cards/k/KarlachFuryOfAvernus.java +++ b/Mage.Sets/src/mage/cards/k/KarlachFuryOfAvernus.java @@ -5,16 +5,17 @@ import mage.abilities.Ability; import mage.abilities.common.AttacksWithCreaturesTriggeredAbility; import mage.abilities.common.ChooseABackgroundAbility; import mage.abilities.condition.common.FirstCombatPhaseCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.AdditionalCombatPhaseEffect; import mage.abilities.effects.common.UntapAllEffect; import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.filter.StaticFilters; -import mage.game.Game; import java.util.UUID; @@ -33,17 +34,13 @@ public final class KarlachFuryOfAvernus extends CardImpl { this.toughness = new MageInt(4); // Whenever you attack, if it's the first combat phase of the turn, untap all attacking creatures. They gain first strike until end of turn. After this phase, there is an additional combat phase. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new AttacksWithCreaturesTriggeredAbility( - new UntapAllEffect(StaticFilters.FILTER_ATTACKING_CREATURES), 1 - ), FirstCombatPhaseCondition.instance, "Whenever you attack, if it's the first " + - "combat phase of the turn, untap all attacking creatures. They gain first strike " + - "until end of turn. After this phase, there is an additional combat phase." - ); + Ability ability = new AttacksWithCreaturesTriggeredAbility( + new UntapAllEffect(StaticFilters.FILTER_ATTACKING_CREATURES), 1 + ).withInterveningIf(FirstCombatPhaseCondition.instance); ability.addEffect(new GainAbilityAllEffect( FirstStrikeAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_ATTACKING_CREATURES - )); + ).setText("They gain first strike until end of turn")); ability.addEffect(new AdditionalCombatPhaseEffect()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/k/KarmicJustice.java b/Mage.Sets/src/mage/cards/k/KarmicJustice.java index 68bb6406d27..ef9e7be0aa1 100644 --- a/Mage.Sets/src/mage/cards/k/KarmicJustice.java +++ b/Mage.Sets/src/mage/cards/k/KarmicJustice.java @@ -1,7 +1,6 @@ package mage.cards.k; -import java.util.UUID; import mage.MageObject; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.common.DestroyTargetEffect; @@ -15,6 +14,9 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.target.Target; import mage.target.TargetPermanent; +import mage.target.targetadjustment.DefineByTriggerTargetAdjuster; + +import java.util.UUID; /** * @@ -25,7 +27,6 @@ public final class KarmicJustice extends CardImpl { public KarmicJustice(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}"); - // Whenever a spell or ability an opponent controls destroys a noncreature permanent you control, you may destroy target permanent that opponent controls. this.addAbility(new KarmicJusticeTriggeredAbility()); } @@ -45,8 +46,9 @@ class KarmicJusticeTriggeredAbility extends TriggeredAbilityImpl { KarmicJusticeTriggeredAbility() { super(Zone.BATTLEFIELD, new DestroyTargetEffect(), true); this.setLeavesTheBattlefieldTrigger(true); + this.setTargetAdjuster(DefineByTriggerTargetAdjuster.instance); } - + private KarmicJusticeTriggeredAbility(final KarmicJusticeTriggeredAbility ability) { super(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KarplusanHound.java b/Mage.Sets/src/mage/cards/k/KarplusanHound.java index cfd0c78ea9d..39ef5994d2c 100644 --- a/Mage.Sets/src/mage/cards/k/KarplusanHound.java +++ b/Mage.Sets/src/mage/cards/k/KarplusanHound.java @@ -1,11 +1,10 @@ package mage.cards.k; -import java.util.UUID; 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.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -14,27 +13,26 @@ import mage.constants.SubType; import mage.filter.common.FilterPlaneswalkerPermanent; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class KarplusanHound extends CardImpl { + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterPlaneswalkerPermanent(SubType.CHANDRA, "you control a Chandra planeswalker") + ); + public KarplusanHound(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); this.subtype.add(SubType.DOG); this.power = new MageInt(3); this.toughness = new MageInt(3); - FilterPlaneswalkerPermanent filter = new FilterPlaneswalkerPermanent("a Chandra planeswalker"); - filter.add(SubType.CHANDRA.getPredicate()); + // Whenever Karplusan Hound attacks, if you control a Chandra planeswalker, this creature deals 2 damage to any target. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new DamageTargetEffect(2), false), - new PermanentsOnTheBattlefieldCondition(filter), - "Whenever {this} attacks, if you control a Chandra planeswalker, " - + "this creature deals 2 damage to any target" - ); + Ability ability = new AttacksTriggeredAbility(new DamageTargetEffect(2)).withInterveningIf(condition); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KavuTitan.java b/Mage.Sets/src/mage/cards/k/KavuTitan.java index a60db4425a1..5e2a273fb83 100644 --- a/Mage.Sets/src/mage/cards/k/KavuTitan.java +++ b/Mage.Sets/src/mage/cards/k/KavuTitan.java @@ -1,7 +1,5 @@ - package mage.cards.k; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; @@ -13,18 +11,19 @@ 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.counters.CounterType; +import java.util.UUID; + /** - * * @author Backfir3 */ public final class KavuTitan extends CardImpl { public KavuTitan(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); this.subtype.add(SubType.KAVU); this.power = new MageInt(2); @@ -32,10 +31,12 @@ public final class KavuTitan extends CardImpl { // Kicker {2}{G} this.addAbility(new KickerAbility("{2}{G}")); + // If Kavu Titan was kicked, it enters with three +1/+1 counters on it and with trample. - Ability ability = new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(3)), - KickedCondition.ONCE, - "If Kavu Titan was kicked, it enters with three +1/+1 counters on it and with trample.", ""); + Ability ability = new EntersBattlefieldAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance(3)), KickedCondition.ONCE, + "If {this} was kicked, it enters with three +1/+1 counters on it and with trample.", "" + ); ability.addEffect(new GainAbilitySourceEffect(TrampleAbility.getInstance(), Duration.WhileOnBattlefield)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KayaGhostAssassin.java b/Mage.Sets/src/mage/cards/k/KayaGhostAssassin.java index c091b26812c..a3a1d8be781 100644 --- a/Mage.Sets/src/mage/cards/k/KayaGhostAssassin.java +++ b/Mage.Sets/src/mage/cards/k/KayaGhostAssassin.java @@ -13,7 +13,6 @@ import mage.abilities.effects.common.discard.DiscardEachPlayerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -27,8 +26,6 @@ import java.util.UUID; */ public final class KayaGhostAssassin extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("target creature to exile. Choose no targets to exile Kaya."); - public KayaGhostAssassin(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{W}{B}"); this.supertype.add(SuperType.LEGENDARY); @@ -39,21 +36,17 @@ public final class KayaGhostAssassin extends CardImpl { // 0: Exile Kaya, Ghost Assassin or up to one target creature. Return that card to the battlefield under its owner's control at the beginning of your next upkeep. // You lose 2 life. Ability ability = new LoyaltyAbility(new KayaGhostAssassinEffect(), 0); - ability.addTarget(new TargetCreaturePermanent(0, 1, filter, false)); + ability.addTarget(new TargetCreaturePermanent(0, 1).withChooseHint("Choose no targets to exile Kaya")); this.addAbility(ability); // -1: Each opponent loses 2 life and you gain 2 life. ability = new LoyaltyAbility(new LoseLifeOpponentsEffect(2), -1); - Effect effect = new GainLifeEffect(2); - effect.setText("and you gain 2 life"); - ability.addEffect(effect); + ability.addEffect(new GainLifeEffect(2).setText("and you gain 2 life")); this.addAbility(ability); // -2: Each opponent discards a card and you draw a card. ability = new LoyaltyAbility(new DiscardEachPlayerEffect(TargetController.OPPONENT), -2); - effect = new DrawCardSourceControllerEffect(1); - effect.setText("and you draw a card"); - ability.addEffect(effect); + ability.addEffect(new DrawCardSourceControllerEffect(1).setText("and you draw a card")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KayaTheInexorable.java b/Mage.Sets/src/mage/cards/k/KayaTheInexorable.java index cc1ab89fcaf..df3d529fd39 100644 --- a/Mage.Sets/src/mage/cards/k/KayaTheInexorable.java +++ b/Mage.Sets/src/mage/cards/k/KayaTheInexorable.java @@ -1,6 +1,5 @@ package mage.cards.k; -import mage.MageObject; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; @@ -22,21 +21,20 @@ import mage.game.Game; import mage.game.command.emblems.KayaTheInexorableEmblem; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; -import mage.game.permanent.Permanent; import mage.game.permanent.token.SpiritWhiteToken; import mage.players.Player; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetNonlandPermanent; import java.util.UUID; /** - * * @author weirddan455 */ public final class KayaTheInexorable extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken creature"); + static { filter.add(TokenPredicate.FALSE); } @@ -52,7 +50,7 @@ public final class KayaTheInexorable extends CardImpl { LoyaltyAbility ability = new LoyaltyAbility(new AddCountersTargetEffect(CounterType.GHOSTFORM.createInstance()), 1); ability.addEffect(new GainAbilityTargetEffect(new KayaTheInexorableTriggeredAbility(), Duration.WhileOnBattlefield, "It gains \"When this creature dies or is put into exile, return it to its owner's hand and create a 1/1 white Spirit creature token with flying.\"")); - ability.addTarget(new TargetCreaturePermanent(0, 1, filter, false)); + ability.addTarget(new TargetPermanent(0, 1, filter)); this.addAbility(ability); // −3: Exile target nonland permanent. diff --git a/Mage.Sets/src/mage/cards/k/KeeperOfKeys.java b/Mage.Sets/src/mage/cards/k/KeeperOfKeys.java index a35271883d5..86b92e316aa 100644 --- a/Mage.Sets/src/mage/cards/k/KeeperOfKeys.java +++ b/Mage.Sets/src/mage/cards/k/KeeperOfKeys.java @@ -1,24 +1,23 @@ package mage.cards.k; -import java.util.UUID; import mage.MageInt; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.MonarchIsSourceControllerCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.BecomesMonarchSourceEffect; import mage.abilities.effects.common.combat.CantBeBlockedAllEffect; import mage.abilities.hint.common.MonarchHint; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.filter.StaticFilters; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class KeeperOfKeys extends CardImpl { @@ -36,10 +35,9 @@ public final class KeeperOfKeys extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new BecomesMonarchSourceEffect()).addHint(MonarchHint.instance)); // At the beginning of your upkeep, if you're the monarch, creatures you control can't be blocked this turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfUpkeepTriggeredAbility( - new CantBeBlockedAllEffect(StaticFilters.FILTER_CONTROLLED_CREATURES, Duration.EndOfTurn) - ), MonarchIsSourceControllerCondition.instance, - "At the beginning of your upkeep, if you're the monarch, creatures you control can't be blocked this turn.")); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new CantBeBlockedAllEffect( + StaticFilters.FILTER_CONTROLLED_CREATURES, Duration.EndOfTurn + )).withInterveningIf(MonarchIsSourceControllerCondition.instance)); } private KeeperOfKeys(final KeeperOfKeys card) { diff --git a/Mage.Sets/src/mage/cards/k/KeeperOfTheAccord.java b/Mage.Sets/src/mage/cards/k/KeeperOfTheAccord.java index 1c90188f3da..6867dc7a039 100644 --- a/Mage.Sets/src/mage/cards/k/KeeperOfTheAccord.java +++ b/Mage.Sets/src/mage/cards/k/KeeperOfTheAccord.java @@ -2,11 +2,10 @@ package mage.cards.k; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -43,22 +42,14 @@ public final class KeeperOfTheAccord extends CardImpl { this.toughness = new MageInt(4); // At the beginning of each opponent's end step, if that player controls more creatures than you, create a 1/1 white Soldier creature token. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - TargetController.OPPONENT, new CreateTokenEffect(new SoldierToken()), false - ), KeeperOfTheAccordCondition.CREATURES, "At the beginning of each opponent's end step, " + - "if that player controls more creatures than you, create a 1/1 white Soldier creature token." - )); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.OPPONENT, new CreateTokenEffect(new SoldierToken()), false + ).withInterveningIf(KeeperOfTheAccordCondition.CREATURES)); // At the beginning of each opponent's end step, if that player controls more lands than you, you may search your library for a basic Plains card, put it onto the battlefield tapped, then shuffle your library. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility(TargetController.OPPONENT, new SearchLibraryPutInPlayEffect( - new TargetCardInLibrary(filter), true - ), true), - KeeperOfTheAccordCondition.LANDS, "At the beginning of each opponent's end step, " + - "if that player controls more lands than you, you may search your library for a basic Plains card, " + - "put it onto the battlefield tapped, then shuffle." - )); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.OPPONENT, new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter), true), true + ).withInterveningIf(KeeperOfTheAccordCondition.LANDS)); } private KeeperOfTheAccord(final KeeperOfTheAccord card) { @@ -73,8 +64,8 @@ public final class KeeperOfTheAccord extends CardImpl { enum KeeperOfTheAccordCondition implements Condition { - CREATURES(StaticFilters.FILTER_PERMANENT_CREATURE), - LANDS(StaticFilters.FILTER_LAND); + CREATURES(StaticFilters.FILTER_PERMANENT_CREATURES), + LANDS(StaticFilters.FILTER_LANDS); private final FilterPermanent filter; @@ -87,4 +78,9 @@ enum KeeperOfTheAccordCondition implements Condition { return game.getBattlefield().countAll(filter, source.getControllerId(), game) < game.getBattlefield().countAll(filter, game.getActivePlayerId(), game); } + + @Override + public String toString() { + return "that player controls more " + filter.getMessage() + " than you"; + } } diff --git a/Mage.Sets/src/mage/cards/k/KeeperOfTheMind.java b/Mage.Sets/src/mage/cards/k/KeeperOfTheMind.java index a2329e6df87..2a412b08e09 100644 --- a/Mage.Sets/src/mage/cards/k/KeeperOfTheMind.java +++ b/Mage.Sets/src/mage/cards/k/KeeperOfTheMind.java @@ -5,14 +5,12 @@ import mage.abilities.Ability; import mage.abilities.condition.Condition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; -import mage.abilities.effects.Effect; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.FilterOpponent; import mage.filter.predicate.ObjectSourcePlayer; import mage.filter.predicate.ObjectSourcePlayerPredicate; @@ -38,12 +36,12 @@ public class KeeperOfTheMind extends CardImpl { this.toughness = new MageInt(2); // {U}, {tap}: Choose target opponent who had at least two more cards in hand than you did as you activated this ability. Draw a card. - Effect effect = new DrawCardSourceControllerEffect(1); - effect.setText("Choose target opponent who had at least two more cards in hand than you did as you activated this ability. Draw a card."); - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, effect, new ManaCostsImpl<>("{U}"), KeeperOfTheMindCondition.instance, - "{U}, {T}: Choose target opponent who had at least two more cards in " - + "hand than you did as you activated this ability. Draw a card."); + Ability ability = new ActivateIfConditionActivatedAbility( + new DrawCardSourceControllerEffect(1) + .setText("choose target opponent who has at least two more cards " + + "in hand than you do as you activate this ability. Draw a card"), + new ManaCostsImpl<>("{U}"), KeeperOfTheMindCondition.instance + ).hideCondition(); ability.addCost(new TapSourceCost()); ability.setTargetAdjuster(KeeperOfTheMindAdjuster.instance); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/k/KeepsakeGorgon.java b/Mage.Sets/src/mage/cards/k/KeepsakeGorgon.java index ada8df11c62..0e1fbe64369 100644 --- a/Mage.Sets/src/mage/cards/k/KeepsakeGorgon.java +++ b/Mage.Sets/src/mage/cards/k/KeepsakeGorgon.java @@ -16,6 +16,7 @@ import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -43,7 +44,7 @@ public final class KeepsakeGorgon extends CardImpl { this.addAbility(new MonstrosityAbility("{5}{B}{B}", 1)); // When Keepsake Gorgon becomes monstrous, destroy target non-Gorgon creature an opponent controls. Ability ability = new BecomesMonstrousSourceTriggeredAbility(new DestroyTargetEffect()); - Target target = new TargetCreaturePermanent(filter); + Target target = new TargetPermanent(filter); ability.addTarget(target); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KefnetsMonument.java b/Mage.Sets/src/mage/cards/k/KefnetsMonument.java index 87763e026e9..9ce129baa4c 100644 --- a/Mage.Sets/src/mage/cards/k/KefnetsMonument.java +++ b/Mage.Sets/src/mage/cards/k/KefnetsMonument.java @@ -15,10 +15,13 @@ import mage.filter.FilterCard; import mage.filter.StaticFilters; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * @author fireshoes */ @@ -43,7 +46,7 @@ public final class KefnetsMonument extends CardImpl { new DontUntapInControllersNextUntapStepTargetEffect(), StaticFilters.FILTER_SPELL_A_CREATURE, false ); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KeldonBerserker.java b/Mage.Sets/src/mage/cards/k/KeldonBerserker.java index 59237df12a6..a94521f8c77 100644 --- a/Mage.Sets/src/mage/cards/k/KeldonBerserker.java +++ b/Mage.Sets/src/mage/cards/k/KeldonBerserker.java @@ -1,33 +1,36 @@ package mage.cards.k; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; -import mage.abilities.condition.InvertCondition; +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.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.ComparisonType; import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledLandPermanent; import mage.filter.predicate.permanent.TappedPredicate; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class KeldonBerserker extends CardImpl { - private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent("untapped lands"); + private static final FilterPermanent filter = new FilterControlledLandPermanent("you control no untapped lands"); static { filter.add(TappedPredicate.UNTAPPED); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.EQUAL_TO, 0); + public KeldonBerserker(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); @@ -38,11 +41,9 @@ public final class KeldonBerserker extends CardImpl { this.toughness = new MageInt(3); // Whenever Keldon Berserker attacks, if you control no untapped lands, it gets +3/+0 until end of turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new BoostSourceEffect(3, 0, Duration.EndOfTurn), false), - new InvertCondition(new PermanentsOnTheBattlefieldCondition(filter)), - "Whenever {this} attacks, if you control no untapped lands, it gets +3/+0 until end of turn." - )); + this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect( + 3, 0, Duration.EndOfTurn, "it" + )).withInterveningIf(condition)); } private KeldonBerserker(final KeldonBerserker card) { diff --git a/Mage.Sets/src/mage/cards/k/KeldonMegaliths.java b/Mage.Sets/src/mage/cards/k/KeldonMegaliths.java index 86f0465ada6..1939b88493a 100644 --- a/Mage.Sets/src/mage/cards/k/KeldonMegaliths.java +++ b/Mage.Sets/src/mage/cards/k/KeldonMegaliths.java @@ -5,14 +5,13 @@ import mage.abilities.common.EntersBattlefieldTappedAbility; import mage.abilities.condition.common.HellbentCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.mana.RedManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AbilityWord; import mage.constants.CardType; -import mage.constants.Zone; import mage.target.common.TargetAnyTarget; import java.util.UUID; @@ -27,12 +26,13 @@ public final class KeldonMegaliths extends CardImpl { // Keldon Megaliths enters the battlefield tapped. this.addAbility(new EntersBattlefieldTappedAbility()); + // {tap}: Add {R}. this.addAbility(new RedManaAbility()); + // Hellbent - {1}{R}, {tap}: Keldon Megaliths deals 1 damage to any target. Activate this ability only if you have no cards in hand. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, new DamageTargetEffect(1), - new ManaCostsImpl<>("{1}{R}"), HellbentCondition.instance + Ability ability = new ActivateIfConditionActivatedAbility( + new DamageTargetEffect(1), new ManaCostsImpl<>("{1}{R}"), HellbentCondition.instance ); ability.setAbilityWord(AbilityWord.HELLBENT); ability.addCost(new TapSourceCost()); diff --git a/Mage.Sets/src/mage/cards/k/KeldonOverseer.java b/Mage.Sets/src/mage/cards/k/KeldonOverseer.java index 7634b4ec17e..17ea8c590b9 100644 --- a/Mage.Sets/src/mage/cards/k/KeldonOverseer.java +++ b/Mage.Sets/src/mage/cards/k/KeldonOverseer.java @@ -1,12 +1,9 @@ - package mage.cards.k; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; @@ -19,8 +16,9 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class KeldonOverseer extends CardImpl { @@ -40,12 +38,15 @@ public final class KeldonOverseer extends CardImpl { this.addAbility(HasteAbility.getInstance()); // When Keldon Overseer enters the battlefield, if it was kicked, gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new GainControlTargetEffect(Duration.EndOfTurn, true)); - ability.addEffect(new UntapTargetEffect()); - ability.addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn)); + Ability ability = new EntersBattlefieldTriggeredAbility( + new GainControlTargetEffect(Duration.EndOfTurn) + ).withInterveningIf(KickedCondition.ONCE); + ability.addEffect(new UntapTargetEffect("Untap that creature")); + ability.addEffect(new GainAbilityTargetEffect( + HasteAbility.getInstance(), Duration.EndOfTurn + ).setText("It gains haste until end of turn")); ability.addTarget(new TargetCreaturePermanent()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.ONCE, - "When {this} enters, if it was kicked, gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn.")); + this.addAbility(ability); } private KeldonOverseer(final KeldonOverseer card) { diff --git a/Mage.Sets/src/mage/cards/k/KeldonStrikeTeam.java b/Mage.Sets/src/mage/cards/k/KeldonStrikeTeam.java index d718011d349..2f30c861bb1 100644 --- a/Mage.Sets/src/mage/cards/k/KeldonStrikeTeam.java +++ b/Mage.Sets/src/mage/cards/k/KeldonStrikeTeam.java @@ -6,7 +6,6 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.KickedCondition; import mage.abilities.condition.common.SourceEnteredThisTurnCondition; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.keyword.HasteAbility; @@ -38,11 +37,9 @@ public final class KeldonStrikeTeam extends CardImpl { this.addAbility(new KickerAbility("{1}{W}")); // When Keldon Strike Team enters the battlefield, if it was kicked, create two 1/1 white Soldier creature tokens. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new SoldierToken(), 2)), - KickedCondition.ONCE, "When {this} enters, if it was kicked, " + - "create two 1/1 white Soldier creature tokens." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new CreateTokenEffect(new SoldierToken(), 2) + ).withInterveningIf(KickedCondition.ONCE)); // As long as Keldon Strike Team entered the battlefield this turn, creatures you control have haste. this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect( @@ -50,7 +47,7 @@ public final class KeldonStrikeTeam extends CardImpl { HasteAbility.getInstance(), Duration.WhileOnBattlefield, StaticFilters.FILTER_CONTROLLED_CREATURE ), SourceEnteredThisTurnCondition.DID, "as long as {this} " + - "entered the battlefield this turn, creatures you control have haste" + "entered this turn, creatures you control have haste" ))); } diff --git a/Mage.Sets/src/mage/cards/k/KelpieGuide.java b/Mage.Sets/src/mage/cards/k/KelpieGuide.java index 8637b8b6589..10d5d81af0e 100644 --- a/Mage.Sets/src/mage/cards/k/KelpieGuide.java +++ b/Mage.Sets/src/mage/cards/k/KelpieGuide.java @@ -15,7 +15,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.StaticFilters; import mage.filter.common.FilterControlledLandPermanent; import mage.target.TargetPermanent; @@ -27,9 +26,9 @@ import java.util.UUID; */ public final class KelpieGuide extends CardImpl { - private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent("you control eight or more lands"); - private static final Condition condition - = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 7); + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledLandPermanent("you control eight or more lands"), ComparisonType.MORE_THAN, 7 + ); public KelpieGuide(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); @@ -44,9 +43,7 @@ public final class KelpieGuide extends CardImpl { this.addAbility(ability); // {T}: Tap target permanent. Activate only if you control eight or more lands. - ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new TapTargetEffect(), new TapSourceCost(), condition - ); + ability = new ActivateIfConditionActivatedAbility(new TapTargetEffect(), new TapSourceCost(), condition); ability.addTarget(new TargetPermanent()); this.addAbility(ability.addHint(LandsYouControlHint.instance)); } diff --git a/Mage.Sets/src/mage/cards/k/KelsinkoRanger.java b/Mage.Sets/src/mage/cards/k/KelsinkoRanger.java index 618b18f0e61..644cccb0c2c 100644 --- a/Mage.Sets/src/mage/cards/k/KelsinkoRanger.java +++ b/Mage.Sets/src/mage/cards/k/KelsinkoRanger.java @@ -17,6 +17,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -44,7 +45,7 @@ public final class KelsinkoRanger extends CardImpl { new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{1}{W}") ); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/Kezzerdrix.java b/Mage.Sets/src/mage/cards/k/Kezzerdrix.java index 2e4e111d1f2..f4fc06f471d 100644 --- a/Mage.Sets/src/mage/cards/k/Kezzerdrix.java +++ b/Mage.Sets/src/mage/cards/k/Kezzerdrix.java @@ -1,27 +1,31 @@ - package mage.cards.k; -import java.util.UUID; import mage.MageInt; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.condition.common.CreatureCountCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.effects.common.DamageControllerEffect; import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.filter.common.FilterOpponentsCreaturePermanent; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class Kezzerdrix extends CardImpl { + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterOpponentsCreaturePermanent("your opponents control no creatures"), ComparisonType.EQUAL_TO, 0 + ); + public Kezzerdrix(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.RABBIT); this.subtype.add(SubType.BEAST); @@ -32,10 +36,7 @@ public final class Kezzerdrix extends CardImpl { this.addAbility(FirstStrikeAbility.getInstance()); // At the beginning of your upkeep, if your opponents control no creatures, Kezzerdrix deals 4 damage to you. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new DamageControllerEffect(4)), - new CreatureCountCondition(0, TargetController.OPPONENT), - "At the beginning of your upkeep, if your opponents control no creatures, {this} deals 4 damage to you.")); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DamageControllerEffect(4)).withInterveningIf(condition)); } private Kezzerdrix(final Kezzerdrix card) { diff --git a/Mage.Sets/src/mage/cards/k/KhalniAmbush.java b/Mage.Sets/src/mage/cards/k/KhalniAmbush.java index 83f23c5fa2b..d4ede15e71e 100644 --- a/Mage.Sets/src/mage/cards/k/KhalniAmbush.java +++ b/Mage.Sets/src/mage/cards/k/KhalniAmbush.java @@ -8,11 +8,14 @@ import mage.cards.ModalDoubleFacedCard; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author JayDi85 */ @@ -31,7 +34,7 @@ public final class KhalniAmbush extends ModalDoubleFacedCard { // Target creature you control fights target creature you don't control. this.getLeftHalfCard().getSpellAbility().addEffect(new FightTargetsEffect()); this.getLeftHalfCard().getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getLeftHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getLeftHalfCard().getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); // 2. // Khalni Territory diff --git a/Mage.Sets/src/mage/cards/k/KikiJikiMirrorBreaker.java b/Mage.Sets/src/mage/cards/k/KikiJikiMirrorBreaker.java index 321feeb05eb..bf78dba3fdd 100644 --- a/Mage.Sets/src/mage/cards/k/KikiJikiMirrorBreaker.java +++ b/Mage.Sets/src/mage/cards/k/KikiJikiMirrorBreaker.java @@ -1,37 +1,34 @@ - package mage.cards.k; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenCopyTargetEffect; -import mage.abilities.effects.common.SacrificeTargetEffect; import mage.abilities.keyword.HasteAbility; 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.constants.Zone; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.Predicates; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author jonubuu */ public final class KikiJikiMirrorBreaker extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("nonlegendary creature you control"); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("nonlegendary creature you control"); static { filter.add(Predicates.not(SuperType.LEGENDARY.getPredicate())); @@ -48,11 +45,11 @@ public final class KikiJikiMirrorBreaker extends CardImpl { // Haste this.addAbility(HasteAbility.getInstance()); + // {T}: Create a token that's a copy of target nonlegendary creature you control, except it has haste. Sacrifice it at the beginning of the next end step. Ability ability = new SimpleActivatedAbility(new KikiJikiMirrorBreakerEffect(), new TapSourceCost()); - ability.addTarget(new TargetControlledCreaturePermanent(1, 1, filter, false)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); - } private KikiJikiMirrorBreaker(final KikiJikiMirrorBreaker card) { diff --git a/Mage.Sets/src/mage/cards/k/KiloApogeeMind.java b/Mage.Sets/src/mage/cards/k/KiloApogeeMind.java new file mode 100644 index 00000000000..3e5003b7852 --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KiloApogeeMind.java @@ -0,0 +1,44 @@ +package mage.cards.k; + +import mage.MageInt; +import mage.abilities.common.BecomesTappedSourceTriggeredAbility; +import mage.abilities.effects.common.counter.ProliferateEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class KiloApogeeMind extends CardImpl { + + public KiloApogeeMind(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{U}{R}{W}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.ROBOT); + this.subtype.add(SubType.ARTIFICER); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // Whenever Kilo becomes tapped, proliferate. + this.addAbility(new BecomesTappedSourceTriggeredAbility(new ProliferateEffect())); + } + + private KiloApogeeMind(final KiloApogeeMind card) { + super(card); + } + + @Override + public KiloApogeeMind copy() { + return new KiloApogeeMind(this); + } +} diff --git a/Mage.Sets/src/mage/cards/k/Kindle.java b/Mage.Sets/src/mage/cards/k/Kindle.java index 457244f8c50..08ca80c427d 100644 --- a/Mage.Sets/src/mage/cards/k/Kindle.java +++ b/Mage.Sets/src/mage/cards/k/Kindle.java @@ -33,7 +33,7 @@ public final class Kindle extends CardImpl { // Kindle deals X damage to any target, where X is 2 plus the number of cards named Kindle in all graveyards. Effect effect = new DamageTargetEffect(new KindleCardsInAllGraveyardsCount(filter)); - effect.setText("{this} deals X damage to any target, where X is 2 plus the number of cards named {this} in all graveyards"); + effect.setText("{this} deals X damage to any target, where X is 2 plus the number of cards named Kindle in all graveyards"); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetAnyTarget()); } diff --git a/Mage.Sets/src/mage/cards/k/KindlyStranger.java b/Mage.Sets/src/mage/cards/k/KindlyStranger.java index d0cb859635d..8a07ada2da8 100644 --- a/Mage.Sets/src/mage/cards/k/KindlyStranger.java +++ b/Mage.Sets/src/mage/cards/k/KindlyStranger.java @@ -3,15 +3,15 @@ package mage.cards.k; import mage.MageInt; import mage.abilities.condition.common.DeliriumCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; 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 java.util.UUID; @@ -30,11 +30,9 @@ public final class KindlyStranger extends CardImpl { // Delirium — {2}{B}: Transform Kindly Stranger. Activate this ability only if there are four or more card types among cards in your graveyard. this.addAbility(new TransformAbility()); - this.addAbility(new ConditionalActivatedAbility( - Zone.BATTLEFIELD, new TransformSourceEffect(), new ManaCostsImpl<>("{2}{B}"), - DeliriumCondition.instance, "Delirium — {2}{B}: Transform {this}. " + - "Activate only if there are four or more card types among cards in your graveyard." - ).addHint(CardTypesInGraveyardCount.YOU.getHint())); + this.addAbility(new ActivateIfConditionActivatedAbility( + new TransformSourceEffect(), new ManaCostsImpl<>("{2}{B}"), DeliriumCondition.instance + ).setAbilityWord(AbilityWord.DELIRIUM).addHint(CardTypesInGraveyardCount.YOU.getHint())); } private KindlyStranger(final KindlyStranger card) { diff --git a/Mage.Sets/src/mage/cards/k/KingCrab.java b/Mage.Sets/src/mage/cards/k/KingCrab.java index 31e6bc413ec..4c7eefe63c9 100644 --- a/Mage.Sets/src/mage/cards/k/KingCrab.java +++ b/Mage.Sets/src/mage/cards/k/KingCrab.java @@ -16,6 +16,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class KingCrab extends CardImpl { // {1}{U}, {tap}: Put target green creature on top of its owner's library. Ability ability = new SimpleActivatedAbility(new PutOnLibraryTargetEffect(true), new ManaCostsImpl<>("{1}{U}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KingsAssassin.java b/Mage.Sets/src/mage/cards/k/KingsAssassin.java index cda86b5d362..bade0ce6034 100644 --- a/Mage.Sets/src/mage/cards/k/KingsAssassin.java +++ b/Mage.Sets/src/mage/cards/k/KingsAssassin.java @@ -1,7 +1,5 @@ - package mage.cards.k; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; @@ -12,17 +10,17 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author fireshoes */ public final class KingsAssassin extends CardImpl { - + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { @@ -30,16 +28,18 @@ public final class KingsAssassin extends CardImpl { } public KingsAssassin(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.HUMAN); this.subtype.add(SubType.ASSASSIN); this.power = new MageInt(1); this.toughness = new MageInt(1); // {tap}: Destroy target tapped creature. Activate this ability only during your turn, before attackers are declared. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new DestroyTargetEffect(), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); - ability.addTarget(new TargetCreaturePermanent(filter)); + Ability ability = new ActivateIfConditionActivatedAbility( + new DestroyTargetEffect(), new TapSourceCost(), + MyTurnBeforeAttackersDeclaredCondition.instance + ); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KioraBehemothBeckoner.java b/Mage.Sets/src/mage/cards/k/KioraBehemothBeckoner.java index 5efdb34cf41..a04671459d6 100644 --- a/Mage.Sets/src/mage/cards/k/KioraBehemothBeckoner.java +++ b/Mage.Sets/src/mage/cards/k/KioraBehemothBeckoner.java @@ -2,14 +2,17 @@ package mage.cards.k; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.UntapTargetEffect; 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.constants.SuperType; import mage.filter.FilterPermanent; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; import mage.target.TargetPermanent; @@ -21,7 +24,7 @@ import java.util.UUID; public final class KioraBehemothBeckoner extends CardImpl { private static final FilterPermanent filter - = new FilterCreaturePermanent("a creature with power 4 or greater"); + = new FilterControlledCreaturePermanent("a creature you control with power 4 or greater"); static { filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3)); @@ -35,9 +38,7 @@ public final class KioraBehemothBeckoner extends CardImpl { this.setStartingLoyalty(7); // Whenever a creature with power 4 or greater you control enters, draw a card. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility( - Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), filter, false - )); + this.addAbility(new EntersBattlefieldAllTriggeredAbility(new DrawCardSourceControllerEffect(1), filter)); // -1: Untap target permanent. Ability ability = new LoyaltyAbility(new UntapTargetEffect(), -1); diff --git a/Mage.Sets/src/mage/cards/k/KioraTheRisingTide.java b/Mage.Sets/src/mage/cards/k/KioraTheRisingTide.java index 8d47f26d2b2..1c7450de867 100644 --- a/Mage.Sets/src/mage/cards/k/KioraTheRisingTide.java +++ b/Mage.Sets/src/mage/cards/k/KioraTheRisingTide.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.ThresholdCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.DrawDiscardControllerEffect; import mage.cards.CardImpl; @@ -18,14 +17,13 @@ import mage.game.permanent.token.ScionOfTheDeepToken; import java.util.UUID; /** - * * @author ciaccona007 */ public final class KioraTheRisingTide extends CardImpl { public KioraTheRisingTide(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); - + this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.MERFOLK); this.subtype.add(SubType.NOBLE); @@ -38,13 +36,8 @@ public final class KioraTheRisingTide extends CardImpl { )); // Threshold -- Whenever Kiora attacks, if there are seven or more cards in your graveyard, you may create Scion of the Deep, a legendary 8/8 blue Octopus creature token. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new CreateTokenEffect(new ScionOfTheDeepToken()), true), - ThresholdCondition.instance, "Whenever {this} attacks, if there are seven " - + "or more cards in your graveyard, you may create " - + "Scion of the Deep, a legendary 8/8 blue Octopus creature token." - ).setAbilityWord(AbilityWord.THRESHOLD)); - + this.addAbility(new AttacksTriggeredAbility(new CreateTokenEffect(new ScionOfTheDeepToken()), true) + .withInterveningIf(ThresholdCondition.instance).setAbilityWord(AbilityWord.THRESHOLD)); } private KioraTheRisingTide(final KioraTheRisingTide card) { diff --git a/Mage.Sets/src/mage/cards/k/KitesailCleric.java b/Mage.Sets/src/mage/cards/k/KitesailCleric.java index 3a98a3682fb..558468dbcd0 100644 --- a/Mage.Sets/src/mage/cards/k/KitesailCleric.java +++ b/Mage.Sets/src/mage/cards/k/KitesailCleric.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.KickerAbility; @@ -36,11 +35,7 @@ public final class KitesailCleric extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When Kitesail Cleric enters the battelfield, if it was kicked, tap up to two target creatures. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new TapTargetEffect()), - KickedCondition.ONCE, "When {this} enters, " + - "if it was kicked, tap up to two target creatures." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new TapTargetEffect()).withInterveningIf(KickedCondition.ONCE); ability.addTarget(new TargetCreaturePermanent(0, 2)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KithkinShielddare.java b/Mage.Sets/src/mage/cards/k/KithkinShielddare.java index 2632b782776..fdae7a9efa1 100644 --- a/Mage.Sets/src/mage/cards/k/KithkinShielddare.java +++ b/Mage.Sets/src/mage/cards/k/KithkinShielddare.java @@ -15,6 +15,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterBlockingCreature; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,7 +39,7 @@ public final class KithkinShielddare extends CardImpl { new BoostTargetEffect(2, 2, Duration.EndOfTurn), new ManaCostsImpl<>("{W}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KitsuneBonesetter.java b/Mage.Sets/src/mage/cards/k/KitsuneBonesetter.java index dbf33066536..75c7e827a96 100644 --- a/Mage.Sets/src/mage/cards/k/KitsuneBonesetter.java +++ b/Mage.Sets/src/mage/cards/k/KitsuneBonesetter.java @@ -1,40 +1,36 @@ - package mage.cards.k; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.condition.common.MoreCardsInHandThanOpponentsCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.PreventDamageToTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class KitsuneBonesetter extends CardImpl { public KitsuneBonesetter(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.FOX); this.subtype.add(SubType.CLERIC); this.power = new MageInt(0); this.toughness = new MageInt(1); - + // {tap}: Prevent the next 3 damage that would be dealt to target creature this turn. Activate this ability only if you have more cards in hand than each opponent. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, - new PreventDamageToTargetEffect(Duration.EndOfTurn, 3), - new TapSourceCost(), + Ability ability = new ActivateIfConditionActivatedAbility( + new PreventDamageToTargetEffect(Duration.EndOfTurn, 3), new TapSourceCost(), MoreCardsInHandThanOpponentsCondition.instance ); ability.addTarget(new TargetCreaturePermanent()); diff --git a/Mage.Sets/src/mage/cards/k/KitsuneHealer.java b/Mage.Sets/src/mage/cards/k/KitsuneHealer.java index bcf1ba79a41..e0f9933349d 100644 --- a/Mage.Sets/src/mage/cards/k/KitsuneHealer.java +++ b/Mage.Sets/src/mage/cards/k/KitsuneHealer.java @@ -16,6 +16,7 @@ import mage.constants.Duration; import mage.constants.SuperType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetAnyTarget; import mage.target.common.TargetCreaturePermanent; @@ -44,7 +45,7 @@ public final class KitsuneHealer extends CardImpl { this.addAbility(firstAbility); // {T}: Prevent all damage that would be dealt to target legendary creature this turn. Ability secondAbility = new SimpleActivatedAbility(new PreventDamageToTargetEffect(Duration.EndOfTurn, Integer.MAX_VALUE), new TapSourceCost()); - secondAbility.addTarget(new TargetCreaturePermanent(filter)); + secondAbility.addTarget(new TargetPermanent(filter)); this.addAbility(secondAbility); } diff --git a/Mage.Sets/src/mage/cards/k/KitsuneMystic.java b/Mage.Sets/src/mage/cards/k/KitsuneMystic.java index dc71085527f..f84edc36e94 100644 --- a/Mage.Sets/src/mage/cards/k/KitsuneMystic.java +++ b/Mage.Sets/src/mage/cards/k/KitsuneMystic.java @@ -1,36 +1,42 @@ - package mage.cards.k; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.EnchantedSourceCondition; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.FlipSourceEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterEnchantmentPermanent; +import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.AttachmentAttachedToCardTypePredicate; +import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.game.Game; -import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.permanent.token.TokenImpl; +import mage.players.Player; +import mage.target.TargetImpl; import mage.target.TargetPermanent; -import mage.target.common.TargetCreaturePermanent; + +import java.util.Optional; +import java.util.UUID; /** - * * @author LevelX2 */ public final class KitsuneMystic extends CardImpl { + private static final Condition condition = new EnchantedSourceCondition(2); + public KitsuneMystic(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.FOX); this.subtype.add(SubType.WIZARD); @@ -40,9 +46,9 @@ public final class KitsuneMystic extends CardImpl { this.flipCardName = "Autumn-Tail, Kitsune Sage"; // At the beginning of the end step, if Kitsune Mystic is enchanted by two or more Auras, flip it. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new FlipSourceEffect(new AutumnTailKitsuneSage())), - new EnchantedSourceCondition(2), "At the beginning of the end step, if {this} is enchanted by two or more Auras, flip it.")); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.NEXT, new FlipSourceEffect(new AutumnTailKitsuneSage()).setText("flip it"), false, condition + )); } private KitsuneMystic(final KitsuneMystic card) { @@ -77,9 +83,9 @@ class AutumnTailKitsuneSage extends TokenImpl { // {1}: Attach target Aura attached to a creature to another creature. Ability ability = new SimpleActivatedAbility(new AutumnTailEffect(), new GenericManaCost(1)); ability.addTarget(new TargetPermanent(filter)); - ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } + private AutumnTailKitsuneSage(final AutumnTailKitsuneSage token) { super(token); } @@ -93,7 +99,7 @@ class AutumnTailEffect extends OneShotEffect { AutumnTailEffect() { super(Outcome.BoostCreature); - this.staticText = "Attach target Aura attached to a creature to another creature"; + this.staticText = "attach target Aura attached to a creature to another creature"; } private AutumnTailEffect(final AutumnTailEffect effect) { @@ -107,17 +113,24 @@ class AutumnTailEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent aura = game.getPermanent(source.getFirstTarget()); - Permanent creature = game.getPermanent(source.getTargets().get(1).getFirstTarget()); - if (aura != null && creature != null) { - Permanent oldCreature = game.getPermanent(aura.getAttachedTo()); - if (oldCreature == null || oldCreature.equals(creature)) { - return false; - } - if (oldCreature.removeAttachment(aura.getId(), source, game)) { - return creature.addAttachment(aura.getId(), source, game); - } + Player player = game.getPlayer(source.getControllerId()); + Permanent aura = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (player == null || aura == null) { + return false; } - return false; + FilterPermanent filter = new FilterCreaturePermanent(); + filter.add(Predicates.not(new PermanentIdPredicate(aura.getAttachedTo()))); + if (!game.getBattlefield().contains(filter, source.getControllerId(), source, game, 1)) { + return false; + } + TargetPermanent target = new TargetPermanent(filter); + target.withNotTarget(true); + player.choose(outcome, target, source, game); + return Optional + .ofNullable(target) + .map(TargetImpl::getFirstTarget) + .map(game::getPermanent) + .filter(permanent -> permanent.addAttachment(aura.getId(), source, game)) + .isPresent(); } } diff --git a/Mage.Sets/src/mage/cards/k/KjeldoranEliteGuard.java b/Mage.Sets/src/mage/cards/k/KjeldoranEliteGuard.java index 4480660ced7..393dacb4eda 100644 --- a/Mage.Sets/src/mage/cards/k/KjeldoranEliteGuard.java +++ b/Mage.Sets/src/mage/cards/k/KjeldoranEliteGuard.java @@ -3,9 +3,10 @@ package mage.cards.k; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.IsPhaseCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; @@ -24,6 +25,8 @@ import java.util.UUID; */ public final class KjeldoranEliteGuard extends CardImpl { + private static final Condition condition = new IsPhaseCondition(TurnPhase.COMBAT, false); + public KjeldoranEliteGuard(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); this.subtype.add(SubType.HUMAN); @@ -34,17 +37,16 @@ public final class KjeldoranEliteGuard extends CardImpl { // Target creature gets +2/+2 until end of turn. // When that creature leaves the battlefield this turn, sacrifice Kjeldoran Elite Guard. // Activate only during combat. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, - new KjeldoranEliteGuardEffect(), - new TapSourceCost(), - new IsPhaseCondition(TurnPhase.COMBAT, false)); + Ability ability = new ActivateIfConditionActivatedAbility( + new KjeldoranEliteGuardEffect(), new TapSourceCost(), condition + ); ability.addTarget(new TargetCreaturePermanent()); - this.addAbility(ability); } - private KjeldoranEliteGuard(final KjeldoranEliteGuard card) { super(card); } + private KjeldoranEliteGuard(final KjeldoranEliteGuard card) { + super(card); + } @Override public KjeldoranEliteGuard copy() { @@ -57,7 +59,7 @@ class KjeldoranEliteGuardEffect extends OneShotEffect { KjeldoranEliteGuardEffect() { super(Outcome.Neutral); staticText = "Target creature gets +2/+2 until end of turn. " - + "When that creature leaves the battlefield this turn, sacrifice Kjeldoran Elite Guard."; + + "When that creature leaves the battlefield this turn, sacrifice {this}."; } @Override @@ -79,10 +81,14 @@ class KjeldoranEliteGuardEffect extends OneShotEffect { return true; } - private KjeldoranEliteGuardEffect(KjeldoranEliteGuardEffect effect) { super(effect); } + private KjeldoranEliteGuardEffect(KjeldoranEliteGuardEffect effect) { + super(effect); + } @Override - public KjeldoranEliteGuardEffect copy() { return new KjeldoranEliteGuardEffect(this); } + public KjeldoranEliteGuardEffect copy() { + return new KjeldoranEliteGuardEffect(this); + } } class KjeldoranEliteGuardDelayedTriggeredAbility extends DelayedTriggeredAbility { @@ -105,7 +111,9 @@ class KjeldoranEliteGuardDelayedTriggeredAbility extends DelayedTriggeredAbility } @Override - public boolean checkTrigger(GameEvent event, Game game) { return event.getTargetId().equals(creatureId); } + public boolean checkTrigger(GameEvent event, Game game) { + return event.getTargetId().equals(creatureId); + } @Override public KjeldoranEliteGuardDelayedTriggeredAbility copy() { @@ -113,5 +121,7 @@ class KjeldoranEliteGuardDelayedTriggeredAbility extends DelayedTriggeredAbility } @Override - public String getRule() { return "that creature left the battlefield this turn"; } + public String getRule() { + return "that creature left the battlefield this turn"; + } } diff --git a/Mage.Sets/src/mage/cards/k/KjeldoranGuard.java b/Mage.Sets/src/mage/cards/k/KjeldoranGuard.java index ece65248115..0818d266dcf 100644 --- a/Mage.Sets/src/mage/cards/k/KjeldoranGuard.java +++ b/Mage.Sets/src/mage/cards/k/KjeldoranGuard.java @@ -5,11 +5,12 @@ import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; import mage.abilities.condition.CompoundCondition; +import mage.abilities.condition.Condition; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.DefendingPlayerControlsNoSourceCondition; import mage.abilities.condition.common.IsPhaseCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.SacrificeTargetEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; @@ -36,6 +37,12 @@ public final class KjeldoranGuard extends CardImpl { filter.add(SuperType.SNOW.getPredicate()); } + private static final Condition condition = new CompoundCondition( + "during combat and only if defending player controls no snow lands", + new IsPhaseCondition(TurnPhase.COMBAT, false), // Only during combat + new InvertCondition(new DefendingPlayerControlsNoSourceCondition(filter)) // Only if defending player controls no snow land + ); + public KjeldoranGuard(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); @@ -45,19 +52,8 @@ public final class KjeldoranGuard extends CardImpl { this.toughness = new MageInt(1); // {T}: Target creature gets +1/+1 until end of turn. When that creature leaves the battlefield this turn, sacrifice Kjeldoran Guard. Activate only during combat and only if defending player controls no snow lands. - CompoundCondition condition = new CompoundCondition( - new IsPhaseCondition(TurnPhase.COMBAT, false), // Only during combat - new InvertCondition(new DefendingPlayerControlsNoSourceCondition(filter)) // Only if defending player controls no snow land - ); - - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, - new KjeldoranGuardEffect(), - new TapSourceCost(), - condition, - "{T}: Target creature gets +1/+1 until end of turn. " - + "When that creature leaves the battlefield this turn, sacrifice {this}. " - + "Activate only during combat and only if defending player controls no snow lands." + Ability ability = new ActivateIfConditionActivatedAbility( + new KjeldoranGuardEffect(), new TapSourceCost(), condition ); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); @@ -77,7 +73,7 @@ class KjeldoranGuardEffect extends OneShotEffect { KjeldoranGuardEffect() { super(Outcome.BoostCreature); - staticText = "Target creature gets +1/+1 until end of turn. " + staticText = "target creature gets +1/+1 until end of turn. " + "When that creature leaves the battlefield this turn, sacrifice {this}."; } @@ -109,7 +105,7 @@ class KjeldoranGuardEffect extends OneShotEffect { // Locking in the Kjeldoran Guard (and its zcc), to be sacrificed later. Permanent guard = source.getSourcePermanentIfItStillExists(game); - if(guard != null) { + if (guard != null) { delayed.getEffects().setTargetPointer(new FixedTarget(guard, game)); } game.addDelayedTriggeredAbility(delayed, source); @@ -152,4 +148,4 @@ class KjeldoranGuardDelayedTriggeredAbility extends DelayedTriggeredAbility { public String getRule() { return "When that creature leaves the battlefield, Sacrifice {this}"; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/k/KjeldoranHomeGuard.java b/Mage.Sets/src/mage/cards/k/KjeldoranHomeGuard.java index 86a203e97b4..94204017100 100644 --- a/Mage.Sets/src/mage/cards/k/KjeldoranHomeGuard.java +++ b/Mage.Sets/src/mage/cards/k/KjeldoranHomeGuard.java @@ -1,24 +1,22 @@ - package mage.cards.k; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EndOfCombatTriggeredAbility; import mage.abilities.condition.common.AttackedOrBlockedThisCombatSourceCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SubType; import mage.counters.CounterType; import mage.game.permanent.token.DeserterToken; import mage.watchers.common.AttackedOrBlockedThisCombatWatcher; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class KjeldoranHomeGuard extends CardImpl { @@ -32,11 +30,11 @@ public final class KjeldoranHomeGuard extends CardImpl { this.toughness = new MageInt(6); // At end of combat, if Kjeldoran Home Guard attacked or blocked this combat, put a -0/-1 counter on Kjeldoran Home Guard and put a 0/1 white Deserter creature token onto the battlefield. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EndOfCombatTriggeredAbility(new AddCountersSourceEffect(CounterType.M0M1.createInstance()), false), - AttackedOrBlockedThisCombatSourceCondition.instance, - "At end of combat, if {this} attacked or blocked this combat, put a -0/-1 counter on {this} and create a 0/1 white Deserter creature token."); - ability.addEffect(new CreateTokenEffect(new DeserterToken()).setText("and create a 0/1 white Deserter creature token.")); + Ability ability = new EndOfCombatTriggeredAbility( + new AddCountersSourceEffect(CounterType.M0M1.createInstance()), false + ).withInterveningIf(AttackedOrBlockedThisCombatSourceCondition.instance); + ability.addEffect(new CreateTokenEffect(new DeserterToken()) + .setText("and create a 0/1 white Deserter creature token.")); this.addAbility(ability, new AttackedOrBlockedThisCombatWatcher()); } diff --git a/Mage.Sets/src/mage/cards/k/KjeldoranPride.java b/Mage.Sets/src/mage/cards/k/KjeldoranPride.java index e952292516b..6773a890dbb 100644 --- a/Mage.Sets/src/mage/cards/k/KjeldoranPride.java +++ b/Mage.Sets/src/mage/cards/k/KjeldoranPride.java @@ -48,7 +48,7 @@ public final class KjeldoranPride extends CardImpl { // 2U: Attach Kjeldoran Pride to target creature other than enchanted creature. Ability ability = new SimpleActivatedAbility(new AttachEffect(Outcome.Benefit, "attach {this} to target " + filter.getMessage()), new ManaCostsImpl<>("{2}{U}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KjeldoranWarCry.java b/Mage.Sets/src/mage/cards/k/KjeldoranWarCry.java index 3185d1e0355..10711261803 100644 --- a/Mage.Sets/src/mage/cards/k/KjeldoranWarCry.java +++ b/Mage.Sets/src/mage/cards/k/KjeldoranWarCry.java @@ -1,7 +1,6 @@ package mage.cards.k; -import java.util.UUID; import mage.abilities.dynamicvalue.IntPlusDynamicValue; import mage.abilities.dynamicvalue.common.CardsInAllGraveyardsCount; import mage.abilities.effects.Effect; @@ -14,8 +13,9 @@ import mage.filter.FilterCard; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.NamePredicate; +import java.util.UUID; + /** - * * @author L_J */ public final class KjeldoranWarCry extends CardImpl { @@ -27,12 +27,12 @@ public final class KjeldoranWarCry extends CardImpl { } public KjeldoranWarCry(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}"); // Creatures you control get +X/+X until end of turn, where X is 1 plus the number of cards named Kjeldoran War Cry in all graveyards. IntPlusDynamicValue value = new IntPlusDynamicValue(1, new CardsInAllGraveyardsCount(filter)); Effect effect = new BoostControlledEffect(value, value, Duration.EndOfTurn, new FilterCreaturePermanent("creatures"), false); - effect.setText("Creatures you control get +X/+X until end of turn, where X is 1 plus the number of cards named {this} in all graveyards"); + effect.setText("Creatures you control get +X/+X until end of turn, where X is 1 plus the number of cards named Kjeldoran War Cry in all graveyards"); this.getSpellAbility().addEffect(effect); } diff --git a/Mage.Sets/src/mage/cards/k/KnightOfTheEbonLegion.java b/Mage.Sets/src/mage/cards/k/KnightOfTheEbonLegion.java index 73aed41bc7c..d21814bed29 100644 --- a/Mage.Sets/src/mage/cards/k/KnightOfTheEbonLegion.java +++ b/Mage.Sets/src/mage/cards/k/KnightOfTheEbonLegion.java @@ -2,16 +2,16 @@ package mage.cards.k; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.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.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.Hint; import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -46,12 +46,8 @@ public final class KnightOfTheEbonLegion extends CardImpl { this.addAbility(ability); // At the beginning of your end step, if a player lost 4 or more life this turn, put a +1/+1 counter on Knight of the Ebon Legion. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - new AddCountersSourceEffect(CounterType.P1P1.createInstance()) - ), KnightOfTheEbonLegionCondition.instance, "At the beginning of your end step, " + - "if a player lost 4 or more life this turn, put a +1/+1 counter on {this}." - ).addHint(new ConditionHint(KnightOfTheEbonLegionCondition.instance, "A player lost 4 or more life this turn"))); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance())) + .withInterveningIf(KnightOfTheEbonLegionCondition.instance).addHint(KnightOfTheEbonLegionCondition.getHint())); } private KnightOfTheEbonLegion(final KnightOfTheEbonLegion card) { @@ -66,6 +62,11 @@ public final class KnightOfTheEbonLegion extends CardImpl { enum KnightOfTheEbonLegionCondition implements Condition { instance; + private static final Hint hint = new ConditionHint(instance); + + public static Hint getHint() { + return hint; + } @Override public boolean apply(Game game, Ability source) { @@ -79,4 +80,9 @@ enum KnightOfTheEbonLegionCondition implements Condition { .stream() .anyMatch(uuid -> watcher.getLifeLost(uuid) > 3); } + + @Override + public String toString() { + return "a player lost 4 or more life this turn"; + } } diff --git a/Mage.Sets/src/mage/cards/k/KnightOfTheWhiteOrchid.java b/Mage.Sets/src/mage/cards/k/KnightOfTheWhiteOrchid.java index 699ae51f03a..aeac56a3b82 100644 --- a/Mage.Sets/src/mage/cards/k/KnightOfTheWhiteOrchid.java +++ b/Mage.Sets/src/mage/cards/k/KnightOfTheWhiteOrchid.java @@ -1,30 +1,32 @@ - - package mage.cards.k; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.OpponentControlsMoreCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.filter.FilterCard; import mage.filter.StaticFilters; import mage.filter.common.FilterBySubtypeCard; import mage.target.common.TargetCardInLibrary; +import java.util.UUID; + /** - * * @author BetaSteward_at_googlemail.com */ public final class KnightOfTheWhiteOrchid extends CardImpl { + private static final FilterCard filter = new FilterBySubtypeCard(SubType.PLAINS); + private static final Condition condition = new OpponentControlsMoreCondition(StaticFilters.FILTER_LANDS); + public KnightOfTheWhiteOrchid(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{W}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.KNIGHT); @@ -33,13 +35,11 @@ public final class KnightOfTheWhiteOrchid extends CardImpl { // First strike this.addAbility(FirstStrikeAbility.getInstance()); - + // When Knight of the White Orchid enters the battlefield, if an opponent controls more lands than you, you may search your library for a Plains card, put it onto the battlefield, then shuffle your library. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(0, 1, new FilterBySubtypeCard(SubType.PLAINS)), false), true), - new OpponentControlsMoreCondition(StaticFilters.FILTER_LANDS), - "When {this} enters, if an opponent controls more lands than you, you may search your library for a Plains card, put it onto the battlefield, then shuffle.")); - + this.addAbility(new EntersBattlefieldTriggeredAbility( + new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter)), true + ).withInterveningIf(condition)); } private KnightOfTheWhiteOrchid(final KnightOfTheWhiteOrchid card) { diff --git a/Mage.Sets/src/mage/cards/k/KnightsOfRen.java b/Mage.Sets/src/mage/cards/k/KnightsOfRen.java index 7a97cc53d6f..302f74fa37b 100644 --- a/Mage.Sets/src/mage/cards/k/KnightsOfRen.java +++ b/Mage.Sets/src/mage/cards/k/KnightsOfRen.java @@ -1,15 +1,13 @@ package mage.cards.k; import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.AttacksTriggeredAbility; -import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility; import mage.abilities.condition.common.HateCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SacrificeAllEffect; import mage.abilities.keyword.MenaceAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; @@ -35,18 +33,9 @@ public class KnightsOfRen extends CardImpl { //Hate — Whenever Knights of Ren enters the battlefield or attacks, if an opponent lost life from a source other //than combat damage this turn, you may have each player sacrifice a creature. - Ability abilityEnterBattlefield = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility( - new SacrificeAllEffect(StaticFilters.FILTER_PERMANENT_CREATURE), true), - HateCondition.instance, - "Hate — When {this} enters, if an opponent lost life from a source other than combat damage this turn, you may have each player sacrifice a creature"); - Ability abilityAttacks = new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility( - new SacrificeAllEffect(StaticFilters.FILTER_PERMANENT_CREATURE), true), - HateCondition.instance, - "Hate — When {this} attacks, if an opponent lost life from a source other than combat damage this turn, you may have each player sacrifice a creature"); - this.addAbility(abilityEnterBattlefield, new LifeLossOtherFromCombatWatcher()); - this.addAbility(abilityAttacks, new LifeLossOtherFromCombatWatcher()); + this.addAbility(new EntersBattlefieldOrAttacksSourceTriggeredAbility( + new SacrificeAllEffect(StaticFilters.FILTER_PERMANENT_CREATURE).setText("have each player sacrifice a creature") + ).withInterveningIf(HateCondition.instance).setAbilityWord(AbilityWord.HATE), new LifeLossOtherFromCombatWatcher()); } private KnightsOfRen(final KnightsOfRen card) { diff --git a/Mage.Sets/src/mage/cards/k/KnucklesTheEchidna.java b/Mage.Sets/src/mage/cards/k/KnucklesTheEchidna.java new file mode 100644 index 00000000000..47a0d6e6354 --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KnucklesTheEchidna.java @@ -0,0 +1,72 @@ +package mage.cards.k; + +import mage.MageInt; +import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.WinGameSourceControllerEffect; +import mage.abilities.hint.common.ArtifactYouControlHint; +import mage.abilities.keyword.DoubleStrikeAbility; +import mage.abilities.keyword.HasteAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledArtifactPermanent; +import mage.game.permanent.token.TreasureToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class KnucklesTheEchidna extends CardImpl { + + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledArtifactPermanent("you control thirty or more artifacts"), + ComparisonType.MORE_THAN, 29 + ); + + public KnucklesTheEchidna(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.ECHIDNA); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // Double strike + this.addAbility(DoubleStrikeAbility.getInstance()); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // Whenever one or more creatures you control deal combat damage to a player, create a Treasure token. + this.addAbility(new OneOrMoreCombatDamagePlayerTriggeredAbility( + new CreateTokenEffect(new TreasureToken()), StaticFilters.FILTER_CONTROLLED_CREATURES + )); + + // Treasure Hunter -- At the beginning of your upkeep, if you control thirty or more artifacts, you win the game. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect()) + .withInterveningIf(condition).addHint(ArtifactYouControlHint.instance).withFlavorWord("Treasure Hunter")); + } + + private KnucklesTheEchidna(final KnucklesTheEchidna card) { + super(card); + } + + @Override + public KnucklesTheEchidna copy() { + return new KnucklesTheEchidna(this); + } +} diff --git a/Mage.Sets/src/mage/cards/k/KodamaOfTheEastTree.java b/Mage.Sets/src/mage/cards/k/KodamaOfTheEastTree.java index a012f1f02d9..36ef81618e5 100644 --- a/Mage.Sets/src/mage/cards/k/KodamaOfTheEastTree.java +++ b/Mage.Sets/src/mage/cards/k/KodamaOfTheEastTree.java @@ -5,7 +5,6 @@ import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.PartnerAbility; @@ -18,8 +17,8 @@ import mage.filter.FilterCard; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterPermanentCard; -import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; @@ -35,7 +34,7 @@ import java.util.*; */ public final class KodamaOfTheEastTree extends CardImpl { - private static final FilterPermanent filter = new FilterControlledPermanent(); + private static final FilterPermanent filter = new FilterControlledPermanent("another permanent you control"); static { filter.add(AnotherPredicate.instance); @@ -53,12 +52,8 @@ public final class KodamaOfTheEastTree extends CardImpl { this.addAbility(ReachAbility.getInstance()); // Whenever another permanent you control enters, if it wasn't put onto the battlefield with this ability, you may put a permanent card with equal or lesser converted mana cost from your hand onto the battlefield. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldAllTriggeredAbility(new KodamaOfTheEastTreeEffect(), filter), - KodamaOfTheEastTreeCondition.instance, "Whenever another permanent enters the battlefield " + - "under your control, if it wasn't put onto the battlefield with this ability, you may put " + - "a permanent card with equal or lesser mana value from your hand onto the battlefield." - ), new KodamaOfTheEastTreeWatcher()); + this.addAbility(new EntersBattlefieldAllTriggeredAbility(new KodamaOfTheEastTreeEffect(), filter) + .withInterveningIf(KodamaOfTheEastTreeCondition.instance), new KodamaOfTheEastTreeWatcher()); // Partner this.addAbility(PartnerAbility.getInstance()); @@ -90,12 +85,18 @@ enum KodamaOfTheEastTreeCondition implements Condition { KodamaOfTheEastTreeWatcher watcher = game.getState().getWatcher(KodamaOfTheEastTreeWatcher.class); return watcher != null && !watcher.checkPermanent(permanent, source, game); } + + @Override + public String toString() { + return "it wasn't put onto the battlefield with this ability"; + } } class KodamaOfTheEastTreeEffect extends OneShotEffect { KodamaOfTheEastTreeEffect() { super(Outcome.Benefit); + staticText = "you may put a permanent card with equal or lesser mana value from your hand onto the battlefield"; } private KodamaOfTheEastTreeEffect(final KodamaOfTheEastTreeEffect effect) { diff --git a/Mage.Sets/src/mage/cards/k/KondasBanner.java b/Mage.Sets/src/mage/cards/k/KondasBanner.java index 137f405895d..e706ee087a0 100644 --- a/Mage.Sets/src/mage/cards/k/KondasBanner.java +++ b/Mage.Sets/src/mage/cards/k/KondasBanner.java @@ -1,29 +1,31 @@ package mage.cards.k; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.AttachableToRestrictedAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.continuous.BoostAllEffect; import mage.abilities.keyword.EquipAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterPermanent; import mage.filter.StaticFilters; -import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.target.Target; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author LevelX */ public final class KondasBanner extends CardImpl { - private static final FilterControlledCreaturePermanent legendaryFilter = new FilterControlledCreaturePermanent("legendary creature"); + private static final FilterPermanent legendaryFilter = new FilterCreaturePermanent("legendary creature"); static { legendaryFilter.add(SuperType.LEGENDARY.getPredicate()); @@ -34,9 +36,8 @@ public final class KondasBanner extends CardImpl { this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.EQUIPMENT); - Target target = new TargetControlledCreaturePermanent(1, 1, legendaryFilter, false); // Konda's Banner can be attached only to a legendary creature. - this.addAbility(new AttachableToRestrictedAbility(target)); + this.addAbility(new AttachableToRestrictedAbility(new TargetPermanent(legendaryFilter))); // Creatures that share a color with equipped creature get +1/+1. this.addAbility(new SimpleStaticAbility(new KondasBannerColorBoostEffect())); @@ -45,8 +46,7 @@ public final class KondasBanner extends CardImpl { this.addAbility(new SimpleStaticAbility(new KondasBannerTypeBoostEffect())); // Equip {2} - this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2), target, false)); - + this.addAbility(new EquipAbility(2, false)); } private KondasBanner(final KondasBanner card) { diff --git a/Mage.Sets/src/mage/cards/k/KongmingsContraptions.java b/Mage.Sets/src/mage/cards/k/KongmingsContraptions.java index 7ebae6d9a1f..50be5503110 100644 --- a/Mage.Sets/src/mage/cards/k/KongmingsContraptions.java +++ b/Mage.Sets/src/mage/cards/k/KongmingsContraptions.java @@ -1,29 +1,35 @@ package mage.cards.k; -import java.util.UUID; import mage.MageInt; 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.IsStepCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; 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.PhaseStep; -import mage.constants.Zone; +import mage.constants.SubType; import mage.target.common.TargetAttackingCreature; import mage.watchers.common.PlayerAttackedStepWatcher; +import java.util.UUID; + /** - * * @author L_J */ public final class KongmingsContraptions extends CardImpl { + private static final Condition condition = new CompoundCondition( + "during the declare attackers step and only if you've been attacked this step", + new IsStepCondition(PhaseStep.DECLARE_ATTACKERS, false), + AttackedThisStepCondition.instance + ); + public KongmingsContraptions(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); this.subtype.add(SubType.HUMAN); @@ -32,10 +38,7 @@ public final class KongmingsContraptions extends CardImpl { this.toughness = new MageInt(4); // {T}: Kongming's Contraptions deals 2 damage to target attacking creature. Activate this ability only during the declare attackers step and only if you've been attacked this step. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(2), new TapSourceCost(), - new CompoundCondition("during the declare attackers step and only if you've been attacked this step", - new IsStepCondition(PhaseStep.DECLARE_ATTACKERS, false), AttackedThisStepCondition.instance) - ); + Ability ability = new ActivateIfConditionActivatedAbility(new DamageTargetEffect(2), new TapSourceCost(), condition); ability.addTarget(new TargetAttackingCreature()); this.addAbility(ability, new PlayerAttackedStepWatcher()); } diff --git a/Mage.Sets/src/mage/cards/k/Kookus.java b/Mage.Sets/src/mage/cards/k/Kookus.java index 58f55d78a1a..ddb80115dea 100644 --- a/Mage.Sets/src/mage/cards/k/Kookus.java +++ b/Mage.Sets/src/mage/cards/k/Kookus.java @@ -1,41 +1,40 @@ - package mage.cards.k; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.costs.mana.ColoredManaCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.DamageControllerEffect; import mage.abilities.effects.common.combat.AttacksIfAbleSourceEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; -import mage.constants.SubType; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.ColoredManaSymbol; +import mage.constants.ComparisonType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.NamePredicate; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class Kookus extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("you don't control a creature named Keeper of Kookus"); static { filter.add(new NamePredicate("Keeper of Kookus")); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.EQUAL_TO, 0); + public Kookus(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}"); @@ -47,18 +46,16 @@ public final class Kookus extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // At the beginning of your upkeep, if you don't control a creature named Keeper of Kookus, Kookus deals 3 damage to you and attacks this turn if able. - TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new DamageControllerEffect(3)); - ability.addEffect(new AttacksIfAbleSourceEffect(Duration.EndOfTurn, false)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - ability, - new InvertCondition(new PermanentsOnTheBattlefieldCondition(filter)), - "At the beginning of your upkeep, " - + "if you don't control a creature named Keeper of Kookus, " - + "{this} deals 3 damage to you and attacks this turn if able" - )); + Ability ability = new BeginningOfUpkeepTriggeredAbility(new DamageControllerEffect(3)).withInterveningIf(condition); + ability.addEffect(new AttacksIfAbleSourceEffect( + Duration.EndOfTurn, false + ).setText("and attacks this turn if able")); + this.addAbility(ability); // {R}: Kookus gets +1/+0 until end of turn. - this.addAbility(new SimpleActivatedAbility(new BoostSourceEffect(1, 0, Duration.EndOfTurn), new ColoredManaCost(ColoredManaSymbol.R))); + this.addAbility(new SimpleActivatedAbility( + new BoostSourceEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl<>("{R}") + )); } private Kookus(final Kookus card) { diff --git a/Mage.Sets/src/mage/cards/k/KorAeronaut.java b/Mage.Sets/src/mage/cards/k/KorAeronaut.java index 2743ee1b975..8f893a15e17 100644 --- a/Mage.Sets/src/mage/cards/k/KorAeronaut.java +++ b/Mage.Sets/src/mage/cards/k/KorAeronaut.java @@ -1,11 +1,9 @@ - package mage.cards.k; -import java.util.UUID; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.KickerAbility; @@ -13,17 +11,17 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Duration; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author North */ public final class KorAeronaut extends CardImpl { public KorAeronaut(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{W}"); this.subtype.add(SubType.KOR); this.subtype.add(SubType.SOLDIER); @@ -37,9 +35,11 @@ public final class KorAeronaut extends CardImpl { this.addAbility(FlyingAbility.getInstance()); //When Kor Aeronaut enters the battlefield, if it was kicked, target creature gains flying until end of turn. - EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), false); + Ability ability = new EntersBattlefieldTriggeredAbility( + new GainAbilityTargetEffect(FlyingAbility.getInstance()) + ).withInterveningIf(KickedCondition.ONCE); ability.addTarget(new TargetCreaturePermanent()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.ONCE, "When {this} enters, if it was kicked, target creature gains flying until end of turn.")); + this.addAbility(ability); } private KorAeronaut(final KorAeronaut card) { diff --git a/Mage.Sets/src/mage/cards/k/KorChant.java b/Mage.Sets/src/mage/cards/k/KorChant.java index d1128957a73..eae15e2e949 100644 --- a/Mage.Sets/src/mage/cards/k/KorChant.java +++ b/Mage.Sets/src/mage/cards/k/KorChant.java @@ -1,7 +1,5 @@ - package mage.cards.k; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.RedirectionEffect; import mage.cards.CardImpl; @@ -9,16 +7,16 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.other.AnotherTargetPredicate; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; +import mage.target.TargetPermanent; import mage.target.TargetSource; import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; /** - * * @author emerald000 */ public final class KorChant extends CardImpl { @@ -28,15 +26,8 @@ public final class KorChant extends CardImpl { // All damage that would be dealt this turn to target creature you control by a source of your choice is dealt to another target creature instead. this.getSpellAbility().addEffect(new KorChantEffect()); - TargetControlledCreaturePermanent target = new TargetControlledCreaturePermanent(); - target.setTargetTag(1); - this.getSpellAbility().addTarget(target); - - FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); - filter.add(new AnotherTargetPredicate(2)); - TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter); - target2.setTargetTag(2); - this.getSpellAbility().addTarget(target2); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent().setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2).setTargetTag(2)); } private KorChant(final KorChant card) { @@ -55,7 +46,7 @@ class KorChantEffect extends RedirectionEffect { KorChantEffect() { super(Duration.EndOfTurn); - staticText = "All damage that would be dealt this turn to target creature you control by a source of your choice is dealt to another target creature instead"; + staticText = "all damage that would be dealt this turn to target creature you control by a source of your choice is dealt to another target creature instead"; } private KorChantEffect(final KorChantEffect effect) { diff --git a/Mage.Sets/src/mage/cards/k/KorDirge.java b/Mage.Sets/src/mage/cards/k/KorDirge.java index a08131260dc..90a31de93c2 100644 --- a/Mage.Sets/src/mage/cards/k/KorDirge.java +++ b/Mage.Sets/src/mage/cards/k/KorDirge.java @@ -1,7 +1,5 @@ - package mage.cards.k; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.RedirectionEffect; import mage.cards.CardImpl; @@ -9,16 +7,16 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.other.AnotherTargetPredicate; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; +import mage.target.TargetPermanent; import mage.target.TargetSource; import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; /** - * * @author emerald000 */ public final class KorDirge extends CardImpl { @@ -28,15 +26,8 @@ public final class KorDirge extends CardImpl { // All damage that would be dealt this turn to target creature you control by a source of your choice is dealt to another target creature instead. this.getSpellAbility().addEffect(new KorDirgeEffect()); - TargetControlledCreaturePermanent target = new TargetControlledCreaturePermanent(); - target.setTargetTag(1); - this.getSpellAbility().addTarget(target); - - FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); - filter.add(new AnotherTargetPredicate(2)); - TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter); - target2.setTargetTag(2); - this.getSpellAbility().addTarget(target2); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent().setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2).setTargetTag(2)); } private KorDirge(final KorDirge card) { diff --git a/Mage.Sets/src/mage/cards/k/KorEntanglers.java b/Mage.Sets/src/mage/cards/k/KorEntanglers.java index ad61f183308..0e806142244 100644 --- a/Mage.Sets/src/mage/cards/k/KorEntanglers.java +++ b/Mage.Sets/src/mage/cards/k/KorEntanglers.java @@ -11,8 +11,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -29,7 +32,7 @@ public final class KorEntanglers extends CardImpl { // Rally — Whenever Kor Entanglers or another Ally you control enters, tap target creature an opponent controls. Ability ability = new AllyEntersBattlefieldTriggeredAbility(new TapTargetEffect(), false); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KorHookmaster.java b/Mage.Sets/src/mage/cards/k/KorHookmaster.java index 64e80a529d4..1e043d23e3b 100644 --- a/Mage.Sets/src/mage/cards/k/KorHookmaster.java +++ b/Mage.Sets/src/mage/cards/k/KorHookmaster.java @@ -11,8 +11,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author North @@ -31,7 +34,7 @@ public final class KorHookmaster extends CardImpl { // That creature doesn't untap during its controller's next untap step. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new TapTargetEffect()); ability.addEffect(new DontUntapInControllersNextUntapStepTargetEffect("that creature")); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KorLineSlinger.java b/Mage.Sets/src/mage/cards/k/KorLineSlinger.java index 35c54e7594d..bf1f15cb734 100644 --- a/Mage.Sets/src/mage/cards/k/KorLineSlinger.java +++ b/Mage.Sets/src/mage/cards/k/KorLineSlinger.java @@ -15,6 +15,7 @@ import mage.constants.ComparisonType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -37,7 +38,7 @@ public final class KorLineSlinger extends CardImpl { this.toughness = new MageInt(1); Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KorSanctifiers.java b/Mage.Sets/src/mage/cards/k/KorSanctifiers.java index a994489cd4e..91f211ac78f 100644 --- a/Mage.Sets/src/mage/cards/k/KorSanctifiers.java +++ b/Mage.Sets/src/mage/cards/k/KorSanctifiers.java @@ -1,10 +1,9 @@ - package mage.cards.k; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -17,13 +16,12 @@ import mage.target.TargetPermanent; import java.util.UUID; /** - * * @author Loki */ public final class KorSanctifiers extends CardImpl { - public KorSanctifiers (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}"); + public KorSanctifiers(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); this.subtype.add(SubType.KOR); this.subtype.add(SubType.CLERIC); @@ -34,9 +32,9 @@ public final class KorSanctifiers extends CardImpl { this.addAbility(new KickerAbility("{W}")); // When Kor Sanctifiers enters the battlefield, if it was kicked, destroy target artifact or enchantment. - EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), false); + Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()).withInterveningIf(KickedCondition.ONCE); ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.ONCE, "When {this} enters, if it was kicked, destroy target artifact or enchantment.")); + this.addAbility(ability); } private KorSanctifiers(final KorSanctifiers card) { diff --git a/Mage.Sets/src/mage/cards/k/KoskunFalls.java b/Mage.Sets/src/mage/cards/k/KoskunFalls.java index 263c52f2a9e..085d753fb0e 100644 --- a/Mage.Sets/src/mage/cards/k/KoskunFalls.java +++ b/Mage.Sets/src/mage/cards/k/KoskunFalls.java @@ -1,51 +1,38 @@ - package mage.cards.k; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.common.TapTargetCost; -import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.Effect; +import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.SacrificeSourceUnlessPaysEffect; import mage.abilities.effects.common.combat.CantAttackYouUnlessPayAllEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SuperType; +import mage.filter.StaticFilters; import java.util.UUID; /** - * * @author fireshoes */ public final class KoskunFalls extends CardImpl { - - private static final FilterControlledCreaturePermanent filterCreature = new FilterControlledCreaturePermanent("untapped creature you control"); - - static { - filterCreature.add(TappedPredicate.UNTAPPED); - } public KoskunFalls(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{B}"); this.supertype.add(SuperType.WORLD); // At the beginning of your upkeep, sacrifice Koskun Falls unless you tap an untapped creature you control. - Effect effect = new SacrificeSourceUnlessPaysEffect(new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filterCreature, true))); - effect.setText("sacrifice Koskun Falls unless you tap an untapped creature you control"); - this.addAbility(new BeginningOfUpkeepTriggeredAbility(effect)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new SacrificeSourceUnlessPaysEffect(new TapTargetCost(StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURE)) + )); // Creatures can't attack you unless their controller pays {2} for each creature they control that's attacking you. - this.addAbility(new SimpleStaticAbility( - Zone.BATTLEFIELD, - new CantAttackYouUnlessPayAllEffect( - Duration.WhileOnBattlefield, - new ManaCostsImpl<>("{2}") - ) - )); + this.addAbility(new SimpleStaticAbility(new CantAttackYouUnlessPayAllEffect( + Duration.WhileOnBattlefield, new GenericManaCost(2) + ))); } private KoskunFalls(final KoskunFalls card) { diff --git a/Mage.Sets/src/mage/cards/k/KozilekTheGreatDistortion.java b/Mage.Sets/src/mage/cards/k/KozilekTheGreatDistortion.java index a23bd556cb5..b8842f6f4b9 100644 --- a/Mage.Sets/src/mage/cards/k/KozilekTheGreatDistortion.java +++ b/Mage.Sets/src/mage/cards/k/KozilekTheGreatDistortion.java @@ -1,16 +1,12 @@ - package mage.cards.k; -import java.util.HashSet; -import java.util.Set; -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.CardsInHandCondition; import mage.abilities.costs.Cost; import mage.abilities.costs.CostImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CastSourceTriggeredAbility; import mage.abilities.effects.common.CounterTargetEffect; @@ -18,12 +14,7 @@ import mage.abilities.keyword.MenaceAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.ComparisonType; -import mage.constants.Outcome; -import mage.constants.SuperType; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.FilterCard; import mage.filter.FilterSpell; import mage.filter.predicate.mageobject.ManaValuePredicate; @@ -34,24 +25,27 @@ import mage.players.Player; import mage.target.TargetSpell; import mage.target.common.TargetCardInHand; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class KozilekTheGreatDistortion extends CardImpl { + private static final Condition condition = new CardsInHandCondition(ComparisonType.FEWER_THAN, 7); + public KozilekTheGreatDistortion(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{8}{C}{C}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{8}{C}{C}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.ELDRAZI); this.power = new MageInt(12); this.toughness = new MageInt(12); // When you cast Kozilek, the Great Distortion, if you have fewer than seven cards in hand, draw cards equal to the difference. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new CastSourceTriggeredAbility(new KozilekDrawEffect(), false), - new CardsInHandCondition(ComparisonType.FEWER_THAN, 7), - "When you cast this spell, if you have fewer than seven cards in hand, draw cards equal to the difference.")); + this.addAbility(new CastSourceTriggeredAbility(new KozilekDrawEffect(), false).withInterveningIf(condition)); + // Menace this.addAbility(new MenaceAbility(false)); @@ -75,7 +69,7 @@ class KozilekDrawEffect extends OneShotEffect { KozilekDrawEffect() { super(Outcome.DrawCard); - this.staticText = "if you have fewer than seven cards in hand, draw cards equal to the difference"; + this.staticText = "draw cards equal to the difference"; } private KozilekDrawEffect(final KozilekDrawEffect effect) { @@ -148,7 +142,7 @@ class KozilekDiscardCost extends CostImpl { } } Player controller = game.getPlayer(ability.getControllerId()); - if(controller != null) { + if (controller != null) { for (Card card : controller.getHand().getCards(game)) { if (stackCMC.contains(card.getManaValue())) { return true; diff --git a/Mage.Sets/src/mage/cards/k/KozileksCommand.java b/Mage.Sets/src/mage/cards/k/KozileksCommand.java index fd0c2b9c9fa..b66c2b9b32f 100644 --- a/Mage.Sets/src/mage/cards/k/KozileksCommand.java +++ b/Mage.Sets/src/mage/cards/k/KozileksCommand.java @@ -19,6 +19,7 @@ import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.game.Game; import mage.game.permanent.token.EldraziSpawnToken; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.TargetPlayer; import mage.target.common.TargetCardInGraveyard; import mage.target.common.TargetCreaturePermanent; @@ -91,7 +92,7 @@ enum KozileksCommandAdjuster implements TargetAdjuster { mode.getTargets().clear(); FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with mana value " + xValue + " or less"); filter.add(new ManaValuePredicate(ComparisonType.OR_LESS, xValue)); - mode.addTarget(new TargetCreaturePermanent(filter)); + mode.addTarget(new TargetPermanent(filter)); } if (target instanceof TargetCardInGraveyard) { mode.getTargets().clear(); @@ -100,4 +101,4 @@ enum KozileksCommandAdjuster implements TargetAdjuster { } } } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/k/KrileBaldesion.java b/Mage.Sets/src/mage/cards/k/KrileBaldesion.java index 577dbb8e1aa..d903845063f 100644 --- a/Mage.Sets/src/mage/cards/k/KrileBaldesion.java +++ b/Mage.Sets/src/mage/cards/k/KrileBaldesion.java @@ -75,6 +75,7 @@ enum KrileBaldesionPredicate implements ObjectSourcePlayerPredicate { return CardUtil .getEffectValueFromAbility(input.getSource(), "spellCast", Spell.class) .map(Spell::getManaValue) - .equals(input.getObject().getManaValue()); + .filter(x -> x == input.getObject().getManaValue()) + .isPresent(); } } diff --git a/Mage.Sets/src/mage/cards/k/KronchWrangler.java b/Mage.Sets/src/mage/cards/k/KronchWrangler.java index d483ffdf91e..ce8efe9add9 100644 --- a/Mage.Sets/src/mage/cards/k/KronchWrangler.java +++ b/Mage.Sets/src/mage/cards/k/KronchWrangler.java @@ -1,7 +1,7 @@ package mage.cards.k; import mage.MageInt; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; @@ -22,7 +22,7 @@ import java.util.UUID; public final class KronchWrangler extends CardImpl { private static final FilterPermanent filter - = new FilterControlledCreaturePermanent("a creature with power 4 or greater"); + = new FilterControlledCreaturePermanent("a creature you control with power 4 or greater"); static { filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3)); @@ -40,7 +40,7 @@ public final class KronchWrangler extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // Whenever a creature with power 4 or greater you control enters, put a +1/+1 counter on Kronch Wrangler. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + this.addAbility(new EntersBattlefieldAllTriggeredAbility( new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filter )); } diff --git a/Mage.Sets/src/mage/cards/k/KrondTheDawnClad.java b/Mage.Sets/src/mage/cards/k/KrondTheDawnClad.java index f9b705c9a23..2a674c115ae 100644 --- a/Mage.Sets/src/mage/cards/k/KrondTheDawnClad.java +++ b/Mage.Sets/src/mage/cards/k/KrondTheDawnClad.java @@ -1,12 +1,10 @@ - package mage.cards.k; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.EnchantedSourceCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.VigilanceAbility; @@ -17,14 +15,17 @@ import mage.constants.SubType; import mage.constants.SuperType; import mage.target.TargetPermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class KrondTheDawnClad extends CardImpl { + private static final Condition condition = new EnchantedSourceCondition(); + public KrondTheDawnClad(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}{G}{G}{W}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{G}{G}{W}{W}{W}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.ARCHON); @@ -36,10 +37,8 @@ public final class KrondTheDawnClad extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // Whenever Krond the Dawn-Clad attacks, if it's enchanted, exile target permanent. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new ExileTargetEffect(), false), - new EnchantedSourceCondition(), - "Whenever {this} attacks, if it's enchanted, exile target permanent."); + Ability ability = new AttacksTriggeredAbility(new ExileTargetEffect(), false) + .withInterveningIf(condition).withRuleTextReplacement(true); ability.addTarget(new TargetPermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KrosanAvenger.java b/Mage.Sets/src/mage/cards/k/KrosanAvenger.java index 1b66837f024..c809242615b 100644 --- a/Mage.Sets/src/mage/cards/k/KrosanAvenger.java +++ b/Mage.Sets/src/mage/cards/k/KrosanAvenger.java @@ -3,7 +3,7 @@ package mage.cards.k; import mage.MageInt; import mage.abilities.condition.common.ThresholdCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.RegenerateSourceEffect; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; @@ -31,7 +31,7 @@ public final class KrosanAvenger extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // Threshold - {1}{G}: Regenerate Krosan Avenger. Activate this ability only if seven or more cards are in your graveyard. - this.addAbility(new ConditionalActivatedAbility( + this.addAbility(new ActivateIfConditionActivatedAbility( new RegenerateSourceEffect(), new ManaCostsImpl<>("{1}{G}"), ThresholdCondition.instance ).setAbilityWord(AbilityWord.THRESHOLD)); } diff --git a/Mage.Sets/src/mage/cards/k/KrosanConstrictor.java b/Mage.Sets/src/mage/cards/k/KrosanConstrictor.java index fcdba83d14d..2da3d9bb40f 100644 --- a/Mage.Sets/src/mage/cards/k/KrosanConstrictor.java +++ b/Mage.Sets/src/mage/cards/k/KrosanConstrictor.java @@ -17,6 +17,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -41,7 +42,7 @@ public final class KrosanConstrictor extends CardImpl { this.addAbility(new SwampwalkAbility()); // {tap}: Target black creature gets -2/-0 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(-2, -0, Duration.EndOfTurn), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KrosanDruid.java b/Mage.Sets/src/mage/cards/k/KrosanDruid.java index 1cfa762d0fc..9e13a8c6738 100644 --- a/Mage.Sets/src/mage/cards/k/KrosanDruid.java +++ b/Mage.Sets/src/mage/cards/k/KrosanDruid.java @@ -1,20 +1,18 @@ - package mage.cards.k; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.keyword.KickerAbility; -import mage.constants.SubType; 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 KrosanDruid extends CardImpl { @@ -31,11 +29,7 @@ public final class KrosanDruid extends CardImpl { this.addAbility(new KickerAbility("{4}{G}")); // When Krosan Druid enters the battlefield, if it was kicked, you gain 10 life. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new GainLifeEffect(10)), - KickedCondition.ONCE, - "When {this} enters, if it was kicked, you gain 10 life" - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(10)).withInterveningIf(KickedCondition.ONCE)); } private KrosanDruid(final KrosanDruid card) { diff --git a/Mage.Sets/src/mage/cards/k/KrosanGroundshaker.java b/Mage.Sets/src/mage/cards/k/KrosanGroundshaker.java index 0a8a6417c7c..b65f877c0dd 100644 --- a/Mage.Sets/src/mage/cards/k/KrosanGroundshaker.java +++ b/Mage.Sets/src/mage/cards/k/KrosanGroundshaker.java @@ -15,6 +15,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -37,7 +38,7 @@ public final class KrosanGroundshaker extends CardImpl { // {G}: Target Beast creature gains trample until end of turn. Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{G}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KrosanRestorer.java b/Mage.Sets/src/mage/cards/k/KrosanRestorer.java index bc9d0d5640a..6e54b624263 100644 --- a/Mage.Sets/src/mage/cards/k/KrosanRestorer.java +++ b/Mage.Sets/src/mage/cards/k/KrosanRestorer.java @@ -5,7 +5,7 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.ThresholdCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.UntapTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -34,7 +34,7 @@ public final class KrosanRestorer extends CardImpl { this.addAbility(ability); // Threshold - {tap}: Untap up to three target lands. Activate this ability only if seven or more cards are in your graveyard. - ability = new ConditionalActivatedAbility(new UntapTargetEffect(), new TapSourceCost(), ThresholdCondition.instance); + ability = new ActivateIfConditionActivatedAbility(new UntapTargetEffect(), new TapSourceCost(), ThresholdCondition.instance); ability.addTarget(new TargetLandPermanent(0, 3)); ability.setAbilityWord(AbilityWord.THRESHOLD); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/k/KrosanWarchief.java b/Mage.Sets/src/mage/cards/k/KrosanWarchief.java index cc836a57493..4d0bb62d357 100644 --- a/Mage.Sets/src/mage/cards/k/KrosanWarchief.java +++ b/Mage.Sets/src/mage/cards/k/KrosanWarchief.java @@ -16,6 +16,7 @@ import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.common.FilterCreaturePermanent; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -45,7 +46,7 @@ public final class KrosanWarchief extends CardImpl { SimpleActivatedAbility ability = new SimpleActivatedAbility( new RegenerateTargetEffect(), new ManaCostsImpl<>("{1}{G}")); - Target target = new TargetCreaturePermanent(filterTarget); + Target target = new TargetPermanent(filterTarget); ability.addTarget(target); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KrovikanPlague.java b/Mage.Sets/src/mage/cards/k/KrovikanPlague.java index ea0ee8d0be0..d0278d074a2 100644 --- a/Mage.Sets/src/mage/cards/k/KrovikanPlague.java +++ b/Mage.Sets/src/mage/cards/k/KrovikanPlague.java @@ -1,11 +1,10 @@ - package mage.cards.k; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.delayed.AtTheBeginOfNextUpkeepDelayedTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.AttachedToMatchesFilterCondition; import mage.abilities.costs.common.TapAttachedCost; import mage.abilities.effects.common.AttachEffect; @@ -17,60 +16,63 @@ 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.Duration; -import mage.constants.Zone; +import mage.constants.Outcome; +import mage.constants.SubType; import mage.counters.CounterType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.TappedPredicate; import mage.target.TargetPermanent; -import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** - * * @author L_J */ public final class KrovikanPlague extends CardImpl { - - private static final FilterControlledCreaturePermanent filterNonWall = new FilterControlledCreaturePermanent("non-Wall creature you control"); + + private static final FilterPermanent filterNonWall = new FilterControlledCreaturePermanent("non-Wall creature you control"); static { filterNonWall.add(Predicates.not(SubType.WALL.getPredicate())); } - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("enchanted creature is untapped"); - + private static final FilterPermanent filter = new FilterCreaturePermanent("enchanted creature is untapped"); + static { filter.add(TappedPredicate.UNTAPPED); } + private static final Condition condition = new AttachedToMatchesFilterCondition(filter); + public KrovikanPlague(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}"); this.subtype.add(SubType.AURA); // Enchant non-Wall creature you control - TargetPermanent auraTarget = new TargetControlledCreaturePermanent(filterNonWall); + TargetPermanent auraTarget = new TargetPermanent(filterNonWall); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // When Krovikan Plague enters the battlefield, draw a card at the beginning of the next turn's upkeep. this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateDelayedTriggeredAbilityEffect( - new AtTheBeginOfNextUpkeepDelayedTriggeredAbility(new DrawCardSourceControllerEffect(1), Duration.OneUse)) - .setText("draw a card at the beginning of the next turn's upkeep"), false)); + new AtTheBeginOfNextUpkeepDelayedTriggeredAbility(new DrawCardSourceControllerEffect(1), Duration.OneUse) + ).setText("draw a card at the beginning of the next turn's upkeep"), false)); // Tap enchanted creature: Tap enchanted creature: Krovikan Plague deals 1 damage to any target. Put a -0/-1 counter on enchanted creature. Activate this ability only if enchanted creature is untapped. - Ability ability2 = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new DamageTargetEffect(1), new TapAttachedCost(), new AttachedToMatchesFilterCondition(filter)); - ability2.addEffect(new AddCountersAttachedEffect(CounterType.M0M1.createInstance(),"enchanted creature")); - ability2.addTarget(new TargetAnyTarget()); - this.addAbility(ability2); - + Ability ability = new ActivateIfConditionActivatedAbility( + new DamageTargetEffect(1), new TapAttachedCost(), condition + ); + ability.addEffect(new AddCountersAttachedEffect( + CounterType.M0M1.createInstance(), "enchanted creature" + )); + ability.addTarget(new TargetAnyTarget()); + this.addAbility(ability); } private KrovikanPlague(final KrovikanPlague card) { diff --git a/Mage.Sets/src/mage/cards/k/KrovikanRot.java b/Mage.Sets/src/mage/cards/k/KrovikanRot.java index 126d4761177..e88e977b93f 100644 --- a/Mage.Sets/src/mage/cards/k/KrovikanRot.java +++ b/Mage.Sets/src/mage/cards/k/KrovikanRot.java @@ -11,6 +11,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -30,7 +31,7 @@ public final class KrovikanRot extends CardImpl { // Destroy target creature with power 2 or less. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // Recover {1}{B}{B} this.addAbility(new RecoverAbility(new ManaCostsImpl<>("{1}{B}{B}"), this)); diff --git a/Mage.Sets/src/mage/cards/k/KuldothaPhoenix.java b/Mage.Sets/src/mage/cards/k/KuldothaPhoenix.java index cebeb77a74d..8fa398e7cd2 100644 --- a/Mage.Sets/src/mage/cards/k/KuldothaPhoenix.java +++ b/Mage.Sets/src/mage/cards/k/KuldothaPhoenix.java @@ -3,17 +3,21 @@ package mage.cards.k; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.condition.CompoundCondition; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; import mage.abilities.hint.common.MetalcraftHint; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.AbilityWord; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; import java.util.UUID; @@ -22,6 +26,11 @@ import java.util.UUID; */ public final class KuldothaPhoenix extends CardImpl { + private static final Condition condition = new CompoundCondition( + "during your upkeep and only if you control three or more artifacts", + IsStepCondition.getMyUpkeep(), MetalcraftCondition.instance + ); + public KuldothaPhoenix(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}{R}"); this.subtype.add(SubType.PHOENIX); @@ -35,11 +44,9 @@ public final class KuldothaPhoenix extends CardImpl { // Metalcraft — {4}: Return Kuldotha Phoenix from your graveyard to the battlefield. // Activate this ability only during your upkeep and only if you control three or more artifacts. - Ability ability = new ConditionalActivatedAbility(Zone.GRAVEYARD, + Ability ability = new ActivateIfConditionActivatedAbility(Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldEffect(false, false), - new ManaCostsImpl<>("{4}"), - new CompoundCondition("during your upkeep and only if you control three or more artifacts", - new IsStepCondition(PhaseStep.UPKEEP), MetalcraftCondition.instance) + new ManaCostsImpl<>("{4}"), condition ); ability.setAbilityWord(AbilityWord.METALCRAFT); ability.addHint(MetalcraftHint.instance); @@ -54,5 +61,4 @@ public final class KuldothaPhoenix extends CardImpl { public KuldothaPhoenix copy() { return new KuldothaPhoenix(this); } - -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/k/KyloRen.java b/Mage.Sets/src/mage/cards/k/KyloRen.java index 0ae7cc7dac3..b6074fbd302 100644 --- a/Mage.Sets/src/mage/cards/k/KyloRen.java +++ b/Mage.Sets/src/mage/cards/k/KyloRen.java @@ -6,7 +6,6 @@ import mage.abilities.common.AttacksEachCombatStaticAbility; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; import mage.abilities.dynamicvalue.common.StaticValue; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.keyword.FirstStrikeAbility; @@ -23,7 +22,7 @@ import mage.filter.predicate.permanent.DefendingPlayerControlsSourceAttackingPre import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -58,11 +57,9 @@ public final class KyloRen extends CardImpl { // Whenever Kylo Ren attacks, it gets +1/+0 for each creature in your graveyard and you may tap target creature defending player controls. CardsInControllerGraveyardCount value = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_CREATURE); - Effect effect = new BoostSourceEffect(value, StaticValue.get(0), Duration.WhileOnBattlefield); - effect.setText("it gets +1/+0 for each creature in your graveyard"); - Ability ability = new AttacksTriggeredAbility(effect, false); + Ability ability = new AttacksTriggeredAbility(new BoostSourceEffect(value, StaticValue.get(0), Duration.WhileOnBattlefield).setText("it gets +1/+0 for each creature in your graveyard")); ability.addEffect(new KyloRenTapTargetEffect()); - ability.addTarget(new TargetCreaturePermanent(0, 1, filter, false)); + ability.addTarget(new TargetPermanent(0, 1, filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/k/KyrenNegotiations.java b/Mage.Sets/src/mage/cards/k/KyrenNegotiations.java index 70b3f95e24e..a99463dd172 100644 --- a/Mage.Sets/src/mage/cards/k/KyrenNegotiations.java +++ b/Mage.Sets/src/mage/cards/k/KyrenNegotiations.java @@ -1,6 +1,5 @@ package mage.cards.k; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapTargetCost; @@ -8,31 +7,22 @@ import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.filter.StaticFilters; import mage.target.common.TargetPlayerOrPlaneswalker; +import java.util.UUID; + /** - * * @author ingmargoudt */ public final class KyrenNegotiations extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); - - static { - filter.add(TappedPredicate.UNTAPPED); - } - public KyrenNegotiations(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}{R}"); // Tap an untapped creature you control: Kyren Negotiations deals 1 damage to target player. Ability ability = new SimpleActivatedAbility( - new DamageTargetEffect(1), - new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, false)) + new DamageTargetEffect(1), new TapTargetCost(StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURE) ); ability.addTarget(new TargetPlayerOrPlaneswalker()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java b/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java index 7e0f854d9b6..56c4872994e 100644 --- a/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java +++ b/Mage.Sets/src/mage/cards/k/KytheonHeroOfAkros.java @@ -1,17 +1,11 @@ - package mage.cards.k; -import java.util.UUID; - import mage.MageInt; -import mage.MageObjectReference; import mage.abilities.Ability; -import mage.constants.Pronoun; import mage.abilities.common.EndOfCombatTriggeredAbility; 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.common.ExileAndReturnSourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.IndestructibleAbility; @@ -20,9 +14,10 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.watchers.common.AttackedOrBlockedThisCombatWatcher; +import java.util.UUID; + /** * @author LevelX2 */ @@ -41,12 +36,14 @@ public final class KytheonHeroOfAkros extends CardImpl { // At end of combat, if Kytheon, Hero of Akros and at least two other creatures attacked this combat, exile Kytheon, // then return him to the battlefield transformed under his owner's control. this.addAbility(new TransformAbility()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EndOfCombatTriggeredAbility(new ExileAndReturnSourceEffect(PutCards.BATTLEFIELD_TRANSFORMED,Pronoun.HE), false), - new KytheonHeroOfAkrosCondition(), "At end of combat, if {this} and at least two other creatures attacked this combat, exile {this}, " - + "then return him to the battlefield transformed under his owner's control."), new AttackedOrBlockedThisCombatWatcher()); + this.addAbility(new EndOfCombatTriggeredAbility( + new ExileAndReturnSourceEffect(PutCards.BATTLEFIELD_TRANSFORMED, Pronoun.HE), false + ).withInterveningIf(KytheonHeroOfAkrosCondition.instance), new AttackedOrBlockedThisCombatWatcher()); // {2}{W}: Kytheon gains indestructible until end of turn. - this.addAbility(new SimpleActivatedAbility(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{2}{W}"))); + this.addAbility(new SimpleActivatedAbility(new GainAbilitySourceEffect( + IndestructibleAbility.getInstance(), Duration.EndOfTurn + ), new ManaCostsImpl<>("{2}{W}"))); } @@ -60,27 +57,20 @@ public final class KytheonHeroOfAkros extends CardImpl { } } -class KytheonHeroOfAkrosCondition implements Condition { +enum KytheonHeroOfAkrosCondition implements Condition { + instance; @Override public boolean apply(Game game, Ability source) { - Permanent sourceObject = game.getPermanent(source.getSourceId()); - if (sourceObject != null) { - AttackedOrBlockedThisCombatWatcher watcher = game.getState().getWatcher(AttackedOrBlockedThisCombatWatcher.class); - if (watcher != null) { - boolean sourceFound = false; - int number = 0; - for (MageObjectReference mor : watcher.getAttackedThisTurnCreatures()) { - if (mor.refersTo(sourceObject, game)) { - sourceFound = true; - } else { - number++; - } - } - return sourceFound && number >= 2; - } - } - return false; + AttackedOrBlockedThisCombatWatcher watcher = game.getState().getWatcher(AttackedOrBlockedThisCombatWatcher.class); + return watcher != null + && watcher + .getAttackedThisTurnCreatures() + .stream() + .anyMatch(mor -> mor.refersTo(source, game)) + && watcher + .getAttackedThisTurnCreatures() + .size() >= 3; } @Override diff --git a/Mage.Sets/src/mage/cards/l/LadySun.java b/Mage.Sets/src/mage/cards/l/LadySun.java index 98110b6b2bf..a409c8bead9 100644 --- a/Mage.Sets/src/mage/cards/l/LadySun.java +++ b/Mage.Sets/src/mage/cards/l/LadySun.java @@ -1,13 +1,10 @@ - package mage.cards.l; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.common.MyTurnBeforeAttackersDeclaredCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.ReturnToHandSourceEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; @@ -15,24 +12,18 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; -import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.AnotherPredicate; -import mage.target.common.TargetCreaturePermanent; +import mage.filter.StaticFilters; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author fireshoes */ public final class LadySun extends CardImpl { - - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); - static { - filter.add(AnotherPredicate.instance); - } public LadySun(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{U}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.ADVISOR); @@ -40,14 +31,12 @@ public final class LadySun extends CardImpl { this.toughness = new MageInt(1); // {tap}: Return Lady Sun and another target creature to their owners' hands. Activate this ability only during your turn, before attackers are declared. - Effect effect = new ReturnToHandSourceEffect(true); - effect.setText("Return Lady Sun"); - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - effect, new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); - effect = new ReturnToHandTargetEffect(); - effect.setText("and another target creature to their owners' hands"); - ability.addTarget(new TargetCreaturePermanent(filter)); - ability.addEffect(effect); + Ability ability = new ActivateIfConditionActivatedAbility( + new ReturnToHandSourceEffect(true).setText("return {this}"), + new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance + ); + ability.addEffect(new ReturnToHandTargetEffect().setText("and another target creature to their owners' hands")); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/l/LagomosHandOfHatred.java b/Mage.Sets/src/mage/cards/l/LagomosHandOfHatred.java index e86e80c5a35..3fd94e32bce 100644 --- a/Mage.Sets/src/mage/cards/l/LagomosHandOfHatred.java +++ b/Mage.Sets/src/mage/cards/l/LagomosHandOfHatred.java @@ -1,19 +1,21 @@ package mage.cards.l; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.SacrificeTargetEffect; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; -import mage.constants.*; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; 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.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.Elemental21TrampleHasteToken; @@ -22,8 +24,9 @@ import mage.target.common.TargetCardInLibrary; import mage.target.targetpointer.FixedTarget; import mage.watchers.common.CreaturesDiedWatcher; +import java.util.UUID; + /** - * * @author weirddan455 */ public final class LagomosHandOfHatred extends CardImpl { @@ -41,11 +44,9 @@ public final class LagomosHandOfHatred extends CardImpl { this.addAbility(new BeginningOfCombatTriggeredAbility(new LagomosHandOfHatredEffect())); // {T}: Search your library for a card, put it into your hand, then shuffle. Activate only if five or more creatures died this turn. - this.addAbility(new ConditionalActivatedAbility( - Zone.BATTLEFIELD, + this.addAbility(new ActivateIfConditionActivatedAbility( new SearchLibraryPutInHandEffect(new TargetCardInLibrary(), false), - new TapSourceCost(), - LagomosHandOfHatredCondition.instance + new TapSourceCost(), LagomosHandOfHatredCondition.instance )); } diff --git a/Mage.Sets/src/mage/cards/l/LagonnaBandElder.java b/Mage.Sets/src/mage/cards/l/LagonnaBandElder.java index 2c6fba72e17..ac751cbcbe9 100644 --- a/Mage.Sets/src/mage/cards/l/LagonnaBandElder.java +++ b/Mage.Sets/src/mage/cards/l/LagonnaBandElder.java @@ -1,17 +1,15 @@ - package mage.cards.l; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledEnchantmentPermanent; import java.util.UUID; @@ -20,6 +18,10 @@ import java.util.UUID; */ public final class LagonnaBandElder extends CardImpl { + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledEnchantmentPermanent("you control an enchantment") + ); + public LagonnaBandElder(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); this.subtype.add(SubType.CENTAUR); @@ -29,11 +31,7 @@ public final class LagonnaBandElder extends CardImpl { this.toughness = new MageInt(2); // When Lagonna-Band Elder enters the battlefield, if you control an enchantment, you gain 3 life. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3), false), - new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_PERMANENT_ENCHANTMENT), - "When Lagonna-Band Elder enters the battlefield, if you control an enchantment, you gain 3 life"); - this.addAbility(ability); + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3), false).withInterveningIf(condition)); } private LagonnaBandElder(final LagonnaBandElder card) { diff --git a/Mage.Sets/src/mage/cards/l/LagonnaBandTrailblazer.java b/Mage.Sets/src/mage/cards/l/LagonnaBandTrailblazer.java index 16b57d7bd8a..0dbc89655be 100644 --- a/Mage.Sets/src/mage/cards/l/LagonnaBandTrailblazer.java +++ b/Mage.Sets/src/mage/cards/l/LagonnaBandTrailblazer.java @@ -26,7 +26,8 @@ public final class LagonnaBandTrailblazer extends CardImpl { this.toughness = new MageInt(4); // Heroic — Whenever you cast a spell that targets Lagonna-Band Trailblazer, put a +1/+1 counter on Lagonna-Band Trailblzer. - this.addAbility(new HeroicAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()))); + this.addAbility(new HeroicAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance())) + .withRuleTextReplacement(true)); } private LagonnaBandTrailblazer(final LagonnaBandTrailblazer card) { diff --git a/Mage.Sets/src/mage/cards/l/LamplighterOfSelhoff.java b/Mage.Sets/src/mage/cards/l/LamplighterOfSelhoff.java index ba96ccaa275..400d96dcb94 100644 --- a/Mage.Sets/src/mage/cards/l/LamplighterOfSelhoff.java +++ b/Mage.Sets/src/mage/cards/l/LamplighterOfSelhoff.java @@ -1,47 +1,45 @@ - package mage.cards.l; import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawDiscardControllerEffect; 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.mageobject.AnotherPredicate; import java.util.UUID; /** - * * @author fireshoes */ public final class LamplighterOfSelhoff extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent("another Zombie"); + private static final FilterPermanent filter + = new FilterControlledPermanent(SubType.ZOMBIE, "you control another Zombie"); static { filter.add(AnotherPredicate.instance); - filter.add(SubType.ZOMBIE.getPredicate()); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); + public LamplighterOfSelhoff(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}"); this.subtype.add(SubType.ZOMBIE); this.subtype.add(SubType.HORROR); this.power = new MageInt(3); this.toughness = new MageInt(5); // When Lamplighter of Selhoff enters the battlefield, if you control another Zombie, you may a draw card. If you do, discard a card. - TriggeredAbility triggeredAbility = new EntersBattlefieldTriggeredAbility(new DrawDiscardControllerEffect(1,1,true)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - triggeredAbility, - new PermanentsOnTheBattlefieldCondition(filter), - "When {this} enters, if you control another Zombie, you may draw a card. If you do, discard a card.")); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new DrawDiscardControllerEffect(1, 1, true) + ).withInterveningIf(condition)); } private LamplighterOfSelhoff(final LamplighterOfSelhoff card) { diff --git a/Mage.Sets/src/mage/cards/l/LandTax.java b/Mage.Sets/src/mage/cards/l/LandTax.java index 8c31da5582c..93bfd709c87 100644 --- a/Mage.Sets/src/mage/cards/l/LandTax.java +++ b/Mage.Sets/src/mage/cards/l/LandTax.java @@ -1,10 +1,9 @@ - package mage.cards.l; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.OpponentControlsMoreCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -14,21 +13,19 @@ import mage.target.common.TargetCardInLibrary; import java.util.UUID; /** - * * @author LevelX2 */ public final class LandTax extends CardImpl { + private static final Condition condition = new OpponentControlsMoreCondition(StaticFilters.FILTER_LANDS); + public LandTax(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}"); // At the beginning of your upkeep, if an opponent controls more lands than you, you may search your library for up to three basic land cards, reveal them, and put them into your hand. If you do, shuffle your library. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(0, 3, StaticFilters.FILTER_CARD_BASIC_LAND), true), true), - new OpponentControlsMoreCondition(StaticFilters.FILTER_LANDS), - "At the beginning of your upkeep, if an opponent controls more lands than you, you may search your library for up to three basic land cards, reveal them, put them into your hand, then shuffle." - )); - + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SearchLibraryPutInHandEffect( + new TargetCardInLibrary(0, 3, StaticFilters.FILTER_CARD_BASIC_LANDS), true + ), true).withInterveningIf(condition)); } private LandTax(final LandTax card) { diff --git a/Mage.Sets/src/mage/cards/l/LandoCalrissian.java b/Mage.Sets/src/mage/cards/l/LandoCalrissian.java index 4be46578402..99f7224a10e 100644 --- a/Mage.Sets/src/mage/cards/l/LandoCalrissian.java +++ b/Mage.Sets/src/mage/cards/l/LandoCalrissian.java @@ -13,6 +13,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -46,7 +47,7 @@ public final class LandoCalrissian extends CardImpl { effect = new GainAbilityTargetEffect(VigilanceAbility.getInstance(), Duration.EndOfTurn); effect.setText("and gains vigilance until end of turn"); ability.addEffect(effect); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/l/LandrovalHorizonWitness.java b/Mage.Sets/src/mage/cards/l/LandrovalHorizonWitness.java index 2766a625627..324ac56eca3 100644 --- a/Mage.Sets/src/mage/cards/l/LandrovalHorizonWitness.java +++ b/Mage.Sets/src/mage/cards/l/LandrovalHorizonWitness.java @@ -1,19 +1,18 @@ package mage.cards.l; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; +import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.filter.common.FilterAttackingCreature; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; -import mage.game.Game; -import mage.game.events.DefenderAttackedEvent; -import mage.game.events.GameEvent; import mage.target.TargetPermanent; import java.util.UUID; @@ -23,6 +22,12 @@ import java.util.UUID; */ public final class LandrovalHorizonWitness extends CardImpl { + private static final FilterPermanent filter + = new FilterAttackingCreature("attacking creature without flying"); + + static { + filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); + } public LandrovalHorizonWitness(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}"); @@ -36,7 +41,11 @@ public final class LandrovalHorizonWitness extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Whenever two or more creatures you control attack a player, target attacking creature without flying gains flying until end of turn. - this.addAbility(new LandrovalHorizonWitnessTriggeredAbility()); + Ability ability = new AttacksPlayerWithCreaturesTriggeredAbility( + new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), + 2, StaticFilters.FILTER_CONTROLLED_CREATURES, SetTargetPointer.NONE, false); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); } private LandrovalHorizonWitness(final LandrovalHorizonWitness card) { @@ -48,40 +57,3 @@ public final class LandrovalHorizonWitness extends CardImpl { return new LandrovalHorizonWitness(this); } } - -class LandrovalHorizonWitnessTriggeredAbility extends TriggeredAbilityImpl { - - private static final FilterPermanent filter - = new FilterAttackingCreature("attacking creature without flying"); - - static { - filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); - } - - LandrovalHorizonWitnessTriggeredAbility() { - super(Zone.BATTLEFIELD, new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn)); - this.addTarget(new TargetPermanent(filter)); - setTriggerPhrase("Whenever two or more creatures you control attack a player, "); - } - - private LandrovalHorizonWitnessTriggeredAbility(final LandrovalHorizonWitnessTriggeredAbility ability) { - super(ability); - } - - @Override - public LandrovalHorizonWitnessTriggeredAbility copy() { - return new LandrovalHorizonWitnessTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DEFENDER_ATTACKED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return isControlledBy(event.getPlayerId()) - && game.getPlayer(event.getTargetId()) != null - && ((DefenderAttackedEvent) event).getAttackers(game).size() >= 2; - } -} diff --git a/Mage.Sets/src/mage/cards/l/LastNightTogether.java b/Mage.Sets/src/mage/cards/l/LastNightTogether.java index 3b804fc0b31..c1efbf98e17 100644 --- a/Mage.Sets/src/mage/cards/l/LastNightTogether.java +++ b/Mage.Sets/src/mage/cards/l/LastNightTogether.java @@ -134,4 +134,4 @@ class LastNightTogetherDelayedCantAttackAbility extends DelayedTriggeredAbility public String getRule() { return "Only the chosen creatures can attack during that combat phase"; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/l/LatchkeyFaerie.java b/Mage.Sets/src/mage/cards/l/LatchkeyFaerie.java index 7773d7ee2c8..d6bc12909d0 100644 --- a/Mage.Sets/src/mage/cards/l/LatchkeyFaerie.java +++ b/Mage.Sets/src/mage/cards/l/LatchkeyFaerie.java @@ -3,7 +3,6 @@ package mage.cards.l; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.ProwlCostWasPaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.hint.common.ProwlCostWasPaidHint; import mage.abilities.keyword.FlyingAbility; @@ -35,11 +34,8 @@ public final class LatchkeyFaerie extends CardImpl { this.addAbility(new ProwlAbility("{2}{U}")); // When Latchkey Faerie enters the battlefield, if its prowl cost was paid, draw a card. - EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1), false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, ProwlCostWasPaidCondition.instance, - "When {this} enters, if its prowl cost was paid, draw a card.") - .addHint(ProwlCostWasPaidHint.instance)); - + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1), false) + .withInterveningIf(ProwlCostWasPaidCondition.instance).addHint(ProwlCostWasPaidHint.instance)); } private LatchkeyFaerie(final LatchkeyFaerie card) { diff --git a/Mage.Sets/src/mage/cards/l/LathielTheBounteousDawn.java b/Mage.Sets/src/mage/cards/l/LathielTheBounteousDawn.java index 20e73478ede..60cbe63c923 100644 --- a/Mage.Sets/src/mage/cards/l/LathielTheBounteousDawn.java +++ b/Mage.Sets/src/mage/cards/l/LathielTheBounteousDawn.java @@ -2,21 +2,19 @@ package mage.cards.l; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.YouGainedLifeCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.ControllerGainedLifeCount; import mage.abilities.effects.common.counter.DistributeCountersEffect; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; import mage.abilities.keyword.LifelinkAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.TargetController; import mage.filter.StaticFilters; -import mage.game.Game; import mage.target.common.TargetCreaturePermanentAmount; import mage.watchers.common.PlayerGainedLifeWatcher; @@ -41,15 +39,17 @@ public final class LathielTheBounteousDawn extends CardImpl { this.addAbility(LifelinkAbility.getInstance()); // At the beginning of each end step, if you gained life this turn, distribute up to that many +1/+1 counters among any number of other target creatures. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility(TargetController.ANY, new DistributeCountersEffect(), false), - condition, "At the beginning of each end step, if you gained life this turn, " + - "distribute up to that many +1/+1 counters among any number of other target creatures." - ); + Ability ability = new BeginningOfEndStepTriggeredAbility( + TargetController.ANY, new DistributeCountersEffect() + .setText("distribute up to that many +1/+1 counters " + + "among any number of other target creatures"), + false + ).withInterveningIf(condition); ability.addTarget(new TargetCreaturePermanentAmount( - LathielTheBounteousDawnValue.instance, - StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE)); - this.addAbility(ability.addHint(LathielTheBounteousDawnValue.getHint()), new PlayerGainedLifeWatcher()); + ControllerGainedLifeCount.instance, + StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE + )); + this.addAbility(ability.addHint(ControllerGainedLifeCount.getHint()), new PlayerGainedLifeWatcher()); } private LathielTheBounteousDawn(final LathielTheBounteousDawn card) { @@ -61,28 +61,3 @@ public final class LathielTheBounteousDawn extends CardImpl { return new LathielTheBounteousDawn(this); } } - -enum LathielTheBounteousDawnValue implements DynamicValue { - instance; - private static final Hint hint = new ValueHint("Life gained this turn", instance); - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - PlayerGainedLifeWatcher watcher = game.getState().getWatcher(PlayerGainedLifeWatcher.class); - return watcher == null ? 0 : watcher.getLifeGained(sourceAbility.getControllerId()); - } - - @Override - public LathielTheBounteousDawnValue copy() { - return instance; - } - - @Override - public String getMessage() { - return ""; - } - - public static Hint getHint() { - return hint; - } -} diff --git a/Mage.Sets/src/mage/cards/l/LavaFieldOverlord.java b/Mage.Sets/src/mage/cards/l/LavaFieldOverlord.java index 2b35f2cb28b..857bb390e1a 100644 --- a/Mage.Sets/src/mage/cards/l/LavaFieldOverlord.java +++ b/Mage.Sets/src/mage/cards/l/LavaFieldOverlord.java @@ -13,8 +13,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author TheElk801 @@ -36,7 +39,7 @@ public final class LavaFieldOverlord extends CardImpl { // When Lava-Field Overlord enters the battlefield, it deals 4 damage to target creature an opponent controls. Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(4), false); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/l/LavabornMuse.java b/Mage.Sets/src/mage/cards/l/LavabornMuse.java index 13808b30afe..e63bccc138b 100644 --- a/Mage.Sets/src/mage/cards/l/LavabornMuse.java +++ b/Mage.Sets/src/mage/cards/l/LavabornMuse.java @@ -1,13 +1,10 @@ - package mage.cards.l; -import java.util.UUID; import mage.MageInt; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.condition.common.CardsInHandCondition; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.CardsInHandCondition; import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -15,23 +12,27 @@ import mage.constants.ComparisonType; import mage.constants.SubType; import mage.constants.TargetController; +import java.util.UUID; + /** - * * @author ilcartographer */ public final class LavabornMuse extends CardImpl { + private static final Condition condition = new CardsInHandCondition(ComparisonType.FEWER_THAN, 3, TargetController.ACTIVE); + public LavabornMuse(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.SPIRIT); this.power = new MageInt(3); this.toughness = new MageInt(3); // At the beginning of each opponent's upkeep, if that player has two or fewer cards in hand, Lavaborn Muse deals 3 damage to that player. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(TargetController.OPPONENT, new DamageTargetEffect(3), false), - (Condition)new CardsInHandCondition(ComparisonType.FEWER_THAN, 3, TargetController.ACTIVE), - "At the beginning of each opponent's upkeep, if that player has two or fewer cards in hand, {this} deals 3 damage to that player.")); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + TargetController.OPPONENT, + new DamageTargetEffect(3, true, "that player"), + false + ).withInterveningIf(condition)); } private LavabornMuse(final LavabornMuse card) { diff --git a/Mage.Sets/src/mage/cards/l/Lawbringer.java b/Mage.Sets/src/mage/cards/l/Lawbringer.java index ef8f63002d1..710887457d3 100644 --- a/Mage.Sets/src/mage/cards/l/Lawbringer.java +++ b/Mage.Sets/src/mage/cards/l/Lawbringer.java @@ -16,6 +16,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class Lawbringer extends CardImpl { // {tap}, Sacrifice Lawbringer: Exile target red creature. Ability ability = new SimpleActivatedAbility(new ExileTargetEffect(), new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/l/LeadBellyChimera.java b/Mage.Sets/src/mage/cards/l/LeadBellyChimera.java index 4765a6e3fc2..b116720c92d 100644 --- a/Mage.Sets/src/mage/cards/l/LeadBellyChimera.java +++ b/Mage.Sets/src/mage/cards/l/LeadBellyChimera.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -45,7 +46,7 @@ public final class LeadBellyChimera extends CardImpl { Ability ability = new SimpleActivatedAbility(new AddCountersTargetEffect(CounterType.P2P2.createInstance()), new SacrificeSourceCost()); ability.addEffect(new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.WhileOnBattlefield) .setText("It gains trample. (This effect lasts indefinitely.)")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/l/LeafArrow.java b/Mage.Sets/src/mage/cards/l/LeafArrow.java index 52b6fe9d383..b80bd3e4b88 100644 --- a/Mage.Sets/src/mage/cards/l/LeafArrow.java +++ b/Mage.Sets/src/mage/cards/l/LeafArrow.java @@ -9,6 +9,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -27,7 +28,7 @@ public final class LeafArrow extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{G}"); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DamageTargetEffect(3)); } diff --git a/Mage.Sets/src/mage/cards/l/LedevChampion.java b/Mage.Sets/src/mage/cards/l/LedevChampion.java index eef9be75efe..2a59b165cae 100644 --- a/Mage.Sets/src/mage/cards/l/LedevChampion.java +++ b/Mage.Sets/src/mage/cards/l/LedevChampion.java @@ -10,13 +10,15 @@ import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.TappedPredicate; +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.permanent.Permanent; import mage.game.permanent.token.SoldierLifelinkToken; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -57,13 +59,6 @@ public final class LedevChampion extends CardImpl { class LedevChampionEffect extends OneShotEffect { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("untapped creatures you control"); - - static { - filter.add(TargetController.YOU.getControllerPredicate()); - filter.add(TappedPredicate.UNTAPPED); - } - public LedevChampionEffect() { super(Outcome.GainLife); staticText = "you may tap any number of untapped creatures you control. " @@ -76,16 +71,14 @@ class LedevChampionEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { + TargetPermanent target = new TargetPermanent(0, Integer.MAX_VALUE, StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURES, true); + target.choose(Outcome.Tap, source.getControllerId(), source.getSourceId(), source, game); int tappedAmount = 0; - TargetCreaturePermanent target = new TargetCreaturePermanent(0, Integer.MAX_VALUE, filter, true); - if (target.canChoose(source.getControllerId(), source, game) - && target.choose(Outcome.Tap, source.getControllerId(), source.getSourceId(), source, game)) { - for (UUID creatureId : target.getTargets()) { - Permanent creature = game.getPermanent(creatureId); - if (creature != null) { - creature.tap(source, game); - tappedAmount++; - } + for (UUID creatureId : target.getTargets()) { + Permanent creature = game.getPermanent(creatureId); + if (creature != null) { + creature.tap(source, game); + tappedAmount++; } } if (tappedAmount > 0) { diff --git a/Mage.Sets/src/mage/cards/l/LeechingBite.java b/Mage.Sets/src/mage/cards/l/LeechingBite.java index 73c1444b5c2..b20f8c1afcf 100644 --- a/Mage.Sets/src/mage/cards/l/LeechingBite.java +++ b/Mage.Sets/src/mage/cards/l/LeechingBite.java @@ -1,45 +1,29 @@ - package mage.cards.l; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.effects.ContinuousEffectImpl; +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.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.other.AnotherTargetPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.SecondTargetPointer; + +import java.util.UUID; /** - * * @author North */ public final class LeechingBite extends CardImpl { public LeechingBite(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}"); - // Target creature gets +1/+1 until end of turn. Another target creature gets -1/-1 until end of turn. - this.getSpellAbility().addEffect(new LeechingBiteEffect()); - - FilterCreaturePermanent filter1 = new FilterCreaturePermanent("creature to get +1/+1"); - TargetCreaturePermanent target1 = new TargetCreaturePermanent(filter1); - target1.setTargetTag(1); - this.getSpellAbility().addTarget(target1); - - FilterCreaturePermanent filter2 = new FilterCreaturePermanent("another creature to get -1/-1"); - filter2.add(new AnotherTargetPredicate(2)); - TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter2); - target2.setTargetTag(2); - this.getSpellAbility().addTarget(target2); + this.getSpellAbility().addEffect(new BoostTargetEffect(1, 1)); + this.getSpellAbility().addEffect(new BoostTargetEffect(-1, -1).setTargetPointer(new SecondTargetPointer()).setText("Another target creature gets -1/-1 until end of turn")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent().withChooseHint("+1/+1").setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2).withChooseHint("-1/-1").setTargetTag(2)); } private LeechingBite(final LeechingBite card) { @@ -51,35 +35,3 @@ public final class LeechingBite extends CardImpl { return new LeechingBite(this); } } - -class LeechingBiteEffect extends ContinuousEffectImpl { - - public LeechingBiteEffect() { - super(Duration.EndOfTurn, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature); - this.staticText = "Target creature gets +1/+1 until end of turn. Another target creature gets -1/-1 until end of turn"; - } - - private LeechingBiteEffect(final LeechingBiteEffect effect) { - super(effect); - } - - @Override - public LeechingBiteEffect copy() { - return new LeechingBiteEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getFirstTarget()); - if (permanent != null) { - permanent.addPower(1); - permanent.addToughness(1); - } - permanent = game.getPermanent(source.getTargets().get(1).getFirstTarget()); - if (permanent != null) { - permanent.addPower(-1); - permanent.addToughness(-1); - } - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/l/LeechriddenSwamp.java b/Mage.Sets/src/mage/cards/l/LeechriddenSwamp.java index fdbebd4d9be..4217e7169d4 100644 --- a/Mage.Sets/src/mage/cards/l/LeechriddenSwamp.java +++ b/Mage.Sets/src/mage/cards/l/LeechriddenSwamp.java @@ -1,60 +1,54 @@ package mage.cards.l; -import java.util.UUID; - -import mage.Mana; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.common.EntersBattlefieldTappedAbility; +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.OneShotEffect; -import mage.abilities.mana.SimpleManaAbility; +import mage.abilities.effects.common.LoseLifeOpponentsEffect; +import mage.abilities.mana.BlackManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; 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.FilterPermanent; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.ColorPredicate; -import mage.game.Game; -import mage.players.Player; + +import java.util.UUID; /** * @author jeffwadsworth */ public final class LeechriddenSwamp extends CardImpl { - private static final FilterControlledPermanent filter = + private static final FilterPermanent filter = new FilterControlledPermanent("you control two or more black permanents"); static { filter.add(new ColorPredicate(ObjectColor.BLACK)); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1); + public LeechriddenSwamp(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); this.subtype.add(SubType.SWAMP); // ({tap}: Add {B}.) - this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, Mana.BlackMana(1), new TapSourceCost())); + this.addAbility(new BlackManaAbility()); // Leechridden Swamp enters the battlefield tapped. this.addAbility(new EntersBattlefieldTappedAbility()); // {B}, {tap}: Each opponent loses 1 life. Activate this ability only if you control two or more black permanents. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, - new LeechriddenSwampLoseLifeEffect(), - new ManaCostsImpl<>("{B}"), - new PermanentsOnTheBattlefieldCondition( - filter, - ComparisonType.MORE_THAN, - 1)); + new LoseLifeOpponentsEffect(1), new ManaCostsImpl<>("{B}"), condition + ); ability.addCost(new TapSourceCost()); this.addAbility(ability); } @@ -68,35 +62,3 @@ public final class LeechriddenSwamp extends CardImpl { return new LeechriddenSwamp(this); } } - -class LeechriddenSwampLoseLifeEffect extends OneShotEffect { - - LeechriddenSwampLoseLifeEffect() { - super(Outcome.Benefit); - staticText = "each opponent loses 1 life"; - } - - private LeechriddenSwampLoseLifeEffect(final LeechriddenSwampLoseLifeEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - for (UUID opponentId : game.getOpponents(controller.getId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - opponent.loseLife(1, game, source, false); - } - } - return true; - } - return false; - } - - @Override - public LeechriddenSwampLoseLifeEffect copy() { - return new LeechriddenSwampLoseLifeEffect(this); - } -} diff --git a/Mage.Sets/src/mage/cards/l/LegacysAllure.java b/Mage.Sets/src/mage/cards/l/LegacysAllure.java index 8f168ae6d8f..731001d099d 100644 --- a/Mage.Sets/src/mage/cards/l/LegacysAllure.java +++ b/Mage.Sets/src/mage/cards/l/LegacysAllure.java @@ -12,6 +12,7 @@ import mage.cards.CardSetInfo; import mage.constants.*; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetadjustment.PowerTargetAdjuster; @@ -33,7 +34,7 @@ public final class LegacysAllure extends CardImpl { // Sacrifice Legacy's Allure: Gain control of target creature with power less than or equal to the number of treasure counters on Legacy's Allure. Ability ability = new SimpleActivatedAbility(new GainControlTargetEffect(Duration.EndOfGame, true), new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); ability.setTargetAdjuster(new PowerTargetAdjuster(new CountersSourceCount(CounterType.TREASURE), ComparisonType.OR_LESS)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/l/LegionGuildmage.java b/Mage.Sets/src/mage/cards/l/LegionGuildmage.java index 419ff3fd814..2a7b982683e 100644 --- a/Mage.Sets/src/mage/cards/l/LegionGuildmage.java +++ b/Mage.Sets/src/mage/cards/l/LegionGuildmage.java @@ -14,8 +14,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.TargetController; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * * @author TheElk801 @@ -44,7 +47,7 @@ public final class LegionGuildmage extends CardImpl { new ManaCostsImpl<>("{2}{W}") ); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/l/LegolasCounterOfKills.java b/Mage.Sets/src/mage/cards/l/LegolasCounterOfKills.java index 272ea6fb749..cf3119e5f00 100644 --- a/Mage.Sets/src/mage/cards/l/LegolasCounterOfKills.java +++ b/Mage.Sets/src/mage/cards/l/LegolasCounterOfKills.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.common.DiesCreatureTriggeredAbility; import mage.abilities.common.ScryTriggeredAbility; import mage.abilities.condition.common.SourceTappedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.UntapSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.ReachAbility; @@ -36,10 +35,8 @@ public final class LegolasCounterOfKills extends CardImpl { this.addAbility(ReachAbility.getInstance()); // Whenever you scry, if Legolas, Counter of Kills is tapped, you may untap it. Do this only once each turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new ScryTriggeredAbility(new UntapSourceEffect()).setDoOnlyOnceEachTurn(true), SourceTappedCondition.TAPPED, - "Whenever you scry, if {this} is tapped, you may untap it. Do this only once each turn." - )); + this.addAbility(new ScryTriggeredAbility(new UntapSourceEffect().setText("untap it"), true) + .withInterveningIf(SourceTappedCondition.TAPPED).setDoOnlyOnceEachTurn(true)); // Whenever a creature an opponent controls dies, put a +1/+1 counter on Legolas. this.addAbility(new DiesCreatureTriggeredAbility( diff --git a/Mage.Sets/src/mage/cards/l/LeoninVanguard.java b/Mage.Sets/src/mage/cards/l/LeoninVanguard.java index 7809d688a1c..8c36c632504 100644 --- a/Mage.Sets/src/mage/cards/l/LeoninVanguard.java +++ b/Mage.Sets/src/mage/cards/l/LeoninVanguard.java @@ -1,27 +1,32 @@ package mage.cards.l; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; -import mage.constants.SubType; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.Duration; -import mage.filter.StaticFilters; +import mage.constants.SubType; +import mage.filter.common.FilterControlledCreaturePermanent; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class LeoninVanguard extends CardImpl { + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledCreaturePermanent("you control three or more creatures"), + ComparisonType.MORE_THAN, 2 + ); + public LeoninVanguard(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}"); @@ -31,19 +36,10 @@ public final class LeoninVanguard extends CardImpl { this.toughness = new MageInt(1); // At the beginning of combat on your turn, if you control three or more creatures, Leonin Vanguard gets +1/+1 until end of turn and you gain 1 life. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility( - new BoostSourceEffect(1, 1, Duration.EndOfTurn) - ), - new PermanentsOnTheBattlefieldCondition( - StaticFilters.FILTER_CONTROLLED_CREATURES, - ComparisonType.MORE_THAN, 2 - ), - "At the beginning of combat on your turn, " - + "if you control three or more creatures, " - + "{this} gets +1/+1 until end of turn and you gain 1 life." - ); - ability.addEffect(new GainLifeEffect(1)); + Ability ability = new BeginningOfCombatTriggeredAbility( + new BoostSourceEffect(1, 1, Duration.EndOfTurn) + ).withInterveningIf(condition); + ability.addEffect(new GainLifeEffect(1).concatBy("and")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/l/LesserWerewolf.java b/Mage.Sets/src/mage/cards/l/LesserWerewolf.java index 25f4f90f75f..c617a9ae948 100644 --- a/Mage.Sets/src/mage/cards/l/LesserWerewolf.java +++ b/Mage.Sets/src/mage/cards/l/LesserWerewolf.java @@ -2,9 +2,10 @@ package mage.cards.l; import mage.MageInt; import mage.abilities.Ability; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; @@ -34,6 +35,8 @@ public final class LesserWerewolf extends CardImpl { filter.add(BlockingOrBlockedBySourcePredicate.EITHER); } + private static final Condition condition = new IsStepCondition(PhaseStep.DECLARE_BLOCKERS, false); + public LesserWerewolf(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); this.subtype.add(SubType.WEREWOLF); @@ -41,9 +44,8 @@ public final class LesserWerewolf extends CardImpl { this.toughness = new MageInt(4); // {B}: If Lesser Werewolf’s power is 1 or more, it gets -1/-0 until end of turn and put a -0/-1 counter on target creature blocking or blocked by Lesser Werewolf. Activate this ability only during the declare blockers step. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, new LesserWerewolfEffect(), new ManaCostsImpl<>("{B}"), - new IsStepCondition(PhaseStep.DECLARE_BLOCKERS, false) + Ability ability = new ActivateIfConditionActivatedAbility( + new LesserWerewolfEffect(), new ManaCostsImpl<>("{B}"), condition ); ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/l/LiberatedDwarf.java b/Mage.Sets/src/mage/cards/l/LiberatedDwarf.java index e4ad8a4f955..ad4f14a6a58 100644 --- a/Mage.Sets/src/mage/cards/l/LiberatedDwarf.java +++ b/Mage.Sets/src/mage/cards/l/LiberatedDwarf.java @@ -20,6 +20,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -47,7 +48,7 @@ public final class LiberatedDwarf extends CardImpl { effect = new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn); effect.setText("and gains first strike until end of turn"); ability.addEffect(effect); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/l/LiberatorUrzasBattlethopter.java b/Mage.Sets/src/mage/cards/l/LiberatorUrzasBattlethopter.java index bca173b619d..1fdd65cf3dd 100644 --- a/Mage.Sets/src/mage/cards/l/LiberatorUrzasBattlethopter.java +++ b/Mage.Sets/src/mage/cards/l/LiberatorUrzasBattlethopter.java @@ -1,12 +1,13 @@ package mage.cards.l; import mage.MageInt; +import mage.Mana; import mage.abilities.Ability; +import mage.abilities.AbilityImpl; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.Effects; +import mage.abilities.costs.mana.ManaCost; import mage.abilities.effects.common.continuous.CastAsThoughItHadFlashAllEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.FlashAbility; @@ -22,7 +23,7 @@ import mage.filter.predicate.mageobject.ColorlessPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.stack.Spell; -import mage.watchers.common.ManaPaidSourceWatcher; +import mage.util.CardUtil; import java.util.UUID; @@ -60,15 +61,10 @@ public final class LiberatorUrzasBattlethopter extends CardImpl { // Whenever you cast a spell, if the amount of mana spent to cast that spell is greater // than Liberator, Urza's Battlethopter's power, put a +1/+1 counter on Liberator. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new SpellCastControllerTriggeredAbility( - new AddCountersSourceEffect(CounterType.P1P1.createInstance()), - StaticFilters.FILTER_SPELL_A, false, SetTargetPointer.SPELL - ), - LiberatorUrzasBattlethopterCondition.instance, - "Whenever you cast a spell, if the amount of mana spent to cast " - + "that spell is greater than {this}'s power, put a +1/+1 counter on {this}" - )); + this.addAbility(new SpellCastControllerTriggeredAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance()), + StaticFilters.FILTER_SPELL_A, false, SetTargetPointer.SPELL + ).withInterveningIf(LiberatorUrzasBattlethopterCondition.instance)); } private LiberatorUrzasBattlethopter(final LiberatorUrzasBattlethopter card) { @@ -87,17 +83,19 @@ enum LiberatorUrzasBattlethopterCondition implements Condition { @Override public boolean apply(Game game, Ability source) { Permanent permanent = source.getSourcePermanentIfItStillExists(game); - if (permanent == null) { - return false; - } - Effects effects = source.getEffects(); - if (effects.isEmpty()) { - return false; - } - Object spell = effects.get(0).getValue("spellCast"); - if (spell instanceof Spell) { - return (ManaPaidSourceWatcher.getTotalPaid(((Spell) spell).getId(), game) > permanent.getPower().getValue()); - } - return false; + return permanent != null + && CardUtil + .getEffectValueFromAbility(source, "spellCast", Spell.class) + .map(Spell::getSpellAbility) + .map(AbilityImpl::getManaCostsToPay) + .map(ManaCost::getUsedManaToPay) + .map(Mana::count) + .filter(x -> x > permanent.getPower().getValue()) + .isPresent(); + } + + @Override + public String toString() { + return "the amount of mana spent to cast that spell is greater than {this}'s power"; } } diff --git a/Mage.Sets/src/mage/cards/l/LibraryOfAlexandria.java b/Mage.Sets/src/mage/cards/l/LibraryOfAlexandria.java index 18813e48d48..5e8b3c6b060 100644 --- a/Mage.Sets/src/mage/cards/l/LibraryOfAlexandria.java +++ b/Mage.Sets/src/mage/cards/l/LibraryOfAlexandria.java @@ -1,35 +1,35 @@ - package mage.cards.l; -import java.util.UUID; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInHandCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.mana.ColorlessManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; -import mage.constants.Zone; + +import java.util.UUID; /** * @author LevelX2 */ public final class LibraryOfAlexandria extends CardImpl { + private static final Condition condition = new CardsInHandCondition(ComparisonType.EQUAL_TO, 7); + public LibraryOfAlexandria(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); // {tap}: Add {C}. this.addAbility(new ColorlessManaAbility()); + // {tap}: Draw a card. Activate this ability only if you have exactly seven cards in hand. - this.addAbility(new ConditionalActivatedAbility( - Zone.BATTLEFIELD, - new DrawCardSourceControllerEffect(1), - new TapSourceCost(), - new CardsInHandCondition(ComparisonType.EQUAL_TO, 7), - "")); + this.addAbility(new ActivateIfConditionActivatedAbility( + new DrawCardSourceControllerEffect(1), new TapSourceCost(), condition + )); } private LibraryOfAlexandria(final LibraryOfAlexandria card) { diff --git a/Mage.Sets/src/mage/cards/l/Lictor.java b/Mage.Sets/src/mage/cards/l/Lictor.java index 2ae66495dfb..6a066125e72 100644 --- a/Mage.Sets/src/mage/cards/l/Lictor.java +++ b/Mage.Sets/src/mage/cards/l/Lictor.java @@ -4,7 +4,6 @@ import mage.MageInt; 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.abilities.keyword.FlashAbility; import mage.cards.CardImpl; @@ -12,7 +11,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.game.Game; -import mage.game.permanent.token.TyranidToken; import mage.game.permanent.token.TyranidWarriorToken; import mage.watchers.common.CreatureEnteredControllerWatcher; @@ -34,12 +32,8 @@ public final class Lictor extends CardImpl { this.addAbility(FlashAbility.getInstance()); // Pheromone Trail -- When Lictor enters the battlefield, if a creature entered the battlefield under an opponent's control this turn, create a 3/3 green Tyranid Warrior creature token with trample. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new TyranidWarriorToken())), - LictorCondition.instance, "When {this} enters, " + - "if a creature entered the battlefield under an opponent's control this turn, " + - "create a 3/3 green Tyranid Warrior creature token with trample." - ).withFlavorWord("Pheromone Trail"), new CreatureEnteredControllerWatcher()); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new TyranidWarriorToken())) + .withInterveningIf(LictorCondition.instance).withFlavorWord("Pheromone Trail"), new CreatureEnteredControllerWatcher()); } private Lictor(final Lictor card) { @@ -62,4 +56,9 @@ enum LictorCondition implements Condition { .stream() .anyMatch(uuid -> CreatureEnteredControllerWatcher.enteredCreatureForPlayer(uuid, game)); } + + @Override + public String toString() { + return "a creature entered the battlefield under an opponent's control this turn"; + } } diff --git a/Mage.Sets/src/mage/cards/l/LifeBurst.java b/Mage.Sets/src/mage/cards/l/LifeBurst.java index 8593838ee91..d6433150126 100644 --- a/Mage.Sets/src/mage/cards/l/LifeBurst.java +++ b/Mage.Sets/src/mage/cards/l/LifeBurst.java @@ -1,7 +1,6 @@ package mage.cards.l; -import java.util.UUID; import mage.abilities.dynamicvalue.MultipliedValue; import mage.abilities.dynamicvalue.common.CardsInAllGraveyardsCount; import mage.abilities.effects.Effect; @@ -13,12 +12,13 @@ import mage.filter.FilterCard; import mage.filter.predicate.mageobject.NamePredicate; import mage.target.TargetPlayer; +import java.util.UUID; + /** - * * @author escplan9 (Derek Monturo - dmontur1 at gmail dot com) */ public final class LifeBurst extends CardImpl { - + private static final FilterCard filter = new FilterCard("card named Life Burst"); static { @@ -26,12 +26,12 @@ public final class LifeBurst extends CardImpl { } public LifeBurst(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}"); // Target player gains 4 life, then gains 4 life for each card named Life Burst in each graveyard. this.getSpellAbility().addEffect(new GainLifeTargetEffect(4)); Effect effect = new GainLifeTargetEffect(new MultipliedValue(new CardsInAllGraveyardsCount(filter), 4)); - effect.setText(", then gains 4 life for each card named {this} in each graveyard"); + effect.setText(", then gains 4 life for each card named Life Burst in each graveyard"); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetPlayer()); } diff --git a/Mage.Sets/src/mage/cards/l/LifeChisel.java b/Mage.Sets/src/mage/cards/l/LifeChisel.java index 062f2f2ac2a..5156d828b3a 100644 --- a/Mage.Sets/src/mage/cards/l/LifeChisel.java +++ b/Mage.Sets/src/mage/cards/l/LifeChisel.java @@ -1,25 +1,18 @@ - package mage.cards.l; -import java.util.UUID; -import mage.abilities.Ability; import mage.abilities.condition.common.IsStepCondition; -import mage.abilities.costs.Cost; import mage.abilities.costs.common.SacrificeTargetCost; -import mage.abilities.decorator.ConditionalActivatedAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.common.ActivateIfConditionActivatedAbility; +import mage.abilities.dynamicvalue.common.SacrificeCostCreaturesToughness; +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.PhaseStep; -import mage.constants.Zone; import mage.filter.StaticFilters; -import mage.game.Game; -import mage.players.Player; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class LifeChisel extends CardImpl { @@ -28,13 +21,12 @@ public final class LifeChisel extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); // Sacrifice a creature: You gain life equal to the sacrificed creature's toughness. Activate this ability only during your upkeep. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, - new LifeChiselEffect(), + this.addAbility(new ActivateIfConditionActivatedAbility( + new GainLifeEffect(SacrificeCostCreaturesToughness.instance) + .setText("you gain life equal to the sacrificed creature's toughness"), new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_CREATURE), - new IsStepCondition(PhaseStep.UPKEEP) - ); - this.addAbility(ability); + IsStepCondition.getMyUpkeep() + )); } private LifeChisel(final LifeChisel card) { @@ -46,37 +38,3 @@ public final class LifeChisel extends CardImpl { return new LifeChisel(this); } } - -class LifeChiselEffect extends OneShotEffect { - - LifeChiselEffect() { - super(Outcome.GainLife); - this.staticText = "You gain life equal to the sacrificed creature's toughness"; - } - - private LifeChiselEffect(final LifeChiselEffect effect) { - super(effect); - } - - @Override - public LifeChiselEffect copy() { - return new LifeChiselEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - for (Cost cost : source.getCosts()) { - if (cost instanceof SacrificeTargetCost) { - int amount = ((SacrificeTargetCost) cost).getPermanents().get(0).getToughness().getValue(); - if (amount > 0) { - controller.gainLife(amount, game, source); - } - } - } - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/l/LifeFindsAWay.java b/Mage.Sets/src/mage/cards/l/LifeFindsAWay.java index fef2799b80c..bae0ebab0be 100644 --- a/Mage.Sets/src/mage/cards/l/LifeFindsAWay.java +++ b/Mage.Sets/src/mage/cards/l/LifeFindsAWay.java @@ -1,25 +1,24 @@ package mage.cards.l; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.common.PopulateEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.FilterPermanent; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; import mage.filter.predicate.permanent.TokenPredicate; import java.util.UUID; /** - * * @author notgreat */ public final class LifeFindsAWay extends CardImpl { - private static final FilterPermanent filter = new FilterCreaturePermanent("nontoken creature with power 4 or greater"); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("nontoken creature you control with power 4 or greater"); static { filter.add(TokenPredicate.FALSE); @@ -30,7 +29,7 @@ public final class LifeFindsAWay extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); // Whenever a nontoken creature with power 4 or greater you control enters, populate. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility(new PopulateEffect(), filter)); + this.addAbility(new EntersBattlefieldAllTriggeredAbility(new PopulateEffect(), filter)); } private LifeFindsAWay(final LifeFindsAWay card) { diff --git a/Mage.Sets/src/mage/cards/l/LifeMatrix.java b/Mage.Sets/src/mage/cards/l/LifeMatrix.java index 803cc8a4f74..0be55f638af 100644 --- a/Mage.Sets/src/mage/cards/l/LifeMatrix.java +++ b/Mage.Sets/src/mage/cards/l/LifeMatrix.java @@ -6,7 +6,7 @@ import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.RemoveCountersSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.RegenerateSourceEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; @@ -14,8 +14,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.PhaseStep; -import mage.constants.Zone; import mage.counters.CounterType; import mage.target.common.TargetCreaturePermanent; @@ -32,17 +30,16 @@ public final class LifeMatrix extends CardImpl { // {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, + Ability ability = new ActivateIfConditionActivatedAbility( new AddCountersTargetEffect(CounterType.MATRIX.createInstance()), - new GenericManaCost(4), - new IsStepCondition(PhaseStep.UPKEEP), "{4}, {T}: Put a matrix counter on target creature and " - + "that creature gains \"Remove a matrix counter from this creature: " - + "Regenerate this creature.\" Activate only during your upkeep."); - Ability ability2 = new SimpleActivatedAbility( - new RegenerateSourceEffect(), - new RemoveCountersSourceCost(CounterType.MATRIX.createInstance())); - ability.addEffect(new GainAbilityTargetEffect(ability2, Duration.Custom)); + new GenericManaCost(4), IsStepCondition.getMyUpkeep() + ); + ability.addEffect(new GainAbilityTargetEffect( + new SimpleActivatedAbility( + new RegenerateSourceEffect(), + new RemoveCountersSourceCost(CounterType.MATRIX.createInstance()) + ), Duration.Custom + ).setText("and that creature gains \"Remove a matrix counter from this creature: Regenerate this creature.\"")); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/l/Lifeline.java b/Mage.Sets/src/mage/cards/l/Lifeline.java index cbdfb9b0447..ae0768b795b 100644 --- a/Mage.Sets/src/mage/cards/l/Lifeline.java +++ b/Mage.Sets/src/mage/cards/l/Lifeline.java @@ -3,16 +3,19 @@ package mage.cards.l; import mage.abilities.Ability; import mage.abilities.common.DiesCreatureTriggeredAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect; 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.filter.StaticFilters; +import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.target.targetpointer.FixedTarget; @@ -23,17 +26,18 @@ import java.util.UUID; */ public final class Lifeline extends CardImpl { + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterCreaturePermanent("another creature is on the battlefield"), false + ); public Lifeline(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}"); - // Whenever a creature dies, if another creature is on the battlefield, return the first card to the battlefield under its owner's control at the beginning of the next end step. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new DiesCreatureTriggeredAbility(new LifelineEffect(), false, StaticFilters.FILTER_PERMANENT_CREATURE, true), - new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_PERMANENT_CREATURE, false), - "Whenever a creature dies, if another creature is on the battlefield, return the first card to the battlefield under its owner's control at the beginning of the next end step."); - this.addAbility(ability); + this.addAbility(new DiesCreatureTriggeredAbility( + new LifelineEffect(), false, + StaticFilters.FILTER_PERMANENT_A_CREATURE, true + ).withInterveningIf(condition)); } private Lifeline(final Lifeline card) { @@ -50,7 +54,7 @@ class LifelineEffect extends OneShotEffect { LifelineEffect() { super(Outcome.PutCardInPlay); - this.staticText = ""; + this.staticText = "return the first card to the battlefield under its owner's control at the beginning of the next end step"; } private LifelineEffect(final LifelineEffect effect) { diff --git a/Mage.Sets/src/mage/cards/l/Lightbringer.java b/Mage.Sets/src/mage/cards/l/Lightbringer.java index 434c8d603ba..39a10dd475e 100644 --- a/Mage.Sets/src/mage/cards/l/Lightbringer.java +++ b/Mage.Sets/src/mage/cards/l/Lightbringer.java @@ -16,6 +16,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class Lightbringer extends CardImpl { // {tap}, Sacrifice Lightbringer: Exile target black creature. Ability ability = new SimpleActivatedAbility(new ExileTargetEffect(), new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/l/LightningPhoenix.java b/Mage.Sets/src/mage/cards/l/LightningPhoenix.java index 8a849151d89..efc41e9c2e0 100644 --- a/Mage.Sets/src/mage/cards/l/LightningPhoenix.java +++ b/Mage.Sets/src/mage/cards/l/LightningPhoenix.java @@ -2,15 +2,14 @@ package mage.cards.l; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.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.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -44,15 +43,11 @@ public final class LightningPhoenix extends CardImpl { 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, - TargetController.YOU, new DoIfCostPaid( - new ReturnSourceFromGraveyardToBattlefieldEffect(), new ManaCostsImpl<>("{R}") - ), false, null - ), 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." + this.addAbility(new BeginningOfEndStepTriggeredAbility( + Zone.GRAVEYARD, TargetController.YOU, + new DoIfCostPaid( + new ReturnSourceFromGraveyardToBattlefieldEffect(), new ManaCostsImpl<>("{R}") + ), false, LightningPhoenixCondition.instance ), new LightningPhoenixWatcher()); } @@ -74,6 +69,11 @@ enum LightningPhoenixCondition implements Condition { LightningPhoenixWatcher watcher = game.getState().getWatcher(LightningPhoenixWatcher.class); return watcher != null && watcher.checkDamage(source.getControllerId()); } + + @Override + public String toString() { + return "an opponent was dealt 3 or more damage this turn"; + } } class LightningPhoenixWatcher extends Watcher { diff --git a/Mage.Sets/src/mage/cards/l/LightningSerpent.java b/Mage.Sets/src/mage/cards/l/LightningSerpent.java index 584890d3cd9..70c8791ea22 100644 --- a/Mage.Sets/src/mage/cards/l/LightningSerpent.java +++ b/Mage.Sets/src/mage/cards/l/LightningSerpent.java @@ -1,23 +1,22 @@ - package mage.cards.l; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldAbility; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; 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.game.events.GameEvent; + +import java.util.UUID; /** - * * @author LoneFox */ public final class LightningSerpent extends CardImpl { @@ -31,12 +30,17 @@ public final class LightningSerpent extends CardImpl { // Trample this.addAbility(TrampleAbility.getInstance()); + // Haste this.addAbility(HasteAbility.getInstance()); + // Lightning Serpent enters the battlefield with X +1/+0 counters on it. this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.P1P0.createInstance()))); + // At the beginning of the end step, sacrifice Lightning Serpent. - this.addAbility(new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new SacrificeSourceEffect())); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.NEXT, new SacrificeSourceEffect(), false + )); } private LightningSerpent(final LightningSerpent card) { diff --git a/Mage.Sets/src/mage/cards/l/LightningSkelemental.java b/Mage.Sets/src/mage/cards/l/LightningSkelemental.java index 0e5a681f693..3d0ce2b3f90 100644 --- a/Mage.Sets/src/mage/cards/l/LightningSkelemental.java +++ b/Mage.Sets/src/mage/cards/l/LightningSkelemental.java @@ -2,16 +2,16 @@ package mage.cards.l; import mage.MageInt; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.game.events.GameEvent; +import mage.constants.TargetController; import java.util.UUID; @@ -40,9 +40,8 @@ public final class LightningSkelemental extends CardImpl { )); // At the beginning of the end step, sacrifice Lightning Skelemental. - this.addAbility(new OnEventTriggeredAbility( - GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", - true, new SacrificeSourceEffect() + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.NEXT, new SacrificeSourceEffect(), false )); } diff --git a/Mage.Sets/src/mage/cards/l/LilianaDeathWielder.java b/Mage.Sets/src/mage/cards/l/LilianaDeathWielder.java index e5a56b63e23..88d6a0945fa 100644 --- a/Mage.Sets/src/mage/cards/l/LilianaDeathWielder.java +++ b/Mage.Sets/src/mage/cards/l/LilianaDeathWielder.java @@ -12,6 +12,7 @@ import mage.constants.SuperType; import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -42,7 +43,7 @@ public final class LilianaDeathWielder extends CardImpl { // -3: Destroy target creature with a -1/-1 counter on it. ability = new LoyaltyAbility(new DestroyTargetEffect(), -3); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // -10: Return all creature cards from your graveyard to the battlefield. diff --git a/Mage.Sets/src/mage/cards/l/LilianaTheNecromancer.java b/Mage.Sets/src/mage/cards/l/LilianaTheNecromancer.java index 10e768d736b..0f941198204 100644 --- a/Mage.Sets/src/mage/cards/l/LilianaTheNecromancer.java +++ b/Mage.Sets/src/mage/cards/l/LilianaTheNecromancer.java @@ -44,7 +44,7 @@ public final class LilianaTheNecromancer extends CardImpl { // −7: Destroy up to two target creatures. Put up to two creature cards from graveyards onto the battlefield under your control. ability = new LoyaltyAbility(new DestroyTargetEffect(), -7); - ability.addTarget(new TargetCreaturePermanent(0, 2, StaticFilters.FILTER_PERMANENT_CREATURES, false)); + ability.addTarget(new TargetCreaturePermanent(0, 2)); ability.addEffect(new LilianaTheNecromancerEffect()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/l/LilianasContract.java b/Mage.Sets/src/mage/cards/l/LilianasContract.java index ef6b3616681..77f572540c3 100644 --- a/Mage.Sets/src/mage/cards/l/LilianasContract.java +++ b/Mage.Sets/src/mage/cards/l/LilianasContract.java @@ -1,16 +1,12 @@ package mage.cards.l; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.LoseLifeSourceControllerEffect; import mage.abilities.effects.common.WinGameSourceControllerEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -18,8 +14,11 @@ import mage.constants.SubType; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class LilianasContract extends CardImpl { @@ -28,25 +27,13 @@ public final class LilianasContract extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}{B}"); // When Liliana's Contract enters the battlefield, you draw four cards and you lose 4 life. - Ability ability = new EntersBattlefieldTriggeredAbility( - new DrawCardSourceControllerEffect(4) - .setText("you draw four cards") - ); - ability.addEffect( - new LoseLifeSourceControllerEffect(4) - .setText("and you lose 4 life") - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(4, true)); + ability.addEffect(new LoseLifeSourceControllerEffect(4).setText("and you lose 4 life")); this.addAbility(ability); // At the beginning of your upkeep, if you control four or more Demons with different names, you win the game. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility( - new WinGameSourceControllerEffect(), false - ), LilianasContractCondition.instance, - "At the beginning of your upkeep, " - + "if you control four or more Demons with different names, " - + "you win the game." - )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect()) + .withInterveningIf(LilianasContractCondition.instance)); } private LilianasContract(final LilianasContract card) { diff --git a/Mage.Sets/src/mage/cards/l/LilianasScrounger.java b/Mage.Sets/src/mage/cards/l/LilianasScrounger.java index 3def5d14982..30825b347fe 100644 --- a/Mage.Sets/src/mage/cards/l/LilianasScrounger.java +++ b/Mage.Sets/src/mage/cards/l/LilianasScrounger.java @@ -2,11 +2,10 @@ package mage.cards.l; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.common.MorbidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.hint.common.MorbidHint; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -37,10 +36,9 @@ public final class LilianasScrounger extends CardImpl { 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( - TargetController.ANY, new LilianasScroungerEffect(), 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." + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.ANY, new LilianasScroungerEffect(), + false, MorbidCondition.instance ).addHint(MorbidHint.instance)); } @@ -61,6 +59,7 @@ class LilianasScroungerEffect extends OneShotEffect { LilianasScroungerEffect() { super(Outcome.Benefit); + staticText = "you may put a loyalty counter on a Liliana planeswalker you control"; } private LilianasScroungerEffect(final LilianasScroungerEffect effect) { diff --git a/Mage.Sets/src/mage/cards/l/LilysplashMentor.java b/Mage.Sets/src/mage/cards/l/LilysplashMentor.java index 68e008a0fa7..1a442a90862 100644 --- a/Mage.Sets/src/mage/cards/l/LilysplashMentor.java +++ b/Mage.Sets/src/mage/cards/l/LilysplashMentor.java @@ -19,20 +19,19 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import mage.util.CardUtil; import java.util.UUID; /** - * * @author notgreat */ public final class LilysplashMentor extends CardImpl { public LilysplashMentor(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{U}"); - + this.subtype.add(SubType.FROG); this.subtype.add(SubType.DRUID); this.power = new MageInt(4); @@ -43,7 +42,7 @@ public final class LilysplashMentor extends CardImpl { // {1}{G}{U}: Exile another target creature you control, then return it to the battlefield under its owner's control with a +1/+1 counter on it. Activate only as a sorcery. Ability ability = new ActivateAsSorceryActivatedAbility(new LilysplashMentorEffect(), new ManaCostsImpl<>("{1}{G}{U}")); - ability.addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); this.addAbility(ability); } @@ -56,6 +55,7 @@ public final class LilysplashMentor extends CardImpl { return new LilysplashMentor(this); } } + //Copied from Planar Incision class LilysplashMentorEffect extends OneShotEffect { diff --git a/Mage.Sets/src/mage/cards/l/LinvalaShieldOfSeaGate.java b/Mage.Sets/src/mage/cards/l/LinvalaShieldOfSeaGate.java index dafe59292ad..3b5928755c2 100644 --- a/Mage.Sets/src/mage/cards/l/LinvalaShieldOfSeaGate.java +++ b/Mage.Sets/src/mage/cards/l/LinvalaShieldOfSeaGate.java @@ -2,11 +2,9 @@ package mage.cards.l; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.FullPartyCondition; import mage.abilities.costs.common.SacrificeSourceCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.RestrictionEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; @@ -14,6 +12,7 @@ import mage.abilities.hint.common.PartyCountHint; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.HexproofAbility; import mage.abilities.keyword.IndestructibleAbility; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -52,13 +51,8 @@ public final class LinvalaShieldOfSeaGate extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // At the beginning of combat on your turn, if you have a full party, choose target nonland permanent an opponent controls. Until your next turn, it can't attack or block, and its activated abilities can't be activated. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility( - new LinvalaShieldOfSeaGateRestrictionEffect() - ), FullPartyCondition.instance, "At the beginning of combat on your turn, " + - "if you have a full party, choose target nonland permanent an opponent controls. " + - "Until your next turn, it can't attack or block, and its activated abilities can't be activated." - ); + Ability ability = new BeginningOfCombatTriggeredAbility(new LinvalaShieldOfSeaGateRestrictionEffect()) + .withInterveningIf(FullPartyCondition.instance); ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability.addHint(PartyCountHint.instance)); @@ -80,6 +74,8 @@ class LinvalaShieldOfSeaGateRestrictionEffect extends RestrictionEffect { LinvalaShieldOfSeaGateRestrictionEffect() { super(Duration.UntilYourNextTurn, Outcome.UnboostCreature); + staticText = "choose target nonland permanent an opponent controls. Until your next turn, " + + "it can't attack or block, and its activated abilities can't be activated"; } private LinvalaShieldOfSeaGateRestrictionEffect(final LinvalaShieldOfSeaGateRestrictionEffect effect) { diff --git a/Mage.Sets/src/mage/cards/l/LinvalaThePreserver.java b/Mage.Sets/src/mage/cards/l/LinvalaThePreserver.java index b63ee29897c..ec96f5c4b89 100644 --- a/Mage.Sets/src/mage/cards/l/LinvalaThePreserver.java +++ b/Mage.Sets/src/mage/cards/l/LinvalaThePreserver.java @@ -1,12 +1,10 @@ - package mage.cards.l; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.OpponentControlsMoreCondition; import mage.abilities.condition.common.OpponentHasMoreLifeCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.keyword.FlyingAbility; @@ -15,15 +13,18 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.StaticFilters; import mage.game.permanent.token.Angel33Token; +import java.util.UUID; + /** - * * @author fireshoes */ public final class LinvalaThePreserver extends CardImpl { + private static final Condition condition = new OpponentControlsMoreCondition(StaticFilters.FILTER_PERMANENT_CREATURES); + public LinvalaThePreserver(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}{W}"); this.supertype.add(SuperType.LEGENDARY); @@ -35,14 +36,12 @@ public final class LinvalaThePreserver extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When Linvala, the Preserver enters the battlefield, if an opponent has more life than you, you gain 5 life. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(5), false), - OpponentHasMoreLifeCondition.instance, - "When {this} enters, if an opponent has more life than you, you gain 5 life.")); + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(5)) + .withInterveningIf(OpponentHasMoreLifeCondition.instance)); // When Linvala enters the battlefield, if an opponent controls more creatures than you, create a 3/3 white Angel creature token with flying. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new Angel33Token()), false), - new OpponentControlsMoreCondition(new FilterCreaturePermanent()), - "When {this} enters, if an opponent controls more creatures than you, create a 3/3 white Angel creature token with flying.")); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new Angel33Token())) + .withInterveningIf(condition)); } private LinvalaThePreserver(final LinvalaThePreserver card) { diff --git a/Mage.Sets/src/mage/cards/l/LittjaraKinseekers.java b/Mage.Sets/src/mage/cards/l/LittjaraKinseekers.java index 285066909de..cd8f520cf49 100644 --- a/Mage.Sets/src/mage/cards/l/LittjaraKinseekers.java +++ b/Mage.Sets/src/mage/cards/l/LittjaraKinseekers.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.GreatestSharedCreatureTypeCount; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.keyword.ScryEffect; @@ -34,14 +33,9 @@ public final class LittjaraKinseekers extends CardImpl { this.addAbility(new ChangelingAbility()); // When Littjara Kinseekers enters the battlefield, if you control three or more creatures that share a creature type, put a +1/+1 counter on Littjara Kinseekers, then scry 1. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility( - new AddCountersSourceEffect(CounterType.P1P1.createInstance()) - ), LittjaraKinseekersCondition.instance, "When {this} enters, " + - "if you control three or more creatures that share a creature type, " + - "put a +1/+1 counter on {this}, then scry 1." - ); - ability.addEffect(new ScryEffect(1)); + Ability ability = new EntersBattlefieldTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance())) + .withInterveningIf(LittjaraKinseekersCondition.instance); + ability.addEffect(new ScryEffect(1).concatBy(", then")); this.addAbility(ability.addHint(GreatestSharedCreatureTypeCount.getHint())); } @@ -62,4 +56,9 @@ enum LittjaraKinseekersCondition implements Condition { public boolean apply(Game game, Ability source) { return GreatestSharedCreatureTypeCount.instance.calculate(game, source, null) >= 3; } + + @Override + public String toString() { + return "you control three or more creatures that share a creature type"; + } } diff --git a/Mage.Sets/src/mage/cards/l/LivingTotem.java b/Mage.Sets/src/mage/cards/l/LivingTotem.java index 7722b0441d2..2590c3131b8 100644 --- a/Mage.Sets/src/mage/cards/l/LivingTotem.java +++ b/Mage.Sets/src/mage/cards/l/LivingTotem.java @@ -13,8 +13,11 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.counters.CounterType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * * @author LevelX2 @@ -33,7 +36,7 @@ public final class LivingTotem extends CardImpl { this.addAbility(new ConvokeAbility()); // When Living Totem enters the battlefield, you may put a +1/+1 counter on another target creature. Ability ability = new EntersBattlefieldTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), true); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/l/LlanowarAugur.java b/Mage.Sets/src/mage/cards/l/LlanowarAugur.java index 6514434c983..f4d496e7692 100644 --- a/Mage.Sets/src/mage/cards/l/LlanowarAugur.java +++ b/Mage.Sets/src/mage/cards/l/LlanowarAugur.java @@ -1,33 +1,29 @@ - package mage.cards.l; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.SacrificeSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; -import mage.abilities.effects.Effect; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; 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.PhaseStep; -import mage.constants.Zone; +import mage.constants.SubType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author North */ public final class LlanowarAugur extends CardImpl { public LlanowarAugur(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}"); this.subtype.add(SubType.ELF); this.subtype.add(SubType.SHAMAN); @@ -36,15 +32,14 @@ public final class LlanowarAugur extends CardImpl { // Sacrifice Llanowar Augur: Target creature gets +3/+3 and gains trample until end of turn. // Activate this ability only during your upkeep. - Effect effect = new BoostTargetEffect(3, 3, Duration.EndOfTurn); - effect.setText("Target creature gets +3/+3"); - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, - effect, - new SacrificeSourceCost(), - new IsStepCondition(PhaseStep.UPKEEP) + Ability ability = new ActivateIfConditionActivatedAbility( + new BoostTargetEffect(3, 3).setText("Target creature gets +3/+3"), + new SacrificeSourceCost(), IsStepCondition.getMyUpkeep() ); - effect = new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, "and gains trample until end of turn"); - ability.addEffect(effect); + ability.addEffect(new GainAbilityTargetEffect( + TrampleAbility.getInstance(), Duration.EndOfTurn, + "and gains trample until end of turn" + )); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/l/LlanowarBehemoth.java b/Mage.Sets/src/mage/cards/l/LlanowarBehemoth.java index c5264808242..f22a89318d5 100644 --- a/Mage.Sets/src/mage/cards/l/LlanowarBehemoth.java +++ b/Mage.Sets/src/mage/cards/l/LlanowarBehemoth.java @@ -1,7 +1,5 @@ - package mage.cards.l; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapTargetCost; @@ -9,33 +7,29 @@ import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.constants.SubType; +import mage.filter.StaticFilters; + +import java.util.UUID; /** - * * @author Plopman */ public final class LlanowarBehemoth extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); - static { - filter.add(TappedPredicate.UNTAPPED); - } - public LlanowarBehemoth(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}"); this.subtype.add(SubType.ELEMENTAL); this.power = new MageInt(4); this.toughness = new MageInt(4); // Tap an untapped creature you control: Llanowar Behemoth gets +1/+1 until end of turn. - this.addAbility(new SimpleActivatedAbility(new BoostSourceEffect(1, 1, Duration.EndOfTurn), new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, false)))); + this.addAbility(new SimpleActivatedAbility( + new BoostSourceEffect(1, 1, Duration.EndOfTurn), + new TapTargetCost(StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURE) + )); } private LlanowarBehemoth(final LlanowarBehemoth card) { diff --git a/Mage.Sets/src/mage/cards/l/LoamDryad.java b/Mage.Sets/src/mage/cards/l/LoamDryad.java index 510ba342a9e..d2859b1c33b 100644 --- a/Mage.Sets/src/mage/cards/l/LoamDryad.java +++ b/Mage.Sets/src/mage/cards/l/LoamDryad.java @@ -1,7 +1,6 @@ package mage.cards.l; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.costs.common.TapTargetCost; @@ -10,24 +9,17 @@ 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.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.filter.StaticFilters; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class LoamDryad extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); - - static { - filter.add(TappedPredicate.UNTAPPED); - } - public LoamDryad(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}"); this.subtype.add(SubType.DRYAD); this.subtype.add(SubType.HORROR); this.power = new MageInt(1); @@ -35,7 +27,7 @@ public final class LoamDryad extends CardImpl { // {T}, Tap an untapped creature you control: Add one mana of any color. Ability ability = new AnyColorManaAbility(); - ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, false))); + ability.addCost(new TapTargetCost(StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURES)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/l/LoanShark.java b/Mage.Sets/src/mage/cards/l/LoanShark.java index ed4334b58a6..0165297bc9f 100644 --- a/Mage.Sets/src/mage/cards/l/LoanShark.java +++ b/Mage.Sets/src/mage/cards/l/LoanShark.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.keyword.PlotAbility; import mage.abilities.keyword.StormAbility; @@ -31,11 +30,8 @@ public final class LoanShark extends CardImpl { this.toughness = new MageInt(4); // When Loan Shark enters the battlefield, if you've cast two or more spells this turn, draw a card. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)), - LoanSharkCondition.instance, "When {this} enters, " + - "if you've cast two or more spells this turn, draw a card." - ).addHint(StormAbility.getHint())); + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)) + .withInterveningIf(LoanSharkCondition.instance).addHint(StormAbility.getHint())); // Plot {3}{U} this.addAbility(new PlotAbility("{3}{U}")); @@ -61,4 +57,9 @@ enum LoanSharkCondition implements Condition { .getWatcher(SpellsCastWatcher.class) .getCount(source.getControllerId()) >= 2; } + + @Override + public String toString() { + return "you've cast two or more spells this turn"; + } } diff --git a/Mage.Sets/src/mage/cards/l/LobeLobber.java b/Mage.Sets/src/mage/cards/l/LobeLobber.java index 6c975bdff91..a7317f1d778 100644 --- a/Mage.Sets/src/mage/cards/l/LobeLobber.java +++ b/Mage.Sets/src/mage/cards/l/LobeLobber.java @@ -5,18 +5,20 @@ 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.Effect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.UntapSourceEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.keyword.EquipAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.AttachmentType; +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.TargetPlayer; +import mage.target.common.TargetPlayerOrPlaneswalker; import java.util.UUID; @@ -29,10 +31,10 @@ public final class LobeLobber extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); this.subtype.add(SubType.EQUIPMENT); - // Equipped creature has "T: This creature deals 1 damage to target player. Roll a six-sided die. On a 5 or higher, untap it." - Effect effect = new LobeLobberEffect(); - SimpleActivatedAbility ability = new SimpleActivatedAbility(effect, new TapSourceCost()); - ability.addTarget(new TargetPlayer()); + // Equipped creature has "T: This creature deals 1 damage to target player or planeswalker. Roll a six-sided die. On a 5 or higher, untap it." + Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new TapSourceCost()); + ability.addTarget(new TargetPlayerOrPlaneswalker()); + ability.addEffect(new LobeLobberEffect()); this.addAbility(new SimpleStaticAbility(new GainAbilityAttachedEffect(ability, AttachmentType.EQUIPMENT))); // Equip 2 @@ -53,7 +55,7 @@ class LobeLobberEffect extends OneShotEffect { LobeLobberEffect() { super(Outcome.Benefit); - this.staticText = "This creature deals 1 damage to target player. Roll a six-sided die. On a 5 or higher, untap it"; + this.staticText = "Roll a six-sided die. On a 5 or higher, untap it"; } private LobeLobberEffect(final LobeLobberEffect effect) { @@ -68,18 +70,13 @@ class LobeLobberEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - Permanent equipment = game.getPermanent(source.getSourceId()); - Player player = game.getPlayer(source.getFirstTarget()); - - if (controller != null && equipment != null && player != null) { - player.damage(1, source.getSourceId(), source, game); + if (controller != null) { int amount = controller.rollDice(outcome, source, game, 6); if (amount >= 5) { new UntapSourceEffect().apply(game, source); } return true; } - return false; } } diff --git a/Mage.Sets/src/mage/cards/l/LockedInTheCemetery.java b/Mage.Sets/src/mage/cards/l/LockedInTheCemetery.java index dc64fd80d07..219754fee65 100644 --- a/Mage.Sets/src/mage/cards/l/LockedInTheCemetery.java +++ b/Mage.Sets/src/mage/cards/l/LockedInTheCemetery.java @@ -1,11 +1,9 @@ package mage.cards.l; -import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInControllerGraveyardCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.DontUntapInControllersUntapStepEnchantedEffect; import mage.abilities.effects.common.TapEnchantedEffect; @@ -36,15 +34,10 @@ public final class LockedInTheCemetery extends CardImpl { TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // When Locked in the Cemetery enters the battlefield, if there are five or more cards in your graveyard, tap enchanted creature. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new TapEnchantedEffect()), - condition, "When {this} enters, if there are " + - "five or more cards in your graveyard, tap enchanted creature." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new TapEnchantedEffect()).withInterveningIf(condition)); // Enchanted creature doesn't untap during its controller's untap step. this.addAbility(new SimpleStaticAbility(new DontUntapInControllersUntapStepEnchantedEffect())); diff --git a/Mage.Sets/src/mage/cards/l/LoneRevenant.java b/Mage.Sets/src/mage/cards/l/LoneRevenant.java index 3250bcab753..3d35cf453fb 100644 --- a/Mage.Sets/src/mage/cards/l/LoneRevenant.java +++ b/Mage.Sets/src/mage/cards/l/LoneRevenant.java @@ -1,11 +1,9 @@ package mage.cards.l; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; import mage.abilities.keyword.HexproofAbility; import mage.cards.CardImpl; @@ -14,19 +12,27 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.PutCards; import mage.constants.SubType; -import mage.filter.StaticFilters; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.AnotherPredicate; + +import java.util.UUID; /** - * * @author awjackson */ public final class LoneRevenant extends CardImpl { - private static final Condition condition = new PermanentsOnTheBattlefieldCondition( - StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE, ComparisonType.EQUAL_TO, 0); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("you control no other creatures"); + + static { + filter.add(AnotherPredicate.instance); + } + + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.EQUAL_TO, 0); public LoneRevenant(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}"); this.subtype.add(SubType.SPIRIT); this.power = new MageInt(4); @@ -37,14 +43,9 @@ public final class LoneRevenant extends CardImpl { // Whenever Lone Revenant deals combat damage to a player, // if you control no other creatures, look at the top four cards of your library. // Put one of them into your hand and the rest on the bottom of your library in any order. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new DealsCombatDamageToAPlayerTriggeredAbility( - new LookLibraryAndPickControllerEffect(4, 1, PutCards.HAND, PutCards.BOTTOM_ANY), - false - ), condition, "Whenever {this} deals combat damage to a player, " + - "if you control no other creatures, look at the top four cards of your library. " + - "Put one of them into your hand and the rest on the bottom of your library in any order." - )); + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new LookLibraryAndPickControllerEffect( + 4, 1, PutCards.HAND, PutCards.BOTTOM_ANY + )).withInterveningIf(condition)); } private LoneRevenant(final LoneRevenant card) { diff --git a/Mage.Sets/src/mage/cards/l/LoneRider.java b/Mage.Sets/src/mage/cards/l/LoneRider.java index 1d2c7db5c86..4043af88cec 100644 --- a/Mage.Sets/src/mage/cards/l/LoneRider.java +++ b/Mage.Sets/src/mage/cards/l/LoneRider.java @@ -1,16 +1,15 @@ package mage.cards.l; import mage.MageInt; -import mage.abilities.triggers.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.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -26,9 +25,8 @@ import java.util.UUID; */ 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"); + private static final Hint hint = new ConditionHint(condition); public LoneRider(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); @@ -47,11 +45,9 @@ 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()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - TargetController.NEXT, new TransformSourceEffect(), false - ), condition, ruleText - ).addHint(hint), new PlayerGainedLifeWatcher()); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.NEXT, new TransformSourceEffect(), false + ).withInterveningIf(condition).addHint(hint), new PlayerGainedLifeWatcher()); } private LoneRider(final LoneRider card) { diff --git a/Mage.Sets/src/mage/cards/l/LordSkittersBlessing.java b/Mage.Sets/src/mage/cards/l/LordSkittersBlessing.java index dc87fa4fd3a..facdafff66a 100644 --- a/Mage.Sets/src/mage/cards/l/LordSkittersBlessing.java +++ b/Mage.Sets/src/mage/cards/l/LordSkittersBlessing.java @@ -1,16 +1,15 @@ package mage.cards.l; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfDrawTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateRoleAttachedTargetEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.LoseLifeSourceControllerEffect; import mage.abilities.hint.ConditionHint; import mage.abilities.hint.Hint; +import mage.abilities.triggers.BeginningOfDrawTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -28,14 +27,14 @@ import java.util.UUID; */ public final class LordSkittersBlessing extends CardImpl { - private static final FilterPermanent filter = new FilterControlledCreaturePermanent(); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("you control an enchanted creature"); static { filter.add(EnchantedPredicate.instance); } private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); - private static final Hint hint = new ConditionHint(condition, "You control an enchanted creature"); + private static final Hint hint = new ConditionHint(condition); public LordSkittersBlessing(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}"); @@ -46,13 +45,10 @@ public final class LordSkittersBlessing extends CardImpl { this.addAbility(ability); // At the beginning of your draw step, if you control an enchanted creature, you lose 1 life and you draw an additional card. - ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfDrawTriggeredAbility( - TargetController.YOU, new LoseLifeSourceControllerEffect(1), false - ), condition, "At the beginning of your draw step, if you control " + - "an enchanted creature, you lose 1 life and you draw an additional card." - ); - ability.addEffect(new DrawCardSourceControllerEffect(1)); + ability = new BeginningOfDrawTriggeredAbility( + TargetController.YOU, new LoseLifeSourceControllerEffect(1), false + ).withInterveningIf(condition); + ability.addEffect(new DrawCardSourceControllerEffect(1).setText("and you draw an additional card")); this.addAbility(ability.addHint(hint)); } diff --git a/Mage.Sets/src/mage/cards/l/LosheelClockworkScholar.java b/Mage.Sets/src/mage/cards/l/LosheelClockworkScholar.java index de570733b88..3a59a5889e1 100644 --- a/Mage.Sets/src/mage/cards/l/LosheelClockworkScholar.java +++ b/Mage.Sets/src/mage/cards/l/LosheelClockworkScholar.java @@ -1,7 +1,7 @@ package mage.cards.l; import mage.MageInt; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.PreventAllDamageToAllEffect; @@ -22,7 +22,7 @@ public final class LosheelClockworkScholar extends CardImpl { private static final FilterPermanent filter = new FilterArtifactCreaturePermanent("attacking artifact creatures you control"); private static final FilterPermanent filter2 - = new FilterArtifactCreaturePermanent("one or more artifact creatures"); + = new FilterArtifactCreaturePermanent("one or more artifact creatures you control"); static { filter.add(TargetController.YOU.getControllerPredicate()); @@ -45,7 +45,7 @@ public final class LosheelClockworkScholar extends CardImpl { ))); // Whenever one or more artifact creatures enter the battlefield under your control, draw a card. This ability triggers only once each turn. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + this.addAbility(new EntersBattlefieldAllTriggeredAbility( new DrawCardSourceControllerEffect(1), filter2 ).setTriggersLimitEachTurn(1)); } diff --git a/Mage.Sets/src/mage/cards/l/LostMonarchOfIfnir.java b/Mage.Sets/src/mage/cards/l/LostMonarchOfIfnir.java index 68b5d63384f..31bd9c446bd 100644 --- a/Mage.Sets/src/mage/cards/l/LostMonarchOfIfnir.java +++ b/Mage.Sets/src/mage/cards/l/LostMonarchOfIfnir.java @@ -1,26 +1,22 @@ package mage.cards.l; -import java.util.Optional; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.TriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.MillCardsControllerEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.hint.ConditionHint; import mage.abilities.hint.Hint; +import mage.abilities.keyword.AfflictAbility; import mage.abilities.triggers.BeginningOfSecondMainTriggeredAbility; import mage.cards.Card; -import mage.constants.*; -import mage.abilities.keyword.AfflictAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.filter.FilterCard; -import mage.filter.common.FilterCreatureCard; +import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.events.DamagedEvent; @@ -31,17 +27,20 @@ import mage.target.TargetCard; import mage.target.common.TargetCardInYourGraveyard; import mage.watchers.Watcher; +import java.util.Optional; +import java.util.UUID; + /** * @author sobiech */ public final class LostMonarchOfIfnir extends CardImpl { - private final static Hint hint = new ConditionHint(LostMonarchOfIfnirCondition.instance, "Player was dealt combat damage by a Zombie this turn"); - private final static FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.ZOMBIE, "Zombies"); + private final static FilterPermanent filter = new FilterCreaturePermanent(SubType.ZOMBIE, "Zombies"); + private final static Hint hint = new ConditionHint(LostMonarchOfIfnirCondition.instance); public LostMonarchOfIfnir(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); - + this.subtype.add(SubType.ZOMBIE); this.subtype.add(SubType.NOBLE); this.power = new MageInt(4); @@ -52,28 +51,15 @@ public final class LostMonarchOfIfnir extends CardImpl { // Other Zombies you control have afflict 3. this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect( - new AfflictAbility(3), - Duration.WhileOnBattlefield, - filter, - true + new AfflictAbility(3), Duration.WhileOnBattlefield, filter, true ))); - final TriggeredAbility ability = new BeginningOfSecondMainTriggeredAbility( - Zone.BATTLEFIELD, - TargetController.YOU, - new LostMonarchOfIfnirEffect(), - false - ); - ability.addHint(hint); - // At the beginning of your second main phase, if a player was dealt combat damage by a Zombie this turn, mill three cards, then you may return a creature card from your graveyard to your hand. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - ability, - LostMonarchOfIfnirCondition.instance, - "at the beginning of your second main phase, " + - "if a player was dealt combat damage by a Zombie this turn, " + - "mill three cards, then you may return a creature card from your graveyard to your hand" - ), new LostMonarchOfIfnirWatcher()); + Ability ability = new BeginningOfSecondMainTriggeredAbility( + new MillCardsControllerEffect(3), false + ).withInterveningIf(LostMonarchOfIfnirCondition.instance); + ability.addEffect(new LostMonarchOfIfnirEffect()); + this.addAbility(ability.addHint(hint), new LostMonarchOfIfnirWatcher()); } private LostMonarchOfIfnir(final LostMonarchOfIfnir card) { @@ -87,38 +73,28 @@ public final class LostMonarchOfIfnir extends CardImpl { } class LostMonarchOfIfnirEffect extends OneShotEffect { - private static final FilterCard filter = new FilterCreatureCard(); LostMonarchOfIfnirEffect() { super(Outcome.Benefit); + staticText = ", then you may return a creature card from your graveyard to your hand"; } - private LostMonarchOfIfnirEffect(OneShotEffect effect){ + + private LostMonarchOfIfnirEffect(LostMonarchOfIfnirEffect effect) { super(effect); } @Override public boolean apply(Game game, Ability source) { - new MillCardsControllerEffect(3).apply(game, source); - - final TargetCard target = new TargetCardInYourGraveyard(0, 1, filter, true); - final Player player = game.getPlayer(source.getControllerId()); - + Player player = game.getPlayer(source.getControllerId()); if (player == null) { return false; } - - if (!player.choose(Outcome.ReturnToHand, target, source, game)) { - return true; - } - - final Card card = game.getCard(target.getFirstTarget()); - if (card == null) { - return true; - } - - player.moveCards(card, Zone.HAND, source, game); - - return true; + TargetCard target = new TargetCardInYourGraveyard( + 0, 1, StaticFilters.FILTER_CARD_CREATURE, true + ); + player.choose(Outcome.ReturnToHand, target, source, game); + Card card = game.getCard(target.getFirstTarget()); + return card != null && player.moveCards(card, Zone.HAND, source, game); } @Override @@ -132,39 +108,34 @@ enum LostMonarchOfIfnirCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - final LostMonarchOfIfnirWatcher watcher = game.getState().getWatcher(LostMonarchOfIfnirWatcher.class); - return watcher != null && watcher.wasDealtDamage(); + return game + .getState() + .getWatcher(LostMonarchOfIfnirWatcher.class) + .conditionMet(); + } + + @Override + public String toString() { + return "a player was dealt combat damage by a Zombie this turn"; } } class LostMonarchOfIfnirWatcher extends Watcher { - private boolean dealtDamage; //by a zombie this turn - LostMonarchOfIfnirWatcher() { - super(WatcherScope.GAME); - this.dealtDamage = false; + LostMonarchOfIfnirWatcher() { + super(WatcherScope.GAME); } @Override public void watch(GameEvent event, Game game) { Optional.of(event) .filter(e -> e.getType() == GameEvent.EventType.DAMAGED_PLAYER) - .filter(e -> e instanceof DamagedPlayerEvent) + .filter(DamagedPlayerEvent.class::isInstance) .map(DamagedPlayerEvent.class::cast) .filter(DamagedEvent::isCombatDamage) - .map(damagedPlayerEvent -> game.getPermanentOrLKIBattlefield(event.getSourceId())) + .map(GameEvent::getSourceId) + .map(game::getPermanentOrLKIBattlefield) .filter(permanent -> permanent.hasSubtype(SubType.ZOMBIE, game)) - .ifPresent(ignored -> this.dealtDamage = true); - } - - @Override - public void reset() { - super.reset(); - this.dealtDamage = false; - } - - boolean wasDealtDamage() { - return this.dealtDamage; + .ifPresent(ignored -> this.condition = true); } } - diff --git a/Mage.Sets/src/mage/cards/l/LothlorienBlade.java b/Mage.Sets/src/mage/cards/l/LothlorienBlade.java index bb1dbec9197..ca3814f9f50 100644 --- a/Mage.Sets/src/mage/cards/l/LothlorienBlade.java +++ b/Mage.Sets/src/mage/cards/l/LothlorienBlade.java @@ -15,7 +15,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.DefendingPlayerControlsAttachedAttackingPredicate; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -34,16 +34,16 @@ public final class LothlorienBlade extends CardImpl { public LothlorienBlade(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); - + this.subtype.add(SubType.EQUIPMENT); // Whenever equipped creature attacks, it deals damage equal to its power to target creature defending player controls. Ability ability = new AttacksAttachedTriggeredAbility(new LothlorienBladeEffect()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // Equip Elf {2} - this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2), new TargetControlledCreaturePermanent(filterElf), false)); + this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2), new TargetPermanent(filterElf), false)); // Equip {5} this.addAbility(new EquipAbility(5, false)); diff --git a/Mage.Sets/src/mage/cards/l/LowlandOaf.java b/Mage.Sets/src/mage/cards/l/LowlandOaf.java index 9ccd0920168..2d53361e007 100644 --- a/Mage.Sets/src/mage/cards/l/LowlandOaf.java +++ b/Mage.Sets/src/mage/cards/l/LowlandOaf.java @@ -20,6 +20,7 @@ import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; @@ -52,7 +53,7 @@ public final class LowlandOaf extends CardImpl { effect.setText("and gains flying until end of turn."); ability.addEffect(effect); ability.addEffect(new LowlandOafEffect()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/l/LoyalRetainers.java b/Mage.Sets/src/mage/cards/l/LoyalRetainers.java index 8d3b5f5649c..f7ed104d7a1 100644 --- a/Mage.Sets/src/mage/cards/l/LoyalRetainers.java +++ b/Mage.Sets/src/mage/cards/l/LoyalRetainers.java @@ -1,7 +1,5 @@ - package mage.cards.l; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; @@ -13,24 +11,25 @@ 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.common.FilterCreatureCard; import mage.target.common.TargetCardInYourGraveyard; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class LoyalRetainers extends CardImpl { - private static final FilterCreatureCard filter = new FilterCreatureCard("legendary creature card from your graveyard"); + private static final FilterCard filter = new FilterCreatureCard("legendary creature card from your graveyard"); static { filter.add(SuperType.LEGENDARY.getPredicate()); } public LoyalRetainers(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.ADVISOR); @@ -38,10 +37,12 @@ public final class LoyalRetainers extends CardImpl { this.toughness = new MageInt(1); // Sacrifice Loyal Retainers: Return target legendary creature card from your graveyard to the battlefield. Activate this ability only during your turn, before attackers are declared. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new ReturnFromGraveyardToBattlefieldTargetEffect(), new SacrificeSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new ReturnFromGraveyardToBattlefieldTargetEffect(), + new SacrificeSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance + ); ability.addTarget(new TargetCardInYourGraveyard(filter)); this.addAbility(ability); - } private LoyalRetainers(final LoyalRetainers card) { diff --git a/Mage.Sets/src/mage/cards/l/LoyalWarhound.java b/Mage.Sets/src/mage/cards/l/LoyalWarhound.java index 9f2162ccca8..b4939d4e19e 100644 --- a/Mage.Sets/src/mage/cards/l/LoyalWarhound.java +++ b/Mage.Sets/src/mage/cards/l/LoyalWarhound.java @@ -1,33 +1,29 @@ package mage.cards.l; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.OpponentControlsMoreCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; -import mage.constants.SubType; import mage.abilities.keyword.VigilanceAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SuperType; +import mage.constants.SubType; import mage.filter.FilterCard; import mage.filter.StaticFilters; +import mage.filter.common.FilterBasicLandCard; import mage.target.common.TargetCardInLibrary; +import java.util.UUID; + /** - * * @author weirddan455 */ public final class LoyalWarhound extends CardImpl { - private static final FilterCard filter = new FilterCard("basic Plains card"); - - static { - filter.add(SuperType.BASIC.getPredicate()); - filter.add(SubType.PLAINS.getPredicate()); - } + private static final FilterCard filter = new FilterBasicLandCard(SubType.PLAINS); + private static final Condition condition = new OpponentControlsMoreCondition(StaticFilters.FILTER_LANDS); public LoyalWarhound(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); @@ -41,12 +37,9 @@ public final class LoyalWarhound extends CardImpl { // When Loyal Warhound enters the battlefield, if an opponent controls more lands than you, // search your library for a basic Plains card, put it onto the battlefield tapped, then shuffle. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter), true)), - new OpponentControlsMoreCondition(StaticFilters.FILTER_LANDS), - "When {this} enters, if an opponent controls more lands than you, " - + "search your library for a basic Plains card, put it onto the battlefield tapped, then shuffle." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter), true) + ).withInterveningIf(condition)); } private LoyalWarhound(final LoyalWarhound card) { diff --git a/Mage.Sets/src/mage/cards/l/LuSuWuAdvisor.java b/Mage.Sets/src/mage/cards/l/LuSuWuAdvisor.java index 0159246fb6c..6c1d058c8f3 100644 --- a/Mage.Sets/src/mage/cards/l/LuSuWuAdvisor.java +++ b/Mage.Sets/src/mage/cards/l/LuSuWuAdvisor.java @@ -1,9 +1,6 @@ - package mage.cards.l; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.common.MyTurnBeforeAttackersDeclaredCondition; import mage.abilities.costs.common.TapSourceCost; @@ -13,16 +10,16 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; -import mage.constants.Zone; + +import java.util.UUID; /** - * * @author fireshoes */ public final class LuSuWuAdvisor extends CardImpl { public LuSuWuAdvisor(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.ADVISOR); @@ -30,9 +27,10 @@ public final class LuSuWuAdvisor extends CardImpl { this.toughness = new MageInt(2); // {tap}: Draw a card. Activate this ability only during your turn, before attackers are declared. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new DrawCardSourceControllerEffect(1), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); - this.addAbility(ability); + this.addAbility(new ActivateIfConditionActivatedAbility( + new DrawCardSourceControllerEffect(1), new TapSourceCost(), + MyTurnBeforeAttackersDeclaredCondition.instance + )); } private LuSuWuAdvisor(final LuSuWuAdvisor card) { diff --git a/Mage.Sets/src/mage/cards/l/LumengridDrake.java b/Mage.Sets/src/mage/cards/l/LumengridDrake.java index 4b2bc03fc9e..459fd8f5923 100644 --- a/Mage.Sets/src/mage/cards/l/LumengridDrake.java +++ b/Mage.Sets/src/mage/cards/l/LumengridDrake.java @@ -1,10 +1,9 @@ package mage.cards.l; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.MetalcraftCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.abilities.hint.common.MetalcraftHint; import mage.abilities.keyword.FlyingAbility; @@ -22,8 +21,6 @@ import java.util.UUID; */ public final class LumengridDrake extends CardImpl { - private static final String ruleText = "When {this} enters, if you control three or more artifacts, return target creature to its owner's hand."; - public LumengridDrake(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); this.subtype.add(SubType.DRAKE); @@ -36,12 +33,10 @@ public final class LumengridDrake extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Metalcraft — When Lumengrid Drake enters the battlefield, if you control three or more artifacts, return target creature to its owner's hand. - TriggeredAbility conditional = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()), MetalcraftCondition.instance, ruleText); - conditional.addTarget(new TargetCreaturePermanent()); - conditional.setAbilityWord(AbilityWord.METALCRAFT); - conditional.addHint(MetalcraftHint.instance); - this.addAbility(conditional); + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()) + .withInterveningIf(MetalcraftCondition.instance); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability.setAbilityWord(AbilityWord.METALCRAFT).addHint(MetalcraftHint.instance)); } private LumengridDrake(final LumengridDrake card) { diff --git a/Mage.Sets/src/mage/cards/l/LuminarchAscension.java b/Mage.Sets/src/mage/cards/l/LuminarchAscension.java index fdef9d188a2..326f1c55688 100644 --- a/Mage.Sets/src/mage/cards/l/LuminarchAscension.java +++ b/Mage.Sets/src/mage/cards/l/LuminarchAscension.java @@ -1,20 +1,17 @@ - package mage.cards.l; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.TargetController; -import mage.constants.Zone; import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.token.AngelToken; @@ -27,25 +24,21 @@ import java.util.UUID; */ public final class LuminarchAscension extends CardImpl { - private static final String rule = "At the beginning of each opponent's end step, " + - "if you didn't lose life this turn, you may put a quest counter on {this}."; private static final Condition condition = new SourceHasCounterCondition(CounterType.QUEST, 4); public LuminarchAscension(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}"); // At the beginning of each opponent's end step, if you didn't lose life this turn, you may put a quest counter on Luminarch Ascension. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - TargetController.OPPONENT, new AddCountersSourceEffect(CounterType.QUEST.createInstance()), - true - ), LuminarchAscensionCondition.instance, rule + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.OPPONENT, + new AddCountersSourceEffect(CounterType.QUEST.createInstance()), + true, LuminarchAscensionCondition.instance )); // {1}{W}: Create a 4/4 white Angel creature token with flying. Activate this ability only if Luminarch Ascension has four or more quest counters on it. this.addAbility(new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new CreateTokenEffect(new AngelToken()), - new ManaCostsImpl<>("{1}{W}"), condition + new CreateTokenEffect(new AngelToken()), new ManaCostsImpl<>("{1}{W}"), condition )); } @@ -64,10 +57,14 @@ enum LuminarchAscensionCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - PlayerLostLifeWatcher watcher = game.getState().getWatcher(PlayerLostLifeWatcher.class); - if (watcher != null) { - return (watcher.getLifeLost(source.getControllerId()) == 0); - } - return false; + return game + .getState() + .getWatcher(PlayerLostLifeWatcher.class) + .getLifeLost(source.getControllerId()) == 0; + } + + @Override + public String toString() { + return "you didn't lose life this turn"; } } diff --git a/Mage.Sets/src/mage/cards/l/LurkingArynx.java b/Mage.Sets/src/mage/cards/l/LurkingArynx.java index 510b8d5c25e..7b85b2a6065 100644 --- a/Mage.Sets/src/mage/cards/l/LurkingArynx.java +++ b/Mage.Sets/src/mage/cards/l/LurkingArynx.java @@ -1,7 +1,5 @@ - package mage.cards.l; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; @@ -12,19 +10,19 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AbilityWord; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class LurkingArynx extends CardImpl { public LurkingArynx(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.CAT); this.subtype.add(SubType.BEAST); this.power = new MageInt(3); @@ -32,13 +30,11 @@ public final class LurkingArynx extends CardImpl { // Formidable — {2}{G}: Target creature blocks Lurking Arynx this turn if able. Activate this ability only if creatures you control have total power 8 or greater. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new MustBeBlockedByTargetSourceEffect(Duration.EndOfTurn), - new ManaCostsImpl<>("{2}{G}"), - FormidableCondition.instance); - ability.setAbilityWord(AbilityWord.FORMIDABLE); + new ManaCostsImpl<>("{2}{G}"), FormidableCondition.instance + ); ability.addTarget(new TargetCreaturePermanent()); - this.addAbility(ability); + this.addAbility(ability.setAbilityWord(AbilityWord.FORMIDABLE)); } private LurkingArynx(final LurkingArynx card) { diff --git a/Mage.Sets/src/mage/cards/l/LurkingChupacabra.java b/Mage.Sets/src/mage/cards/l/LurkingChupacabra.java index 3e993717b3a..651b38cec79 100644 --- a/Mage.Sets/src/mage/cards/l/LurkingChupacabra.java +++ b/Mage.Sets/src/mage/cards/l/LurkingChupacabra.java @@ -12,8 +12,11 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author TheElk801 @@ -30,7 +33,7 @@ public final class LurkingChupacabra extends CardImpl { // Whenever a creature you control explores, target creature an opponent controls gets -2/-2 until end of turn Ability ability = new CreatureExploresTriggeredAbility(new BoostTargetEffect(-2, -2, Duration.EndOfTurn)); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/l/LurkingJackals.java b/Mage.Sets/src/mage/cards/l/LurkingJackals.java index e10149b40a0..d7022a2c54d 100644 --- a/Mage.Sets/src/mage/cards/l/LurkingJackals.java +++ b/Mage.Sets/src/mage/cards/l/LurkingJackals.java @@ -1,7 +1,7 @@ package mage.cards.l; -import mage.MageInt; import mage.abilities.StateTriggeredAbility; +import mage.abilities.condition.common.SourceIsEnchantmentCondition; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -11,7 +11,8 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.permanent.token.TokenImpl; +import mage.game.permanent.token.custom.CreatureToken; +import mage.players.Player; import java.util.UUID; @@ -40,9 +41,12 @@ public final class LurkingJackals extends CardImpl { class LurkingJackalsStateTriggeredAbility extends StateTriggeredAbility { public LurkingJackalsStateTriggeredAbility() { - super(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new LurkingJackalsToken(), null, Duration.Custom)); - setTriggerPhrase("When an opponent has 10 or less life, if {this} is an enchantment, "); + super(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new CreatureToken( + 3, 2, "3/2 Jackal creature", SubType.JACKAL + ), null, Duration.Custom)); + this.withInterveningIf(SourceIsEnchantmentCondition.instance); this.withRuleTextReplacement(true); + this.setTriggerPhrase("When an opponent has 10 or less life, "); } private LurkingJackalsStateTriggeredAbility(final LurkingJackalsStateTriggeredAbility ability) { @@ -56,42 +60,11 @@ class LurkingJackalsStateTriggeredAbility extends StateTriggeredAbility { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (game.getOpponents(getControllerId()) != null) { - for (UUID opponentId : game.getOpponents(getControllerId())) { - if (game.getPlayer(opponentId).getLife() <= 10) { - return true; - } - } - } - return false; - } - - @Override - public boolean checkInterveningIfClause(Game game) { - if (getSourcePermanentIfItStillExists(game) != null) { - return getSourcePermanentIfItStillExists(game).isEnchantment(game); - } - return false; - } - -} - -class LurkingJackalsToken extends TokenImpl { - - public LurkingJackalsToken() { - super("Dog", "3/2 Jackal creature"); - cardType.add(CardType.CREATURE); - subtype.add(SubType.JACKAL); - power = new MageInt(3); - toughness = new MageInt(2); - } - - private LurkingJackalsToken(final LurkingJackalsToken token) { - super(token); - } - - @Override - public LurkingJackalsToken copy() { - return new LurkingJackalsToken(this); + return game + .getOpponents(getControllerId()) + .stream() + .map(game::getPlayer) + .mapToInt(Player::getLife) + .anyMatch(x -> x <= 10); } } diff --git a/Mage.Sets/src/mage/cards/l/LurkingSkirge.java b/Mage.Sets/src/mage/cards/l/LurkingSkirge.java index e1ed2ce781a..0dc66fc1257 100644 --- a/Mage.Sets/src/mage/cards/l/LurkingSkirge.java +++ b/Mage.Sets/src/mage/cards/l/LurkingSkirge.java @@ -1,11 +1,7 @@ package mage.cards.l; -import java.util.UUID; -import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.PutIntoGraveFromBattlefieldAllTriggeredAbility; -import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.SourceIsEnchantmentCondition; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -14,18 +10,18 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.constants.TargetController; -import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; -import mage.game.permanent.token.TokenImpl; +import mage.game.permanent.token.custom.CreatureToken; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class LurkingSkirge extends CardImpl { - + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); - + static { filter.add(TargetController.OPPONENT.getOwnerPredicate()); } @@ -34,9 +30,14 @@ public final class LurkingSkirge extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}"); // When a creature is put into an opponent's graveyard from the battlefield, if Lurking Skirge is an enchantment, Lurking Skirge becomes a 3/2 Imp creature with flying. - TriggeredAbility ability = new PutIntoGraveFromBattlefieldAllTriggeredAbility(new BecomesCreatureSourceEffect(new LurkingSkirgeToken(), null, Duration.WhileOnBattlefield), false, filter, false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_PERMANENT_ENCHANTMENT), - "When a creature is put into an opponent's graveyard from the battlefield, if {this} is an enchantment, {this} becomes a 3/2 Phyrexian Imp creature with flying.")); + this.addAbility(new PutIntoGraveFromBattlefieldAllTriggeredAbility(new BecomesCreatureSourceEffect( + new CreatureToken( + 3, 2, "3/2 Phyrexian Imp creature with flying", SubType.PHYREXIAN, SubType.IMP + ).withAbility(FlyingAbility.getInstance()), null, Duration.WhileOnBattlefield + ), false, filter, false) + .withInterveningIf(SourceIsEnchantmentCondition.instance) + .withRuleTextReplacement(true) + .setTriggerPhrase("When a creature is put into an opponent's graveyard from the battlefield, ")); } private LurkingSkirge(final LurkingSkirge card) { @@ -48,24 +49,3 @@ public final class LurkingSkirge extends CardImpl { return new LurkingSkirge(this); } } - -class LurkingSkirgeToken extends TokenImpl { - - public LurkingSkirgeToken() { - super("Phyrexian Imp", "3/2 Phyrexian Imp with flying."); - cardType.add(CardType.CREATURE); - subtype.add(SubType.PHYREXIAN); - subtype.add(SubType.IMP); - power = new MageInt(3); - toughness = new MageInt(2); - this.addAbility(FlyingAbility.getInstance()); - } - - private LurkingSkirgeToken(final LurkingSkirgeToken token) { - super(token); - } - - public LurkingSkirgeToken copy() { - return new LurkingSkirgeToken(this); - } -} diff --git a/Mage.Sets/src/mage/cards/l/LutriTheSpellchaser.java b/Mage.Sets/src/mage/cards/l/LutriTheSpellchaser.java index 818845b3be4..8d0c7c65af5 100644 --- a/Mage.Sets/src/mage/cards/l/LutriTheSpellchaser.java +++ b/Mage.Sets/src/mage/cards/l/LutriTheSpellchaser.java @@ -5,7 +5,6 @@ import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromEverywhereSourceCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CopyTargetStackObjectEffect; import mage.abilities.keyword.CompanionAbility; import mage.abilities.keyword.CompanionCondition; @@ -54,12 +53,8 @@ public final class LutriTheSpellchaser extends CardImpl { this.addAbility(FlashAbility.getInstance()); // When Lutri, the Spellchaser enters the battlefield, if you cast it, copy target instant or sorcery spell you control. You may choose new targets for the copy. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new CopyTargetStackObjectEffect(), false), - CastFromEverywhereSourceCondition.instance, "When {this} enters, " + - "if you cast it, copy target instant or sorcery spell you control. " + - "You may choose new targets for the copy." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new CopyTargetStackObjectEffect()) + .withInterveningIf(CastFromEverywhereSourceCondition.instance); ability.addTarget(new TargetSpell(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/l/LuxaRiverShrine.java b/Mage.Sets/src/mage/cards/l/LuxaRiverShrine.java index 44b5a6d7b5f..f18c3661555 100644 --- a/Mage.Sets/src/mage/cards/l/LuxaRiverShrine.java +++ b/Mage.Sets/src/mage/cards/l/LuxaRiverShrine.java @@ -6,7 +6,7 @@ import mage.abilities.condition.Condition; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; @@ -33,7 +33,7 @@ public final class LuxaRiverShrine extends CardImpl { this.addAbility(ability); // {T}: You gain 2 life. Activate this ability only if there are three or more brick counters on Luxa River Shrine. - this.addAbility(new ConditionalActivatedAbility(new GainLifeEffect(2), new TapSourceCost(), condition)); + this.addAbility(new ActivateIfConditionActivatedAbility(new GainLifeEffect(2), new TapSourceCost(), condition)); } private LuxaRiverShrine(final LuxaRiverShrine card) { diff --git a/Mage.Sets/src/mage/cards/l/LysAlanaBowmaster.java b/Mage.Sets/src/mage/cards/l/LysAlanaBowmaster.java index 25e31c5d426..d031b08afd3 100644 --- a/Mage.Sets/src/mage/cards/l/LysAlanaBowmaster.java +++ b/Mage.Sets/src/mage/cards/l/LysAlanaBowmaster.java @@ -13,6 +13,7 @@ import mage.constants.SubType; import mage.filter.FilterSpell; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -40,7 +41,7 @@ public final class LysAlanaBowmaster extends CardImpl { this.addAbility(ReachAbility.getInstance()); Ability ability = new SpellCastControllerTriggeredAbility(new DamageTargetEffect(2) .setText("{this} deal 2 damage to target creature with flying"), filterElf, true); - ability.addTarget(new TargetCreaturePermanent(filterFlying)); + ability.addTarget(new TargetPermanent(filterFlying)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MabelsMettle.java b/Mage.Sets/src/mage/cards/m/MabelsMettle.java index 81f1690ff91..f19ce6ac47a 100644 --- a/Mage.Sets/src/mage/cards/m/MabelsMettle.java +++ b/Mage.Sets/src/mage/cards/m/MabelsMettle.java @@ -5,6 +5,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.SecondTargetPointer; @@ -18,12 +19,11 @@ public final class MabelsMettle extends CardImpl { public MabelsMettle(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}"); - // Target creature gets +2/+2 until end of turn. Up to one other target creature gets +1/+1 until end of turn. this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2)); this.getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(1)); this.getSpellAbility().addEffect(new BoostTargetEffect(1, 1).setTargetPointer(new SecondTargetPointer())); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 1, StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2, false).setTargetTag(2)); + this.getSpellAbility().addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2).setTargetTag(2)); } private MabelsMettle(final MabelsMettle card) { diff --git a/Mage.Sets/src/mage/cards/m/MadAuntie.java b/Mage.Sets/src/mage/cards/m/MadAuntie.java index 19aa0e37958..f6790689ed1 100644 --- a/Mage.Sets/src/mage/cards/m/MadAuntie.java +++ b/Mage.Sets/src/mage/cards/m/MadAuntie.java @@ -18,6 +18,7 @@ import mage.constants.Zone; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -46,7 +47,7 @@ public final class MadAuntie extends CardImpl { // {T}: Regenerate another target Goblin. Ability ability = new SimpleActivatedAbility(new RegenerateTargetEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter1)); + ability.addTarget(new TargetPermanent(filter1)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MadDog.java b/Mage.Sets/src/mage/cards/m/MadDog.java index f8d45d22f2b..17ee7d1312c 100644 --- a/Mage.Sets/src/mage/cards/m/MadDog.java +++ b/Mage.Sets/src/mage/cards/m/MadDog.java @@ -1,27 +1,24 @@ - package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.condition.InvertCondition; -import mage.abilities.condition.OrCondition; import mage.abilities.condition.common.AttackedThisTurnSourceCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SacrificeSourceEffect; -import mage.constants.SubType; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SubType; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.Optional; +import java.util.UUID; + /** * @author xenohedron */ - public final class MadDog extends CardImpl { public MadDog(UUID ownerId, CardSetInfo setInfo) { @@ -32,12 +29,9 @@ public final class MadDog extends CardImpl { this.toughness = new MageInt(2); // At the beginning of your end step, if Mad Dog didn't attack or come under your control this turn, sacrifice it. - Condition condition = new InvertCondition(new OrCondition(AttackedThisTurnSourceCondition.instance, MadDogCondition.instance)); - Ability ability = new ConditionalInterveningIfTriggeredAbility(new BeginningOfEndStepTriggeredAbility( - new SacrificeSourceEffect()), condition, - "At the beginning of your end step, if {this} didn't attack or come under your control this turn, sacrifice it"); - this.addAbility(ability); - + this.addAbility(new BeginningOfEndStepTriggeredAbility( + new SacrificeSourceEffect().setText("sacrifice it") + ).withInterveningIf(MadDogCondition.instance)); } private MadDog(final MadDog card) { @@ -55,8 +49,15 @@ enum MadDogCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = source.getSourcePermanentOrLKI(game); - // TRUE if came under your control this turn - return permanent != null && !permanent.wasControlledFromStartOfControllerTurn(); + return !AttackedThisTurnSourceCondition.instance.apply(game, source) + && Optional + .ofNullable(source.getSourcePermanentOrLKI(game)) + .filter(Permanent::wasControlledFromStartOfControllerTurn) + .isPresent(); + } + + @Override + public String toString() { + return "{this} didn't attack or come under your control this turn"; } } diff --git a/Mage.Sets/src/mage/cards/m/MadblindMountain.java b/Mage.Sets/src/mage/cards/m/MadblindMountain.java index f635a3fb40c..e20d6b4ba2c 100644 --- a/Mage.Sets/src/mage/cards/m/MadblindMountain.java +++ b/Mage.Sets/src/mage/cards/m/MadblindMountain.java @@ -1,39 +1,40 @@ - package mage.cards.m; -import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTappedAbility; +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.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.ShuffleLibrarySourceEffect; import mage.abilities.mana.RedManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.ComparisonType; -import mage.constants.Zone; +import mage.constants.SubType; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class MadblindMountain extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent("if you control two or more red permanents"); + private static final FilterControlledPermanent filter = new FilterControlledPermanent("you control two or more red permanents"); static { filter.add(new ColorPredicate(ObjectColor.RED)); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1); + public MadblindMountain(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.LAND},""); + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); this.subtype.add(SubType.MOUNTAIN); // ({tap}: Add {R}.) @@ -43,13 +44,11 @@ public final class MadblindMountain extends CardImpl { this.addAbility(new EntersBattlefieldTappedAbility()); // {R}, {tap}: Shuffle your library. Activate this ability only if you control two or more red permanents. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, - new ShuffleLibrarySourceEffect(), - new ManaCostsImpl<>("{R}"), - new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1)); + Ability ability = new ActivateIfConditionActivatedAbility( + new ShuffleLibrarySourceEffect(), new ManaCostsImpl<>("{R}"), condition + ); ability.addCost(new TapSourceCost()); this.addAbility(ability); - } private MadblindMountain(final MadblindMountain card) { diff --git a/Mage.Sets/src/mage/cards/m/MaddeningImp.java b/Mage.Sets/src/mage/cards/m/MaddeningImp.java index 06a989f264d..569389556ce 100644 --- a/Mage.Sets/src/mage/cards/m/MaddeningImp.java +++ b/Mage.Sets/src/mage/cards/m/MaddeningImp.java @@ -1,18 +1,15 @@ - package mage.cards.m; -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.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.common.OpponentsTurnCondition; import mage.abilities.condition.common.TargetAttackedThisTurnCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.combat.AttacksIfAbleAllEffect; import mage.abilities.keyword.FlyingAbility; @@ -26,18 +23,20 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.watchers.common.AttackedThisTurnWatcher; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + /** - * * @author L_J */ public final class MaddeningImp extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("non-Wall creatures"); + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("non-Wall creatures the active player controls"); static { filter.add(Predicates.not(SubType.WALL.getPredicate())); filter.add(TargetController.ACTIVE.getControllerPredicate()); - filter.setMessage("non-Wall creatures the active player controls"); } public MaddeningImp(UUID ownerId, CardSetInfo setInfo) { @@ -50,14 +49,12 @@ public final class MaddeningImp extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // {T}: Non-Wall creatures the active player controls attack this turn if able. At the beginning of the next end step, destroy each of those creatures that didn't attack this turn. Activate this ability only during an opponent's turn and only before combat. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new AttacksIfAbleAllEffect(filter, Duration.EndOfTurn), - new TapSourceCost(), new MaddeningImpTurnCondition(), - "{T}: Non-Wall creatures the active player controls attack this turn if able. " - + "At the beginning of the next end step, destroy each of those creatures that didn't attack this turn. " - + "Activate only during an opponent's turn and only before combat."); + Ability ability = new ActivateIfConditionActivatedAbility( + new AttacksIfAbleAllEffect(filter, Duration.EndOfTurn), + new TapSourceCost(), MaddeningImpTurnCondition.instance + ); ability.addEffect(new MaddeningImpCreateDelayedTriggeredAbilityEffect()); this.addAbility(ability); - } private MaddeningImp(final MaddeningImp card) { @@ -70,17 +67,17 @@ public final class MaddeningImp extends CardImpl { } } -class MaddeningImpTurnCondition implements Condition { +enum MaddeningImpTurnCondition implements Condition { + instance; @Override public boolean apply(Game game, Ability source) { - Player activePlayer = game.getPlayer(game.getActivePlayerId()); - return activePlayer != null && activePlayer.hasOpponent(source.getControllerId(), game) && game.getPhase().getStep().getType().getIndex() < 5; + return OpponentsTurnCondition.instance.apply(game, source) && !game.getTurn().isDeclareAttackersStepStarted(); } @Override public String toString() { - return ""; + return "during an opponent's turn and only before combat"; } } @@ -150,7 +147,7 @@ class MaddeningImpDelayedDestroyEffect extends OneShotEffect { Player player = game.getPlayer(game.getActivePlayerId()); if (player != null) { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(player.getId())) { - + MageObjectReference mor = new MageObjectReference(permanent, game); // Only affect permanents present when the ability resolved if (!activeCreatures.contains(mor)) { diff --git a/Mage.Sets/src/mage/cards/m/MaestrosDiabolist.java b/Mage.Sets/src/mage/cards/m/MaestrosDiabolist.java index 85596a1765f..e965f604851 100644 --- a/Mage.Sets/src/mage/cards/m/MaestrosDiabolist.java +++ b/Mage.Sets/src/mage/cards/m/MaestrosDiabolist.java @@ -4,7 +4,6 @@ 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.CreateTokenEffect; import mage.abilities.keyword.DeathtouchAbility; import mage.abilities.keyword.HasteAbility; @@ -25,7 +24,7 @@ import java.util.UUID; */ public final class MaestrosDiabolist extends CardImpl { - private static final FilterPermanent filter = new FilterControlledPermanent(SubType.DEVIL); + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.DEVIL, "you don't control a Devil token"); static { filter.add(TokenPredicate.TRUE); @@ -49,13 +48,9 @@ public final class MaestrosDiabolist extends CardImpl { this.addAbility(HasteAbility.getInstance()); // Whenever Maestros Diabolist attacks, if you don't control a Devil token, create a tapped and attacking 1/1 red Devil creature token with "When this creature dies, it deals 1 damage to any target." - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility( - new CreateTokenEffect(new DevilToken(), 1, true, true) - ), condition, "Whenever {this} attacks, if you don't control a Devil token, " + - "create a tapped and attacking 1/1 red Devil creature token with " + - "\"When this creature dies, it deals 1 damage to any target.\"" - )); + this.addAbility(new AttacksTriggeredAbility( + new CreateTokenEffect(new DevilToken(), 1, true, true) + ).withInterveningIf(condition)); } private MaestrosDiabolist(final MaestrosDiabolist card) { diff --git a/Mage.Sets/src/mage/cards/m/MageRingResponder.java b/Mage.Sets/src/mage/cards/m/MageRingResponder.java index 56ce5c14dca..86bab2ed384 100644 --- a/Mage.Sets/src/mage/cards/m/MageRingResponder.java +++ b/Mage.Sets/src/mage/cards/m/MageRingResponder.java @@ -1,9 +1,8 @@ - package mage.cards.m; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.ManaCostsImpl; @@ -13,23 +12,24 @@ import mage.abilities.effects.common.UntapSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SetTargetPointer; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; +import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster; + +import java.util.UUID; /** - * * @author fireshoes */ public final class MageRingResponder extends CardImpl { + private static final FilterCreaturePermanent filter + = new FilterCreaturePermanent("creature defending player controls"); + public MageRingResponder(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{7}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{7}"); this.subtype.add(SubType.GOLEM); this.power = new MageInt(7); this.toughness = new MageInt(7); @@ -41,7 +41,10 @@ public final class MageRingResponder extends CardImpl { this.addAbility(new SimpleActivatedAbility(new UntapSourceEffect(), new ManaCostsImpl<>("{7}"))); // Whenever Mage-Ring Responder attacks, it deals 7 damage to target creature defending player controls. - this.addAbility(new MageRingResponderAbility()); + Ability ability = new AttacksTriggeredAbility(new DamageTargetEffect(7), false, null, SetTargetPointer.PLAYER); + ability.addTarget(new TargetPermanent(filter)); + ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster()); + this.addAbility(ability); } private MageRingResponder(final MageRingResponder card) { @@ -53,44 +56,3 @@ public final class MageRingResponder extends CardImpl { return new MageRingResponder(this); } } - -class MageRingResponderAbility extends TriggeredAbilityImpl { - - public MageRingResponderAbility() { - super(Zone.BATTLEFIELD, new DamageTargetEffect(7)); - } - - private MageRingResponderAbility(final MageRingResponderAbility ability) { - super(ability); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ATTACKER_DECLARED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getSourceId().equals(this.getSourceId())) { - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls"); - UUID defenderId = game.getCombat().getDefenderId(sourceId); - filter.add(new ControllerIdPredicate(defenderId)); - - this.getTargets().clear(); - TargetCreaturePermanent target = new TargetCreaturePermanent(filter); - this.addTarget(target); - return true; - } - return false; - } - - @Override - public String getRule() { - return "Whenever {this} attacks, it deals 7 damage to target creature defending player controls."; - } - - @Override - public MageRingResponderAbility copy() { - return new MageRingResponderAbility(this); - } -} diff --git a/Mage.Sets/src/mage/cards/m/MagewrightsStone.java b/Mage.Sets/src/mage/cards/m/MagewrightsStone.java index 64467e9ceb9..95a789e6842 100644 --- a/Mage.Sets/src/mage/cards/m/MagewrightsStone.java +++ b/Mage.Sets/src/mage/cards/m/MagewrightsStone.java @@ -16,6 +16,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicate; import mage.game.Game; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -37,7 +38,7 @@ public final class MagewrightsStone extends CardImpl { // {1}, {T}: Untap target creature that has an activated ability with {T} in its cost. Ability ability = new SimpleActivatedAbility(new UntapTargetEffect(), new ManaCostsImpl<>("{1}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MagmaSliver.java b/Mage.Sets/src/mage/cards/m/MagmaSliver.java index d5d4217f715..6bacede7d4a 100644 --- a/Mage.Sets/src/mage/cards/m/MagmaSliver.java +++ b/Mage.Sets/src/mage/cards/m/MagmaSliver.java @@ -20,8 +20,11 @@ import mage.constants.Zone; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.constants.SubType.SLIVER; + /** * * @author cbt33 @@ -42,8 +45,7 @@ public final class MagmaSliver extends CardImpl { StaticFilters.FILTER_PERMANENT_ALL_SLIVERS), StaticValue.get(0), Duration.EndOfTurn), new TapSourceCost()); - Target target = new TargetCreaturePermanent( - new FilterCreaturePermanent(SubType.SLIVER, "Sliver creature")); + Target target = new TargetPermanent(new FilterCreaturePermanent(SLIVER, "Sliver creature")); ability.addTarget(target); Effect effect = new GainAbilityAllEffect(ability, Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_ALL_SLIVERS); diff --git a/Mage.Sets/src/mage/cards/m/MagneticMountain.java b/Mage.Sets/src/mage/cards/m/MagneticMountain.java index bc2aa00d7f2..69cfeeb18ca 100644 --- a/Mage.Sets/src/mage/cards/m/MagneticMountain.java +++ b/Mage.Sets/src/mage/cards/m/MagneticMountain.java @@ -1,16 +1,19 @@ - package mage.cards.m; import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.Cost; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DontUntapInControllersUntapStepAllEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; @@ -19,7 +22,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; import mage.util.ManaUtil; import java.util.UUID; @@ -29,7 +32,7 @@ import java.util.UUID; */ public final class MagneticMountain extends CardImpl { - static final FilterCreaturePermanent filter = new FilterCreaturePermanent("blue creatures"); + static final FilterPermanent filter = new FilterCreaturePermanent("blue creatures"); static { filter.add(new ColorPredicate(ObjectColor.BLUE)); @@ -80,28 +83,27 @@ class MagneticMountainEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - - Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); - Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if (player != null && sourcePermanent != null) { - int countBattlefield = game.getBattlefield().getAllActivePermanents(filter2, game.getActivePlayerId(), game).size(); - while (player.canRespond() && countBattlefield > 0 && player.chooseUse(Outcome.Benefit, "Pay {4} and untap a tapped blue creature under your control?", source, game)) { - Target tappedCreatureTarget = new TargetControlledCreaturePermanent(1, 1, filter2, true); - if (player.choose(Outcome.Untap, tappedCreatureTarget, source, game)) { - Cost cost = ManaUtil.createManaCost(4, false); - Permanent tappedCreature = game.getPermanent(tappedCreatureTarget.getFirstTarget()); - if (tappedCreature != null && cost.pay(source, game, source, player.getId(), false)) { - tappedCreature.untap(game); - } else { - break; - } + Player player = game.getPlayer(game.getActivePlayerId()); + if (player == null) { + return false; + } + int countBattlefield = game.getBattlefield().getAllActivePermanents(filter2, game.getActivePlayerId(), game).size(); + while (player.canRespond() && countBattlefield > 0 && player.chooseUse(Outcome.Benefit, "Pay {4} and untap a tapped blue creature under your control?", source, game)) { + Target tappedCreatureTarget = new TargetControlledPermanent(filter2); + tappedCreatureTarget.withNotTarget(true); + if (player.choose(Outcome.Untap, tappedCreatureTarget, source, game)) { + Cost cost = ManaUtil.createManaCost(4, false); + Permanent tappedCreature = game.getPermanent(tappedCreatureTarget.getFirstTarget()); + if (tappedCreature != null && cost.pay(source, game, source, player.getId(), false)) { + tappedCreature.untap(game); } else { break; } - countBattlefield = game.getBattlefield().getAllActivePermanents(filter2, game.getActivePlayerId(), game).size(); + } else { + break; } - return true; + countBattlefield = game.getBattlefield().getAllActivePermanents(filter2, game.getActivePlayerId(), game).size(); } - return false; + return true; } } diff --git a/Mage.Sets/src/mage/cards/m/MagusOfTheAbyss.java b/Mage.Sets/src/mage/cards/m/MagusOfTheAbyss.java index 2d293a138d2..37b91a639c2 100644 --- a/Mage.Sets/src/mage/cards/m/MagusOfTheAbyss.java +++ b/Mage.Sets/src/mage/cards/m/MagusOfTheAbyss.java @@ -1,39 +1,45 @@ - package mage.cards.m; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; +import mage.constants.TargetController; +import mage.filter.FilterPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; -import mage.game.events.GameEvent; -import mage.players.Player; import mage.target.Target; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; +import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetpointer.FirstTargetPointer; + +import java.util.UUID; /** - * * @author escplan9 (Derek Monturo - dmontur1 at gmail dot com) */ public final class MagusOfTheAbyss extends CardImpl { + private static final FilterPermanent filter = new FilterPermanent("nonartifact creature that player controls of their choice"); + public MagusOfTheAbyss(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.HUMAN); this.subtype.add(SubType.WIZARD); this.power = new MageInt(4); this.toughness = new MageInt(3); // At the beginning of each player's upkeep, destroy target nonartifact creature that player controls of their choice. It can't be regenerated. - this.addAbility(new MagusOfTheAbyssTriggeredAbility()); + Ability ability = new BeginningOfUpkeepTriggeredAbility(TargetController.EACH_PLAYER, + new DestroyTargetEffect(true), false).withTargetPointerSet(true); + ability.addTarget(new TargetPermanent(filter)); // Only used for text generation + ability.setTargetAdjuster(MagusOfTheAbyssTargetAdjuster.instance); + this.addAbility(ability); } private MagusOfTheAbyss(final MagusOfTheAbyss card) { @@ -46,45 +52,27 @@ public final class MagusOfTheAbyss extends CardImpl { } } -class MagusOfTheAbyssTriggeredAbility extends TriggeredAbilityImpl { +enum MagusOfTheAbyssTargetAdjuster implements TargetAdjuster { + instance; - MagusOfTheAbyssTriggeredAbility() { - super(Zone.BATTLEFIELD, new DestroyTargetEffect(true), false); - } + private static final FilterPermanent filter + = new FilterPermanent("nonartifact creature that player controls of their choice"); - private MagusOfTheAbyssTriggeredAbility(final MagusOfTheAbyssTriggeredAbility ability) { - super(ability); + static { + filter.add(Predicates.not(CardType.ARTIFACT.getPredicate())); + filter.add(CardType.CREATURE.getPredicate()); } @Override - public MagusOfTheAbyssTriggeredAbility copy() { - return new MagusOfTheAbyssTriggeredAbility(this); - } + public void adjustTargets(Ability ability, Game game) { + UUID opponentId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability); + ability.getTargets().clear(); + ability.getAllEffects().setTargetPointer(new FirstTargetPointer()); - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.UPKEEP_STEP_PRE; + FilterPermanent adjustedFilter = filter.copy(); + adjustedFilter.add(new ControllerIdPredicate(opponentId)); + Target newTarget = new TargetPermanent(adjustedFilter); + newTarget.setTargetController(opponentId); + ability.addTarget(newTarget); } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - Player player = game.getPlayer(event.getPlayerId()); - if (player != null) { - FilterCreaturePermanent filter = new FilterCreaturePermanent("nonartifact creature you control"); - filter.add(Predicates.not(CardType.ARTIFACT.getPredicate())); - filter.add(new ControllerIdPredicate(player.getId())); - Target target = new TargetCreaturePermanent(filter); - target.setAbilityController(getControllerId()); - target.setTargetController(player.getId()); - this.getTargets().clear(); - this.getTargets().add(target); - return true; - } - return false; - } - - @Override - public String getRule() { - return "At the beginning of each player's upkeep, destroy target nonartifact creature that player controls of their choice. It can't be regenerated."; - } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/m/MagusOfTheLibrary.java b/Mage.Sets/src/mage/cards/m/MagusOfTheLibrary.java index a6e0bca334b..9c61c7fc0ed 100644 --- a/Mage.Sets/src/mage/cards/m/MagusOfTheLibrary.java +++ b/Mage.Sets/src/mage/cards/m/MagusOfTheLibrary.java @@ -1,28 +1,29 @@ - package mage.cards.m; -import java.util.UUID; import mage.MageInt; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInHandCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.mana.ColorlessManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.ComparisonType; -import mage.constants.Zone; +import mage.constants.SubType; + +import java.util.UUID; /** - * * @author fireshoes */ public final class MagusOfTheLibrary extends CardImpl { + private static final Condition condition = new CardsInHandCondition(ComparisonType.EQUAL_TO, 7); + public MagusOfTheLibrary(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{G}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WIZARD); this.power = new MageInt(1); @@ -30,14 +31,11 @@ public final class MagusOfTheLibrary extends CardImpl { // {tap}: Add {C}. this.addAbility(new ColorlessManaAbility()); - + // {tap}: Draw a card. Activate this ability only if you have exactly seven cards in hand. - this.addAbility(new ConditionalActivatedAbility( - Zone.BATTLEFIELD, - new DrawCardSourceControllerEffect(1), - new TapSourceCost(), - new CardsInHandCondition(ComparisonType.EQUAL_TO, 7), - "")); + this.addAbility(new ActivateIfConditionActivatedAbility( + new DrawCardSourceControllerEffect(1), new TapSourceCost(), condition + )); } private MagusOfTheLibrary(final MagusOfTheLibrary card) { diff --git a/Mage.Sets/src/mage/cards/m/MagusOfTheMirror.java b/Mage.Sets/src/mage/cards/m/MagusOfTheMirror.java index 2583026ea28..e354c4a6f96 100644 --- a/Mage.Sets/src/mage/cards/m/MagusOfTheMirror.java +++ b/Mage.Sets/src/mage/cards/m/MagusOfTheMirror.java @@ -1,24 +1,21 @@ - package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.ExchangeLifeControllerTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.PhaseStep; -import mage.constants.Zone; import mage.target.common.TargetOpponent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class MagusOfTheMirror extends CardImpl { @@ -31,11 +28,9 @@ public final class MagusOfTheMirror extends CardImpl { this.toughness = new MageInt(2); // {tap}, Sacrifice Magus of the Mirror: Exchange life totals with target opponent. Activate this ability only during your upkeep. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, + Ability ability = new ActivateIfConditionActivatedAbility( new ExchangeLifeControllerTargetEffect(), - new TapSourceCost(), - new IsStepCondition(PhaseStep.UPKEEP) + new TapSourceCost(), IsStepCondition.getMyUpkeep() ); ability.addCost(new SacrificeSourceCost()); ability.addTarget(new TargetOpponent()); diff --git a/Mage.Sets/src/mage/cards/m/MalametVeteran.java b/Mage.Sets/src/mage/cards/m/MalametVeteran.java index d88a452d28a..00d00aea653 100644 --- a/Mage.Sets/src/mage/cards/m/MalametVeteran.java +++ b/Mage.Sets/src/mage/cards/m/MalametVeteran.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.DescendCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; @@ -24,7 +23,7 @@ public final class MalametVeteran extends CardImpl { public MalametVeteran(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}"); - + this.subtype.add(SubType.CAT); this.subtype.add(SubType.WARRIOR); this.power = new MageInt(5); @@ -34,13 +33,9 @@ public final class MalametVeteran extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // Descend 4 -- Whenever Malamet Veteran attacks, if there are four or more permanent cards in your graveyard, put a +1/+1 counter on target creature. - Ability ability = new ConditionalInterveningIfTriggeredAbility(new AttacksTriggeredAbility( - new AddCountersTargetEffect(CounterType.P1P1.createInstance())), DescendCondition.FOUR, - "Whenever {this} attacks, if there are four or more permanent cards in your graveyard, put a +1/+1 counter on target creature." - ); + Ability ability = new AttacksTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance())).withInterveningIf(DescendCondition.FOUR); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability.setAbilityWord(AbilityWord.DESCEND_4).addHint(DescendCondition.getHint())); - } private MalametVeteran(final MalametVeteran card) { diff --git a/Mage.Sets/src/mage/cards/m/MaliciousAffliction.java b/Mage.Sets/src/mage/cards/m/MaliciousAffliction.java index e537e4dd686..25669eb4fa8 100644 --- a/Mage.Sets/src/mage/cards/m/MaliciousAffliction.java +++ b/Mage.Sets/src/mage/cards/m/MaliciousAffliction.java @@ -1,20 +1,22 @@ package mage.cards.m; -import mage.abilities.Ability; import mage.abilities.condition.common.MorbidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CastSourceTriggeredAbility; import mage.abilities.effects.common.CopySourceSpellEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.hint.common.MorbidHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * @author LevelX2 */ @@ -24,17 +26,13 @@ public final class MaliciousAffliction extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}{B}"); // Morbid — When you cast Malicious Affliction, if a creature died this turn, you may copy Malicious Affliction and may choose a new target for the copy. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new CastSourceTriggeredAbility(new CopySourceSpellEffect(), true), - MorbidCondition.instance, "Morbid — When you cast this spell, " + - "if a creature died this turn, you may copy {this} and may choose a new target for the copy." - ); - ability.setRuleAtTheTop(true); - this.addAbility(ability.addHint(MorbidHint.instance)); + this.addAbility(new CastSourceTriggeredAbility( + new CopySourceSpellEffect().setText("copy {this} and may choose a new target for the copy"), true + ).withInterveningIf(MorbidCondition.instance).setAbilityWord(AbilityWord.MORBID).addHint(MorbidHint.instance).setRuleAtTheTop(true)); // Destroy target nonblack creature. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); } private MaliciousAffliction(final MaliciousAffliction card) { diff --git a/Mage.Sets/src/mage/cards/m/ManaCache.java b/Mage.Sets/src/mage/cards/m/ManaCache.java index 3bc422f2550..b6592f70579 100644 --- a/Mage.Sets/src/mage/cards/m/ManaCache.java +++ b/Mage.Sets/src/mage/cards/m/ManaCache.java @@ -1,40 +1,52 @@ package mage.cards.m; import mage.Mana; -import mage.abilities.Ability; -import mage.abilities.TriggeredAbility; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.costs.common.RemoveCountersSourceCost; -import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.CountersSourceCount; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.mana.BasicManaEffect; import mage.abilities.mana.ActivatedManaAbilityImpl; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.PhaseStep; +import mage.constants.TargetController; +import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.FilterPermanent; -import mage.filter.common.FilterControlledLandPermanent; +import mage.filter.common.FilterLandPermanent; import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; import mage.players.Player; import java.util.UUID; -import mage.abilities.dynamicvalue.common.CountersSourceCount; /** * @author L_J */ public final class ManaCache extends CardImpl { + private static final FilterPermanent filter = new FilterLandPermanent("untapped land that player controls"); + + static { + filter.add(TappedPredicate.UNTAPPED); + filter.add(TargetController.ACTIVE.getControllerPredicate()); + } + + private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter); + public ManaCache(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}{R}"); // At the beginning of each player's end step, put a charge counter on Mana Cache for each untapped land that player controls. - TriggeredAbility ability = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of each player's end step", true, new ManaCacheEffect()); - this.addAbility(ability); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.EACH_PLAYER, + new AddCountersSourceEffect(CounterType.CHARGE.createInstance(), xValue), + false + )); // Remove a charge counter from Mana Cache: Add {C}. Any player may activate this ability but only during their turn before the end step. this.addAbility(new ManaCacheManaAbility()); @@ -50,41 +62,6 @@ public final class ManaCache extends CardImpl { } } -class ManaCacheEffect extends OneShotEffect { - - private static final FilterPermanent filter = new FilterControlledLandPermanent(); - - static { - filter.add(TappedPredicate.UNTAPPED); - } - - public ManaCacheEffect() { - super(Outcome.Damage); - this.staticText = "put a charge counter on {this} for each untapped land that player controls"; - } - - private ManaCacheEffect(final ManaCacheEffect effect) { - super(effect); - } - - @Override - public ManaCacheEffect copy() { - return new ManaCacheEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(game.getActivePlayerId()); - Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if (player != null && sourcePermanent != null) { - int controlledUntappedLands = game.getBattlefield().countAll(filter, game.getActivePlayerId(), game); - sourcePermanent.addCounters(CounterType.CHARGE.createInstance(controlledUntappedLands), source.getControllerId(), source, game); - return true; - } - return false; - } -} - class ManaCacheManaAbility extends ActivatedManaAbilityImpl { public ManaCacheManaAbility() { diff --git a/Mage.Sets/src/mage/cards/m/ManaSkimmer.java b/Mage.Sets/src/mage/cards/m/ManaSkimmer.java index 17e473baede..2cff22f5320 100644 --- a/Mage.Sets/src/mage/cards/m/ManaSkimmer.java +++ b/Mage.Sets/src/mage/cards/m/ManaSkimmer.java @@ -1,9 +1,9 @@ package mage.cards.m; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; +import mage.abilities.common.DealsDamageToAPlayerTriggeredAbility; import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect; import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.keyword.FlyingAbility; @@ -11,13 +11,10 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; -import mage.filter.common.FilterLandPermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; -import mage.target.TargetPermanent; +import mage.target.common.TargetLandPermanent; +import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster; + +import java.util.UUID; /** * @@ -34,7 +31,11 @@ public final class ManaSkimmer extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); // Whenever Mana Skimmer deals damage to a player, tap target land that player controls. That land doesn't untap during its controller's next untap step. - this.addAbility(new ManaSkimmerTriggeredAbility()); + Ability ability = new DealsDamageToAPlayerTriggeredAbility(new TapTargetEffect(), false, true); + ability.addEffect(new DontUntapInControllersNextUntapStepTargetEffect("That land")); + ability.addTarget(new TargetLandPermanent().withTargetName("target land that player controls")); + ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster()); + this.addAbility(ability); } private ManaSkimmer(final ManaSkimmer card) { @@ -46,44 +47,3 @@ public final class ManaSkimmer extends CardImpl { return new ManaSkimmer(this); } } - -class ManaSkimmerTriggeredAbility extends TriggeredAbilityImpl { - - ManaSkimmerTriggeredAbility() { - super(Zone.BATTLEFIELD, new TapTargetEffect(), false); - addEffect(new DontUntapInControllersNextUntapStepTargetEffect()); - } - - private ManaSkimmerTriggeredAbility(final ManaSkimmerTriggeredAbility ability) { - super(ability); - } - - @Override - public ManaSkimmerTriggeredAbility copy() { - return new ManaSkimmerTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - Permanent source = game.getPermanent(event.getSourceId()); - if (source != null && source.getId().equals(this.getSourceId())) { - FilterLandPermanent filter = new FilterLandPermanent("land that player controls"); - filter.add(new ControllerIdPredicate(event.getPlayerId())); - filter.setMessage("land controlled by " + game.getPlayer(event.getTargetId()).getLogName()); - this.getTargets().clear(); - this.addTarget(new TargetPermanent(filter)); - return true; - } - return false; - } - - @Override - public String getRule() { - return "Whenever {this} deals damage to a player, tap target land that player controls. That land doesn't untap during its controller's next untap step."; - } -} diff --git a/Mage.Sets/src/mage/cards/m/ManicScribe.java b/Mage.Sets/src/mage/cards/m/ManicScribe.java index 78767f93007..3050860269d 100644 --- a/Mage.Sets/src/mage/cards/m/ManicScribe.java +++ b/Mage.Sets/src/mage/cards/m/ManicScribe.java @@ -1,19 +1,18 @@ package mage.cards.m; import mage.MageInt; -import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.DeliriumCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.effects.common.MillCardsEachPlayerEffect; import mage.abilities.effects.common.MillCardsTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.TargetController; -import mage.constants.Zone; import java.util.UUID; @@ -36,13 +35,9 @@ public final class ManicScribe extends CardImpl { // 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, TargetController.OPPONENT, new MillCardsTargetEffect(3), - false - ), 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(CardTypesInGraveyardCount.YOU.getHint())); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + TargetController.OPPONENT, new MillCardsTargetEffect(3), false + ).withInterveningIf(DeliriumCondition.instance).setAbilityWord(AbilityWord.DELIRIUM).addHint(CardTypesInGraveyardCount.YOU.getHint())); } private ManicScribe(final ManicScribe card) { diff --git a/Mage.Sets/src/mage/cards/m/MaraudingLooter.java b/Mage.Sets/src/mage/cards/m/MaraudingLooter.java index d3500d59ff1..b7ff7e2f97b 100644 --- a/Mage.Sets/src/mage/cards/m/MaraudingLooter.java +++ b/Mage.Sets/src/mage/cards/m/MaraudingLooter.java @@ -1,12 +1,10 @@ package mage.cards.m; import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawDiscardControllerEffect; import mage.abilities.hint.common.RaidHint; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AbilityWord; @@ -30,15 +28,9 @@ public final class MaraudingLooter extends CardImpl { this.toughness = new MageInt(3); // Raid - At the beginning of your end step, if you attacked this turn, you may draw a card. If you do, discard a card. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility(new DrawDiscardControllerEffect(1, 1, true)), - RaidCondition.instance, - "At the beginning of your end step, " - + "if you attacked this turn, " - + "you may draw a card. If you do, discard a card."); - ability.setAbilityWord(AbilityWord.RAID); - ability.addHint(RaidHint.instance); - this.addAbility(ability, new PlayerAttackedWatcher()); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + new DrawDiscardControllerEffect(1, 1, true) + ).withInterveningIf(RaidCondition.instance).setAbilityWord(AbilityWord.RAID).addHint(RaidHint.instance), new PlayerAttackedWatcher()); } private MaraudingLooter(final MaraudingLooter card) { diff --git a/Mage.Sets/src/mage/cards/m/MarchOfTheCanonized.java b/Mage.Sets/src/mage/cards/m/MarchOfTheCanonized.java index 47841d26fd3..c05b3e22254 100644 --- a/Mage.Sets/src/mage/cards/m/MarchOfTheCanonized.java +++ b/Mage.Sets/src/mage/cards/m/MarchOfTheCanonized.java @@ -1,22 +1,21 @@ package mage.cards.m; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.condition.IntCompareCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.dynamicvalue.common.DevotionCount; import mage.abilities.dynamicvalue.common.GetXValue; import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.ComparisonType; import mage.game.Game; import mage.game.permanent.token.IxalanVampireToken; import mage.game.permanent.token.VampireDemonToken; +import java.util.UUID; + /** * @author arcox */ @@ -29,13 +28,8 @@ public final class MarchOfTheCanonized extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new IxalanVampireToken(), GetXValue.instance))); // At the beginning of your upkeep, if your devotion to white and black is seven or greater, create a 4/3 white and black Vampire Demon creature token with flying. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new VampireDemonToken())), - new MarchOfTheCanonizedCondition(), - "At the beginning of your upkeep, " - + "if your devotion to white and black is seven or greater, " - + "create a 4/3 white and black Vampire Demon creature token with flying." - ).addHint(DevotionCount.WB.getHint())); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new VampireDemonToken())) + .withInterveningIf(MarchOfTheCanonizedCondition.instance).addHint(DevotionCount.WB.getHint())); } private MarchOfTheCanonized(final MarchOfTheCanonized card) { @@ -48,14 +42,16 @@ public final class MarchOfTheCanonized extends CardImpl { } } -class MarchOfTheCanonizedCondition extends IntCompareCondition { +enum MarchOfTheCanonizedCondition implements Condition { + instance; - MarchOfTheCanonizedCondition() { - super(ComparisonType.OR_GREATER, 7); + @Override + public boolean apply(Game game, Ability source) { + return DevotionCount.WB.calculate(game, source, null) >= 7; } @Override - protected int getInputValue(Game game, Ability source) { - return DevotionCount.WB.calculate(game, source, null); + public String toString() { + return "your devotion to white and black is seven or greater"; } } diff --git a/Mage.Sets/src/mage/cards/m/MarchesaResoluteMonarch.java b/Mage.Sets/src/mage/cards/m/MarchesaResoluteMonarch.java index aeca802c7fd..37cea498d81 100644 --- a/Mage.Sets/src/mage/cards/m/MarchesaResoluteMonarch.java +++ b/Mage.Sets/src/mage/cards/m/MarchesaResoluteMonarch.java @@ -3,16 +3,19 @@ package mage.cards.m; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.LoseLifeSourceControllerEffect; import mage.abilities.effects.common.counter.RemoveAllCountersPermanentTargetEffect; import mage.abilities.keyword.DeathtouchAbility; import mage.abilities.keyword.MenaceAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.WatcherScope; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.DamagedEvent; @@ -52,13 +55,9 @@ public final class MarchesaResoluteMonarch extends CardImpl { this.addAbility(ability); // At the beginning of your upkeep, if you haven't been dealt combat damage since your last turn, you draw a card and you lose 1 life. - ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility( - new DrawCardSourceControllerEffect(1), false - ), MarchesaResoluteMonarchWatcher::checkPlayer, "At the beginning of your upkeep, " + - "if you haven't been dealt combat damage since your last turn, you draw a card and you lose 1 life." - ); - ability.addEffect(new LoseLifeSourceControllerEffect(1)); + ability = new BeginningOfUpkeepTriggeredAbility(new DrawCardSourceControllerEffect(1, true)) + .withInterveningIf(MarchesaResoluteMonarchCondition.instance); + ability.addEffect(new LoseLifeSourceControllerEffect(1).concatBy("and")); this.addAbility(ability); } @@ -76,6 +75,20 @@ public final class MarchesaResoluteMonarch extends CardImpl { } } +enum MarchesaResoluteMonarchCondition implements Condition { + instance; + + @Override + public boolean apply(Game game, Ability source) { + return MarchesaResoluteMonarchWatcher.checkPlayer(game, source); + } + + @Override + public String toString() { + return "you haven't been dealt combat damage since your last turn"; + } +} + class MarchesaResoluteMonarchWatcher extends Watcher { private final Set players = new HashSet<>(); diff --git a/Mage.Sets/src/mage/cards/m/MarduHeartPiercer.java b/Mage.Sets/src/mage/cards/m/MarduHeartPiercer.java index 17a3bf31124..0b585235d2b 100644 --- a/Mage.Sets/src/mage/cards/m/MarduHeartPiercer.java +++ b/Mage.Sets/src/mage/cards/m/MarduHeartPiercer.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.hint.common.RaidHint; import mage.cards.CardImpl; @@ -31,12 +30,9 @@ public final class MarduHeartPiercer extends CardImpl { this.toughness = new MageInt(3); // Raid - When Mardu Heart-Piercer enters the battlefield, if you attacked this turn, Mardu Heart-Piercer deals 2 damage to any target. - Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2)), RaidCondition.instance, - "When {this} enters, if you attacked this turn, {this} deals 2 damage to any target."); + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2)).withInterveningIf(RaidCondition.instance); ability.addTarget(new TargetAnyTarget()); - ability.setAbilityWord(AbilityWord.RAID); - ability.addHint(RaidHint.instance); - this.addAbility(ability, new PlayerAttackedWatcher()); + this.addAbility(ability.setAbilityWord(AbilityWord.RAID).addHint(RaidHint.instance), new PlayerAttackedWatcher()); } private MarduHeartPiercer(final MarduHeartPiercer card) { diff --git a/Mage.Sets/src/mage/cards/m/MarduHordechief.java b/Mage.Sets/src/mage/cards/m/MarduHordechief.java index 27430d4ce84..b26bc66cf98 100644 --- a/Mage.Sets/src/mage/cards/m/MarduHordechief.java +++ b/Mage.Sets/src/mage/cards/m/MarduHordechief.java @@ -3,7 +3,6 @@ package mage.cards.m; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.hint.common.RaidHint; import mage.cards.CardImpl; @@ -30,13 +29,8 @@ public final class MarduHordechief extends CardImpl { this.toughness = new MageInt(3); // Raid — When Mardu Hordechief enters the battlefield, if you attacked this turn, create a 1/1 white Warrior creature token - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility( - new CreateTokenEffect(new WarriorToken())), - RaidCondition.instance, - "When {this} enters, if you attacked this turn, create a 1/1 white Warrior creature token.") - .setAbilityWord(AbilityWord.RAID) - .addHint(RaidHint.instance), - new PlayerAttackedWatcher()); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new WarriorToken())) + .withInterveningIf(RaidCondition.instance).setAbilityWord(AbilityWord.RAID).addHint(RaidHint.instance), new PlayerAttackedWatcher()); } private MarduHordechief(final MarduHordechief card) { diff --git a/Mage.Sets/src/mage/cards/m/MarduSkullhunter.java b/Mage.Sets/src/mage/cards/m/MarduSkullhunter.java index ec59f21eb59..4153d13a8ea 100644 --- a/Mage.Sets/src/mage/cards/m/MarduSkullhunter.java +++ b/Mage.Sets/src/mage/cards/m/MarduSkullhunter.java @@ -5,7 +5,6 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTappedAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.abilities.hint.common.RaidHint; import mage.cards.CardImpl; @@ -35,12 +34,9 @@ public final class MarduSkullhunter extends CardImpl { this.addAbility(new EntersBattlefieldTappedAbility()); // Raid - When Mardu Skullhunter enters the battlefield, if you attacked this turn, target opponent discards a card. - Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(1)), RaidCondition.instance, - "When {this} enters, if you attacked this turn, target opponent discards a card."); + Ability ability = new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(1)).withInterveningIf(RaidCondition.instance); ability.addTarget(new TargetOpponent()); - ability.setAbilityWord(AbilityWord.RAID); - ability.addHint(RaidHint.instance); - this.addAbility(ability, new PlayerAttackedWatcher()); + this.addAbility(ability.setAbilityWord(AbilityWord.RAID).addHint(RaidHint.instance), new PlayerAttackedWatcher()); } private MarduSkullhunter(final MarduSkullhunter card) { diff --git a/Mage.Sets/src/mage/cards/m/MarduWarshrieker.java b/Mage.Sets/src/mage/cards/m/MarduWarshrieker.java index 0acb5bbbb2d..745db07abc7 100644 --- a/Mage.Sets/src/mage/cards/m/MarduWarshrieker.java +++ b/Mage.Sets/src/mage/cards/m/MarduWarshrieker.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.Mana; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.mana.AddManaToManaPoolSourceControllerEffect; import mage.abilities.hint.common.RaidHint; import mage.cards.CardImpl; @@ -30,13 +29,9 @@ public final class MarduWarshrieker extends CardImpl { this.toughness = new MageInt(3); // Raid - When Mardu Warshrieker enters the battlefield, if you attacked this turn, add {R}{W}{B}. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility( - new AddManaToManaPoolSourceControllerEffect(new Mana(1, 0, 1, 1, 0, 0, 0, 0))), - RaidCondition.instance, - "When {this} enters, if you attacked this turn, add {R}{W}{B}.") - .setAbilityWord(AbilityWord.RAID) - .addHint(RaidHint.instance), - new PlayerAttackedWatcher()); + this.addAbility(new EntersBattlefieldTriggeredAbility(new AddManaToManaPoolSourceControllerEffect( + new Mana(1, 0, 1, 1, 0, 0, 0, 0) + ).setText("add {R}{W}{B}")).withInterveningIf(RaidCondition.instance).setAbilityWord(AbilityWord.RAID).addHint(RaidHint.instance), new PlayerAttackedWatcher()); } private MarduWarshrieker(final MarduWarshrieker card) { diff --git a/Mage.Sets/src/mage/cards/m/MarinaVendrellsGrimoire.java b/Mage.Sets/src/mage/cards/m/MarinaVendrellsGrimoire.java index 82a54e1e140..f8618b1edff 100644 --- a/Mage.Sets/src/mage/cards/m/MarinaVendrellsGrimoire.java +++ b/Mage.Sets/src/mage/cards/m/MarinaVendrellsGrimoire.java @@ -7,7 +7,6 @@ import mage.abilities.common.LoseLifeTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.CastFromEverywhereSourceCondition; import mage.abilities.condition.common.HellbentCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.dynamicvalue.common.SavedGainedLifeValue; import mage.abilities.dynamicvalue.common.SavedLifeLossValue; @@ -35,10 +34,8 @@ public final class MarinaVendrellsGrimoire extends CardImpl { this.supertype.add(SuperType.LEGENDARY); // When Marina Vendrell's Grimoire enters, if you cast it, draw five cards. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(5)), - CastFromEverywhereSourceCondition.instance, "When {this} enters, if you cast it, draw five cards." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(5)) + .withInterveningIf(CastFromEverywhereSourceCondition.instance)); // You have no maximum hand size and don't lose the game for having 0 or less life. Ability ability = new SimpleStaticAbility(new MaximumHandSizeControllerEffect( diff --git a/Mage.Sets/src/mage/cards/m/MaritLagesSlumber.java b/Mage.Sets/src/mage/cards/m/MaritLagesSlumber.java index 5753d166982..d5694ada06b 100644 --- a/Mage.Sets/src/mage/cards/m/MaritLagesSlumber.java +++ b/Mage.Sets/src/mage/cards/m/MaritLagesSlumber.java @@ -1,15 +1,14 @@ package mage.cards.m; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.common.SacrificeSourceCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.keyword.ScryEffect; import mage.abilities.hint.ConditionHint; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -28,14 +27,17 @@ public final class MaritLagesSlumber extends CardImpl { private static final FilterPermanent filter = new FilterControlledPermanent("snow permanent"); + private static final FilterPermanent filter2 + = new FilterControlledPermanent("you control ten or more snow permanents"); static { filter.add(SuperType.SNOW.getPredicate()); + filter2.add(SuperType.SNOW.getPredicate()); } private static final Condition condition - = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 9); - private static final ConditionHint hint = new ConditionHint(condition, "You control ten or more snow permanents"); + = new PermanentsOnTheBattlefieldCondition(filter2, ComparisonType.MORE_THAN, 9); + private static final ConditionHint hint = new ConditionHint(condition); public MaritLagesSlumber(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); @@ -49,14 +51,10 @@ public final class MaritLagesSlumber extends CardImpl { )); // 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( - new BeginningOfUpkeepTriggeredAbility(new DoIfCostPaid( - new CreateTokenEffect(new MaritLageToken()), - new SacrificeSourceCost(), "", false - )), condition, "At the beginning of your upkeep, " + - "if you control ten or more snow permanents, sacrifice {this}. If you do, create Marit Lage, " + - "a legendary 20/20 black Avatar creature token with flying and indestructible." - ).addHint(hint)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DoIfCostPaid( + new CreateTokenEffect(new MaritLageToken()), + new SacrificeSourceCost(), "", false + )).withInterveningIf(condition).addHint(hint)); } private MaritLagesSlumber(final MaritLagesSlumber card) { diff --git a/Mage.Sets/src/mage/cards/m/Marjhan.java b/Mage.Sets/src/mage/cards/m/Marjhan.java index 647523eca49..9795dee8330 100644 --- a/Mage.Sets/src/mage/cards/m/Marjhan.java +++ b/Mage.Sets/src/mage/cards/m/Marjhan.java @@ -1,7 +1,5 @@ - package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ControlsPermanentsControllerTriggeredAbility; @@ -10,8 +8,7 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; -import mage.abilities.effects.Effect; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.DontUntapInControllersUntapStepSourceEffect; import mage.abilities.effects.common.SacrificeSourceEffect; @@ -21,17 +18,21 @@ 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.ComparisonType; +import mage.constants.Duration; +import mage.constants.SubType; import mage.filter.StaticFilters; import mage.filter.common.FilterAttackingCreature; import mage.filter.common.FilterLandPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class Marjhan extends CardImpl { @@ -52,8 +53,9 @@ public final class Marjhan extends CardImpl { this.addAbility(new SimpleStaticAbility(new DontUntapInControllersUntapStepSourceEffect())); // {U}{U}, Sacrifice a creature: Untap Marjhan. Activate this ability only during your upkeep. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, - new UntapSourceEffect(), new ManaCostsImpl<>("{U}{U}"), new IsStepCondition(PhaseStep.UPKEEP), null); + Ability ability = new ActivateIfConditionActivatedAbility( + new UntapSourceEffect(), new ManaCostsImpl<>("{U}{U}"), IsStepCondition.getMyUpkeep() + ); ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_CREATURE)); this.addAbility(ability); @@ -63,7 +65,7 @@ public final class Marjhan extends CardImpl { // {U}{U}: Marjhan gets -1/-0 until end of turn and deals 1 damage to target attacking creature without flying. ability = new SimpleActivatedAbility(new BoostSourceEffect(-1, 0, Duration.EndOfTurn), new ManaCostsImpl<>("{U}{U}")); ability.addEffect(new DamageTargetEffect(1, "and")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // When you control no Islands, sacrifice Marjhan. diff --git a/Mage.Sets/src/mage/cards/m/MarkForDeath.java b/Mage.Sets/src/mage/cards/m/MarkForDeath.java index b533b5b8f0f..56fcc4e39c0 100644 --- a/Mage.Sets/src/mage/cards/m/MarkForDeath.java +++ b/Mage.Sets/src/mage/cards/m/MarkForDeath.java @@ -18,9 +18,12 @@ import mage.filter.predicate.mageobject.CardIdPredicate; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author jeffwadsworth @@ -32,7 +35,7 @@ public final class MarkForDeath extends CardImpl { // Target creature an opponent controls blocks this turn if able. Untap that creature. Other creatures that player controls can't block this turn. this.getSpellAbility().addEffect(new MarkForDeathEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); } private MarkForDeath(final MarkForDeath card) { diff --git a/Mage.Sets/src/mage/cards/m/MarketwatchPhantom.java b/Mage.Sets/src/mage/cards/m/MarketwatchPhantom.java index f1ae73f2d5a..40f7b4a14b2 100644 --- a/Mage.Sets/src/mage/cards/m/MarketwatchPhantom.java +++ b/Mage.Sets/src/mage/cards/m/MarketwatchPhantom.java @@ -1,7 +1,7 @@ package mage.cards.m; import mage.MageInt; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -23,7 +23,7 @@ import java.util.UUID; public final class MarketwatchPhantom extends CardImpl { private static final FilterPermanent filter - = new FilterControlledCreaturePermanent("another creature with power 2 or less"); + = new FilterControlledCreaturePermanent("another creature you control with power 2 or less"); static { filter.add(AnotherPredicate.instance); @@ -39,7 +39,7 @@ public final class MarketwatchPhantom extends CardImpl { this.toughness = new MageInt(2); // Whenever another creature with power 2 or less you control enters, Marketwatch Phantom gains flying until end of turn. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + this.addAbility(new EntersBattlefieldAllTriggeredAbility( new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), filter )); } diff --git a/Mage.Sets/src/mage/cards/m/MarthaJones.java b/Mage.Sets/src/mage/cards/m/MarthaJones.java index 08363a2f3ee..cf8d6b3a06f 100644 --- a/Mage.Sets/src/mage/cards/m/MarthaJones.java +++ b/Mage.Sets/src/mage/cards/m/MarthaJones.java @@ -17,7 +17,7 @@ import mage.constants.SuperType; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -52,7 +52,7 @@ public final class MarthaJones extends CardImpl { ); ability.addEffect(new CantBeBlockedTargetEffect() .setText("and up to one other target creature can't be blocked this turn")); - ability.addTarget(new TargetCreaturePermanent(0, 1, filterOther, false)); + ability.addTarget(new TargetPermanent(0, 1, filterOther)); this.addAbility(ability); // Doctor's companion diff --git a/Mage.Sets/src/mage/cards/m/MartialLaw.java b/Mage.Sets/src/mage/cards/m/MartialLaw.java index dffa0610bff..fa40616f24b 100644 --- a/Mage.Sets/src/mage/cards/m/MartialLaw.java +++ b/Mage.Sets/src/mage/cards/m/MartialLaw.java @@ -1,15 +1,14 @@ - package mage.cards.m; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.effects.common.DetainTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.StaticFilters; -import mage.target.common.TargetCreaturePermanent; +import mage.target.common.TargetOpponentsCreaturePermanent; + +import java.util.UUID; /** * @author LevelX2 @@ -17,14 +16,12 @@ import mage.target.common.TargetCreaturePermanent; public final class MartialLaw extends CardImpl { public MartialLaw(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}{W}"); - + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); // At the beginning of your upkeep, detain target creature an opponent controls. // (Until your next turn, that creature can't attack or block and its activated abilities can't be activated.) Ability ability = new BeginningOfUpkeepTriggeredAbility(new DetainTargetEffect()); - TargetCreaturePermanent target = new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE); - ability.addTarget(target); + ability.addTarget(new TargetOpponentsCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MartyrsSoul.java b/Mage.Sets/src/mage/cards/m/MartyrsSoul.java index f7190ff1b81..e19e16f32c4 100644 --- a/Mage.Sets/src/mage/cards/m/MartyrsSoul.java +++ b/Mage.Sets/src/mage/cards/m/MartyrsSoul.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.ConvokeAbility; import mage.cards.CardImpl; @@ -24,7 +23,7 @@ import java.util.UUID; */ public final class MartyrsSoul extends CardImpl { - private static final FilterPermanent filter = new FilterControlledLandPermanent(); + private static final FilterPermanent filter = new FilterControlledLandPermanent("you control no tapped lands"); static { filter.add(TappedPredicate.TAPPED); @@ -45,12 +44,10 @@ public final class MartyrsSoul extends CardImpl { this.addAbility(new ConvokeAbility()); // When Martyr's Soul enters the battlefield, if you control no tapped lands, put two +1/+1 counters on it. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new AddCountersSourceEffect( - CounterType.P1P1.createInstance(2) - )), condition, "When {this} enters, " + - "if you control no tapped lands, put two +1/+1 counters on it." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)) + .setText("put two +1/+1 counters on it") + ).withInterveningIf(condition)); } private MartyrsSoul(final MartyrsSoul card) { diff --git a/Mage.Sets/src/mage/cards/m/Marut.java b/Mage.Sets/src/mage/cards/m/Marut.java index 8a168a0d724..83a166f8d65 100644 --- a/Mage.Sets/src/mage/cards/m/Marut.java +++ b/Mage.Sets/src/mage/cards/m/Marut.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TreasureSpentToCastCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.CreateTokenEffect; @@ -35,11 +34,9 @@ public final class Marut extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // When Marut enters the battlefield, if mana from a Treasure was spent to cast it, create a Treasure token for each mana from a Treasure spent to cast it. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new TreasureToken(), MarutValue.instance)), - TreasureSpentToCastCondition.instance, "When {this} enters, if mana from a " + - "Treasure was spent to cast it, create a Treasure token for each mana from a Treasure spent to cast it." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new CreateTokenEffect(new TreasureToken(), MarutValue.instance) + ).withInterveningIf(TreasureSpentToCastCondition.instance)); } private Marut(final Marut card) { @@ -67,6 +64,11 @@ enum MarutValue implements DynamicValue { @Override public String getMessage() { - return ""; + return "mana from a Treasure spent to cast it"; + } + + @Override + public String toString() { + return "1"; } } diff --git a/Mage.Sets/src/mage/cards/m/MaskOfIntolerance.java b/Mage.Sets/src/mage/cards/m/MaskOfIntolerance.java index a88e165c016..b4d4df12080 100644 --- a/Mage.Sets/src/mage/cards/m/MaskOfIntolerance.java +++ b/Mage.Sets/src/mage/cards/m/MaskOfIntolerance.java @@ -1,17 +1,14 @@ package mage.cards.m; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.condition.IntCompareCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.DomainValue; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.hint.common.DomainHint; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.ComparisonType; import mage.constants.TargetController; import mage.game.Game; @@ -22,16 +19,13 @@ import java.util.UUID; */ public final class MaskOfIntolerance extends CardImpl { - private static final Condition condition = new MaskOfIntoleranceCondition(); - public MaskOfIntolerance(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); // At the beginning of each player's upkeep, if there are four or more basic land types among lands that player controls, Mask of Intolerance deals 3 damage to that player. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfUpkeepTriggeredAbility( - TargetController.ANY, new DamageTargetEffect(3), false - ), condition, "At the beginning of each player's upkeep, if there are four or more basic land types " + - "among lands that player controls, {this} deals 3 damage to that player.").addHint(DomainHint.instance)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + TargetController.EACH_PLAYER, new DamageTargetEffect(3, true, "that player"), false + ).withInterveningIf(MaskOfIntoleranceCondition.instance).addHint(DomainHint.instance)); } private MaskOfIntolerance(final MaskOfIntolerance card) { @@ -44,14 +38,16 @@ public final class MaskOfIntolerance extends CardImpl { } } -class MaskOfIntoleranceCondition extends IntCompareCondition { +enum MaskOfIntoleranceCondition implements Condition { + instance; - public MaskOfIntoleranceCondition() { - super(ComparisonType.MORE_THAN, 3); + @Override + public boolean apply(Game game, Ability source) { + return DomainValue.ACTIVE.calculate(game, source, null) >= 4; } @Override - protected int getInputValue(Game game, Ability source) { - return DomainValue.ACTIVE.calculate(game, source, null); + public String toString() { + return "there are four or more basic land types among lands that player controls"; } } diff --git a/Mage.Sets/src/mage/cards/m/MaskOfTheMimic.java b/Mage.Sets/src/mage/cards/m/MaskOfTheMimic.java index 438b6efae01..5e38afcef06 100644 --- a/Mage.Sets/src/mage/cards/m/MaskOfTheMimic.java +++ b/Mage.Sets/src/mage/cards/m/MaskOfTheMimic.java @@ -17,6 +17,7 @@ import mage.filter.predicate.mageobject.NamePredicate; import mage.filter.predicate.permanent.TokenPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; @@ -41,7 +42,7 @@ public final class MaskOfTheMimic extends CardImpl { // Search your library for a card with the same name as target nontoken creature and put that card onto the battlefield. Then shuffle your library. this.getSpellAbility().addEffect(new MaskOfTheMimicEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private MaskOfTheMimic(final MaskOfTheMimic card) { diff --git a/Mage.Sets/src/mage/cards/m/MasterOfDiversion.java b/Mage.Sets/src/mage/cards/m/MasterOfDiversion.java index eca0f1d9ded..aed3b066464 100644 --- a/Mage.Sets/src/mage/cards/m/MasterOfDiversion.java +++ b/Mage.Sets/src/mage/cards/m/MasterOfDiversion.java @@ -12,6 +12,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.DefendingPlayerControlsSourceAttackingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -35,7 +36,7 @@ public final class MasterOfDiversion extends CardImpl { // Whenever Master of Diversion attacks, tap target creature defending player controls. Ability ability = new AttacksTriggeredAbility(new TapTargetEffect(), false); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MasterOfTheVeil.java b/Mage.Sets/src/mage/cards/m/MasterOfTheVeil.java index 583aef98668..cee6f88e03b 100644 --- a/Mage.Sets/src/mage/cards/m/MasterOfTheVeil.java +++ b/Mage.Sets/src/mage/cards/m/MasterOfTheVeil.java @@ -1,11 +1,9 @@ package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.TurnedFaceUpSourceTriggeredAbility; -import mage.constants.SubType; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.BecomesFaceDownCreatureAllEffect; @@ -14,6 +12,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicate; import mage.filter.predicate.Predicates; @@ -21,10 +20,11 @@ import mage.filter.predicate.mageobject.AbilityPredicate; import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.game.Game; import mage.target.Target; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class MasterOfTheVeil extends CardImpl { @@ -48,7 +48,7 @@ public final class MasterOfTheVeil extends CardImpl { // When Master of the Veil is turned face up, you may turn target creature with a morph ability face down. Ability ability = new TurnedFaceUpSourceTriggeredAbility(new MasterOfTheVeilEffect(), false, true); - ability.addTarget(new TargetCreaturePermanent(1, 1, filter, false)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MasterOfTheWildHunt.java b/Mage.Sets/src/mage/cards/m/MasterOfTheWildHunt.java index 63e08d01d3c..f784e102b7e 100644 --- a/Mage.Sets/src/mage/cards/m/MasterOfTheWildHunt.java +++ b/Mage.Sets/src/mage/cards/m/MasterOfTheWildHunt.java @@ -2,20 +2,22 @@ package mage.cards.m; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.hint.ValueHint; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.MultiAmountType; +import mage.constants.Outcome; +import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; -import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.game.permanent.token.WolfToken; import mage.players.Player; @@ -39,8 +41,7 @@ public final class MasterOfTheWildHunt extends CardImpl { this.toughness = new MageInt(3); // At the beginning of your upkeep, create a 2/2 green Wolf creature token. - this.addAbility(new OnEventTriggeredAbility(EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", - new CreateTokenEffect(new WolfToken()))); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new WolfToken()))); // {T}: Tap all untapped Wolf creatures you control. Each Wolf tapped this way deals damage equal to its power to target creature. That creature deals damage equal to its power divided as its controller chooses among any number of those Wolves. Ability ability = new SimpleActivatedAbility(new MasterOfTheWildHuntEffect(), new TapSourceCost()); diff --git a/Mage.Sets/src/mage/cards/m/MasterWarcraft.java b/Mage.Sets/src/mage/cards/m/MasterWarcraft.java index 303eb9ed934..8a0c2335fb9 100644 --- a/Mage.Sets/src/mage/cards/m/MasterWarcraft.java +++ b/Mage.Sets/src/mage/cards/m/MasterWarcraft.java @@ -21,7 +21,7 @@ import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.targetpointer.FixedTarget; import mage.watchers.common.ControlCombatRedundancyWatcher; @@ -107,7 +107,7 @@ class MasterWarcraftChooseAttackersEffect extends ContinuousRuleModifyingEffectI if (controller == null || attackingPlayer == null || attackingPlayer.getAvailableAttackers(game).isEmpty()) { return false; // the attack declaration resumes for the active player as normal } - Target target = new TargetCreaturePermanent(0, Integer.MAX_VALUE, filter, true); + Target target = new TargetPermanent(0, Integer.MAX_VALUE, filter, true); if (!controller.chooseTarget(Outcome.Benefit, target, source, game)) { return false; // the attack declaration resumes for the active player as normal } diff --git a/Mage.Sets/src/mage/cards/m/MastermindPlum.java b/Mage.Sets/src/mage/cards/m/MastermindPlum.java index b9fc6d5e3a2..56dd1c61c84 100644 --- a/Mage.Sets/src/mage/cards/m/MastermindPlum.java +++ b/Mage.Sets/src/mage/cards/m/MastermindPlum.java @@ -1,25 +1,18 @@ package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.Condition; -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.Cards; -import mage.cards.CardsImpl; -import mage.constants.Outcome; -import mage.constants.SetTargetPointer; -import mage.constants.SubType; -import mage.constants.SuperType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Zone; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.*; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.token.Token; @@ -29,6 +22,8 @@ import mage.players.Player; import mage.target.common.TargetCardInGraveyard; import mage.watchers.common.ManaPaidSourceWatcher; +import java.util.UUID; + /** * Mastermind Plum {2}{B} * Legendary Creature - Human Wizard 2/2 @@ -54,15 +49,11 @@ public final class MastermindPlum extends CardImpl { this.addAbility(ability); // Whenever you cast a spell, if mana from a Treasure was spent to cast it, you draw a card and you lose 1 life. - ability = new ConditionalInterveningIfTriggeredAbility( - new SpellCastControllerTriggeredAbility( - new DrawCardSourceControllerEffect(1), StaticFilters.FILTER_SPELL, - false, SetTargetPointer.SPELL), - MastermindPlumCondition.instance, - "Whenever you cast a spell, if mana from a Treasure was spent to cast it, " + - "you draw a card and you lose 1 life." - ); - ability.addEffect(new LoseLifeSourceControllerEffect(1)); + ability = new SpellCastControllerTriggeredAbility( + new DrawCardSourceControllerEffect(1, true), + StaticFilters.FILTER_SPELL_A, false, SetTargetPointer.SPELL + ).withInterveningIf(MastermindPlumCondition.instance); + ability.addEffect(new LoseLifeSourceControllerEffect(1).concatBy("and")); this.addAbility(ability); } @@ -120,4 +111,9 @@ enum MastermindPlumCondition implements Condition { Spell spell = (Spell) source.getEffects().get(0).getValue("spellCast"); return spell != null && ManaPaidSourceWatcher.getTreasurePaid(spell.getSourceId(), game) > 0; } + + @Override + public String toString() { + return "mana from a Treasure was spent to cast it"; + } } diff --git a/Mage.Sets/src/mage/cards/m/MastersManufactory.java b/Mage.Sets/src/mage/cards/m/MastersManufactory.java index fbd796afbc6..ed3f49799fa 100644 --- a/Mage.Sets/src/mage/cards/m/MastersManufactory.java +++ b/Mage.Sets/src/mage/cards/m/MastersManufactory.java @@ -12,7 +12,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.WatcherScope; -import mage.constants.Zone; import mage.game.Game; import mage.game.events.EntersTheBattlefieldEvent; import mage.game.events.GameEvent; @@ -27,11 +26,6 @@ import java.util.*; */ public final class MastersManufactory extends CardImpl { - private static final Hint hint = new ConditionHint( - MastersManufactoryCondition.instance, - "{this} or another artifact entered under your control this turn" - ); - public MastersManufactory(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, ""); this.nightCard = true; @@ -40,11 +34,9 @@ public final class MastersManufactory extends CardImpl { // {T}: Create a 4/4 white and blue Golem artifact creature token. Activate only if Master's Manufactory or another artifact entered the battlefield under your control this turn. this.addAbility(new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new CreateTokenEffect(new GolemWhiteBlueToken()), - new TapSourceCost(), - MastersManufactoryCondition.instance - ).addHint(hint), new MastersManufactoryWatcher()); + new TapSourceCost(), MastersManufactoryCondition.instance + ).addHint(MastersManufactoryCondition.getHint()), new MastersManufactoryWatcher()); } private MastersManufactory(final MastersManufactory card) { @@ -59,19 +51,23 @@ public final class MastersManufactory extends CardImpl { enum MastersManufactoryCondition implements Condition { instance; + private static final Hint hint = new ConditionHint(instance); + + public static Hint getHint() { + return hint; + } @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); MastersManufactoryWatcher watcher = game.getState().getWatcher(MastersManufactoryWatcher.class); - return watcher != null - && permanent != null + return watcher != null && permanent != null && watcher.check(source.getControllerId(), new MageObjectReference(permanent, game)); } @Override public String toString() { - return "if {this} or another artifact entered the battlefield under your control this turn"; + return "{this} or another artifact entered the battlefield under your control this turn"; } } diff --git a/Mage.Sets/src/mage/cards/m/MathasFiendSeeker.java b/Mage.Sets/src/mage/cards/m/MathasFiendSeeker.java index bf12a53d574..3ff467d78a0 100644 --- a/Mage.Sets/src/mage/cards/m/MathasFiendSeeker.java +++ b/Mage.Sets/src/mage/cards/m/MathasFiendSeeker.java @@ -1,40 +1,29 @@ - package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.DiesSourceTriggeredAbility; -import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.DrawCardAllEffect; -import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.effects.common.GainLifeAllEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.keyword.MenaceAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; 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.SuperType; -import mage.constants.TargetController; +import mage.constants.*; 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.TargetCreaturePermanent; +import mage.target.common.TargetOpponentsCreaturePermanent; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class MathasFiendSeeker extends CardImpl { - private static final String rule = "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.\""; - public MathasFiendSeeker(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}{W}{B}"); @@ -47,12 +36,11 @@ public final class MathasFiendSeeker extends CardImpl { this.addAbility(new MenaceAbility(false)); // 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 BeginningOfEndStepTriggeredAbility(new AddCountersTargetEffect(CounterType.BOUNTY.createInstance())); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); - Ability ability2 = new DiesSourceTriggeredAbility(new DrawCardAllEffect(1, TargetController.OPPONENT)); - ability2.addEffect(new OpponentsGainLifeEffect()); - Effect effect = new MathasFiendSeekerGainAbilityEffect(ability2, Duration.Custom, rule); - ability.addEffect(effect); + Ability ability = new BeginningOfEndStepTriggeredAbility( + new AddCountersTargetEffect(CounterType.BOUNTY.createInstance()) + ); + ability.addEffect(new MathasFiendSeekerEffect()); + ability.addTarget(new TargetOpponentsCreaturePermanent()); this.addAbility(ability); } @@ -66,56 +54,36 @@ public final class MathasFiendSeeker extends CardImpl { } } -class MathasFiendSeekerGainAbilityEffect extends GainAbilityTargetEffect { +class MathasFiendSeekerEffect extends ContinuousEffectImpl { - MathasFiendSeekerGainAbilityEffect(Ability ability, Duration duration, String rule) { - super(ability, duration, rule); + private final Ability ability; + + MathasFiendSeekerEffect() { + super(Duration.Custom, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + staticText = "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.\""; + this.ability = new DiesSourceTriggeredAbility(new DrawCardAllEffect(1, TargetController.OPPONENT)); + this.ability.addEffect(new GainLifeAllEffect(2, TargetController.OPPONENT).setText("and gains 2 life")); } - private MathasFiendSeekerGainAbilityEffect(final MathasFiendSeekerGainAbilityEffect effect) { + private MathasFiendSeekerEffect(final MathasFiendSeekerEffect effect) { super(effect); + this.ability = effect.ability.copy(); } @Override - public boolean isInactive(Ability source, Game game) { - Permanent creature = game.getPermanent(this.getTargetPointer().getFirst(game, source)); - if (creature != null && creature.getCounters(game).getCount(CounterType.BOUNTY) < 1) { - return true; - } - return false; - } - - @Override - public MathasFiendSeekerGainAbilityEffect copy() { - return new MathasFiendSeekerGainAbilityEffect(this); - } -} - -class OpponentsGainLifeEffect extends OneShotEffect { - - OpponentsGainLifeEffect() { - super(Outcome.GainLife); - staticText = "and gains 2 life."; - } - - private OpponentsGainLifeEffect(final OpponentsGainLifeEffect effect) { - super(effect); - } - - @Override - public OpponentsGainLifeEffect copy() { - return new OpponentsGainLifeEffect(this); + public MathasFiendSeekerEffect copy() { + return new MathasFiendSeekerEffect(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 && game.isOpponent(player, source.getControllerId())) { - player.gainLife(2, game, source); - } + Permanent creature = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + if (creature == null || !creature.getCounters(game).containsKey(CounterType.BOUNTY)) { + discard(); + return false; } + creature.addAbility(ability, source.getSourceId(), game); return true; } - } diff --git a/Mage.Sets/src/mage/cards/m/MatsuTribeSniper.java b/Mage.Sets/src/mage/cards/m/MatsuTribeSniper.java index eee0f6b76cb..e6347dc4070 100644 --- a/Mage.Sets/src/mage/cards/m/MatsuTribeSniper.java +++ b/Mage.Sets/src/mage/cards/m/MatsuTribeSniper.java @@ -18,6 +18,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -43,7 +44,7 @@ public final class MatsuTribeSniper extends CardImpl { // {t}: Matsu-Tribe Sniper deals 1 damage to target creature with flying. Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // Whenever Matsu-Tribe Sniper deals damage to a creature, tap that creature and it doesn't untap during its controller's next untap step. diff --git a/Mage.Sets/src/mage/cards/m/MatzalantliTheGreatDoor.java b/Mage.Sets/src/mage/cards/m/MatzalantliTheGreatDoor.java index 3152e2d0860..04f0ff0b214 100644 --- a/Mage.Sets/src/mage/cards/m/MatzalantliTheGreatDoor.java +++ b/Mage.Sets/src/mage/cards/m/MatzalantliTheGreatDoor.java @@ -5,7 +5,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.IntCompareCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DrawDiscardControllerEffect; @@ -43,7 +43,7 @@ public final class MatzalantliTheGreatDoor extends CardImpl { // {4}, {T}: Transform Matzalantli, the Great Door. Activate only if there are four or more permanent types among cards in your graveyard. this.addAbility(new TransformAbility()); - Ability ability = new ConditionalActivatedAbility( + Ability ability = new ActivateIfConditionActivatedAbility( new TransformSourceEffect(), new GenericManaCost(4), new MatzalantliTheGreatDoorCondition() @@ -118,4 +118,4 @@ enum MatzalantliTheGreatDoorValue implements DynamicValue { public String toString() { return "X"; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/m/MausoleumHarpy.java b/Mage.Sets/src/mage/cards/m/MausoleumHarpy.java index 0c1deab303f..f666a9469af 100644 --- a/Mage.Sets/src/mage/cards/m/MausoleumHarpy.java +++ b/Mage.Sets/src/mage/cards/m/MausoleumHarpy.java @@ -3,7 +3,6 @@ package mage.cards.m; import mage.MageInt; import mage.abilities.common.DiesCreatureTriggeredAbility; import mage.abilities.condition.common.CitysBlessingCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.hint.common.CitysBlessingHint; import mage.abilities.keyword.AscendAbility; @@ -36,12 +35,10 @@ public final class MausoleumHarpy extends CardImpl { this.addAbility(new AscendAbility()); // Whenever another creature you control dies, if you have the city's blessing, put a +1/+1 counter on Mausoleum Harpy. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new DiesCreatureTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false, StaticFilters.FILTER_ANOTHER_CREATURE_YOU_CONTROL), - CitysBlessingCondition.instance, - "Whenever another creature you control dies, if you have the city's blessing, put a +1/+1 counter on {this}.") - .addHint(CitysBlessingHint.instance)); - + this.addAbility(new DiesCreatureTriggeredAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false, + StaticFilters.FILTER_ANOTHER_CREATURE_YOU_CONTROL + ).withInterveningIf(CitysBlessingCondition.instance).addHint(CitysBlessingHint.instance)); } private MausoleumHarpy(final MausoleumHarpy card) { diff --git a/Mage.Sets/src/mage/cards/m/MausoleumTurnkey.java b/Mage.Sets/src/mage/cards/m/MausoleumTurnkey.java index 5e95ea8d9c5..a5427501f26 100644 --- a/Mage.Sets/src/mage/cards/m/MausoleumTurnkey.java +++ b/Mage.Sets/src/mage/cards/m/MausoleumTurnkey.java @@ -1,32 +1,31 @@ - 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.cards.Card; +import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; 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.SubType; import mage.filter.common.FilterCreatureCard; -import mage.filter.predicate.card.OwnerIdPredicate; import mage.game.Game; import mage.players.Player; import mage.target.Target; -import mage.target.common.TargetCardInGraveyard; +import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetOpponent; +import mage.target.targetadjustment.TargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class MausoleumTurnkey extends CardImpl { + private static final FilterCreatureCard filter = new FilterCreatureCard("creature card of an opponent's choice"); + public MausoleumTurnkey(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); @@ -36,8 +35,10 @@ public final class MausoleumTurnkey extends CardImpl { this.toughness = new MageInt(2); // When Mausoleum Turnkey enters the battlefield, return target creature card of an opponent's choice from your graveyard to your hand. - this.addAbility(new EntersBattlefieldTriggeredAbility(new MausoleumTurnkeyEffect(), false)); - + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect()); + ability.addTarget(new TargetCardInYourGraveyard(filter)); + ability.setTargetAdjuster(MausoleumTurnkeyAdjuster.instance); + this.addAbility(ability); } private MausoleumTurnkey(final MausoleumTurnkey card) { @@ -50,50 +51,27 @@ public final class MausoleumTurnkey extends CardImpl { } } -class MausoleumTurnkeyEffect extends OneShotEffect { - - MausoleumTurnkeyEffect() { - super(Outcome.Benefit); - this.staticText = "return target creature card of an opponent's choice from your graveyard to your hand"; - } - - private MausoleumTurnkeyEffect(final MausoleumTurnkeyEffect effect) { - super(effect); - } +// Exact copy of KarplusanMinotaurAdjuster +enum MausoleumTurnkeyAdjuster implements TargetAdjuster { + instance; @Override - public MausoleumTurnkeyEffect copy() { - return new MausoleumTurnkeyEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - UUID opponentId = null; - if (game.getOpponents(controller.getId()).size() > 1) { - Target target = new TargetOpponent(true); - if (controller.chooseTarget(outcome, target, source, game)) { - opponentId = target.getFirstTarget(); - } - } else { - opponentId = game.getOpponents(controller.getId()).iterator().next(); - } - if (opponentId != null) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - FilterCreatureCard filter = new FilterCreatureCard("creature card from " + controller.getLogName() + " graveyard"); - filter.add(new OwnerIdPredicate(controller.getId())); - Target target = new TargetCardInGraveyard(filter); - opponent.chooseTarget(outcome, target, source, game); - Card card = game.getCard(target.getFirstTarget()); - if (card != null) { - controller.moveCards(card, Zone.HAND, source, game); - } - } - } - return true; + public void adjustTargets(Ability ability, Game game) { + Player controller = game.getPlayer(ability.getControllerId()); + if (controller == null) { + return; + } + UUID opponentId = null; + if (game.getOpponents(controller.getId()).size() > 1) { + Target target = new TargetOpponent(true); + if (controller.chooseTarget(Outcome.Neutral, target, ability, game)) { + opponentId = target.getFirstTarget(); + } + } else { + opponentId = game.getOpponents(controller.getId()).iterator().next(); + } + if (opponentId != null) { + ability.getTargets().get(0).setTargetController(opponentId); } - return false; } } diff --git a/Mage.Sets/src/mage/cards/m/MazesMantle.java b/Mage.Sets/src/mage/cards/m/MazesMantle.java index 3970420af8c..df561e997a7 100644 --- a/Mage.Sets/src/mage/cards/m/MazesMantle.java +++ b/Mage.Sets/src/mage/cards/m/MazesMantle.java @@ -3,9 +3,8 @@ package mage.cards.m; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.AttachedToMatchesFilterCondition; -import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.continuous.BoostEnchantedEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; @@ -24,6 +23,15 @@ import mage.target.common.TargetCreaturePermanent; import java.util.UUID; public class MazesMantle extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("enchanted creature has toxic"); + + static { + filter.add(new AbilityPredicate(ToxicAbility.class)); + } + + private static final Condition condition = new AttachedToMatchesFilterCondition(filter); + public MazesMantle(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); this.addSubType(SubType.AURA); @@ -39,13 +47,9 @@ public class MazesMantle extends CardImpl { this.addAbility(ability); //When Maze’s Mantle enters the battlefield, if enchanted creature has toxic, that creature gains hexproof until end of turn. - FilterPermanent filter = new FilterPermanent("if enchanted creature has toxic"); - filter.add(new AbilityPredicate(ToxicAbility.class)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility( - new GainAbilityAttachedEffect(HexproofAbility.getInstance(), AttachmentType.AURA, Duration.EndOfTurn)), - new AttachedToMatchesFilterCondition(filter), "When {this} enters, " + - "if enchanted creature has toxic, that creature gains hexproof until end of turn." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainAbilityAttachedEffect( + HexproofAbility.getInstance(), AttachmentType.AURA, Duration.EndOfTurn + ).setText("that creature gains hexproof until end of turn")).withInterveningIf(condition)); //Enchanted creature gets +2/+2. this.addAbility(new SimpleStaticAbility(new BoostEnchantedEffect(2, 2, Duration.WhileOnBattlefield))); diff --git a/Mage.Sets/src/mage/cards/m/MemoriesReturning.java b/Mage.Sets/src/mage/cards/m/MemoriesReturning.java index a5b7c0e15b0..9e5c58141f6 100644 --- a/Mage.Sets/src/mage/cards/m/MemoriesReturning.java +++ b/Mage.Sets/src/mage/cards/m/MemoriesReturning.java @@ -74,6 +74,7 @@ class MemoriesReturningEffect extends OneShotEffect { } TargetPlayer target = new TargetOpponent(); target.withNotTarget(true); + controller.choose(Outcome.Neutral, target, source, game); Player opponent = game.getPlayer(target.getFirstTarget()); if (putCardOnBottom(controller, opponent, cards, source, game)) { return true; diff --git a/Mage.Sets/src/mage/cards/m/MerfolkAssassin.java b/Mage.Sets/src/mage/cards/m/MerfolkAssassin.java index 98873f31acd..19d2af39adf 100644 --- a/Mage.Sets/src/mage/cards/m/MerfolkAssassin.java +++ b/Mage.Sets/src/mage/cards/m/MerfolkAssassin.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,7 +39,7 @@ public final class MerfolkAssassin extends CardImpl { // {tap}: Destroy target creature with islandwalk. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MerfolkSeastalkers.java b/Mage.Sets/src/mage/cards/m/MerfolkSeastalkers.java index 2d4d25f7e49..ca389f8ba5d 100644 --- a/Mage.Sets/src/mage/cards/m/MerfolkSeastalkers.java +++ b/Mage.Sets/src/mage/cards/m/MerfolkSeastalkers.java @@ -16,6 +16,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class MerfolkSeastalkers extends CardImpl { this.addAbility(new IslandwalkAbility()); SimpleActivatedAbility ability = new SimpleActivatedAbility(new TapTargetEffect(), new ManaCostsImpl<>("{2}{U}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MerfolkSovereign.java b/Mage.Sets/src/mage/cards/m/MerfolkSovereign.java index ca499fa5ac7..08dd298229a 100644 --- a/Mage.Sets/src/mage/cards/m/MerfolkSovereign.java +++ b/Mage.Sets/src/mage/cards/m/MerfolkSovereign.java @@ -14,6 +14,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -43,7 +44,7 @@ public final class MerfolkSovereign extends CardImpl { // {tap}: Target Merfolk creature can't be blocked this turn. Ability ability = new SimpleActivatedAbility(new CantBeBlockedTargetEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter2)); + ability.addTarget(new TargetPermanent(filter2)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MerfolkWindrobber.java b/Mage.Sets/src/mage/cards/m/MerfolkWindrobber.java index f5e341bca31..3d5a9c30432 100644 --- a/Mage.Sets/src/mage/cards/m/MerfolkWindrobber.java +++ b/Mage.Sets/src/mage/cards/m/MerfolkWindrobber.java @@ -1,25 +1,19 @@ package mage.cards.m; -import java.util.UUID; - import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.ActivateIfConditionActivatedAbility; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.condition.common.CardsInOpponentGraveyardCondition; import mage.abilities.costs.common.SacrificeSourceCost; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.MillCardsTargetEffect; -import mage.constants.SubType; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.DamagedPlayerEvent; -import mage.game.events.GameEvent; -import mage.target.targetpointer.FixedTarget; +import mage.constants.SubType; + +import java.util.UUID; /** * @author TheElk801 @@ -38,11 +32,13 @@ public final class MerfolkWindrobber extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Whenever Merfolk Windrobber deals combat damage to a player, that player mills a card. - this.addAbility(new MerfolkWindrobberTriggeredAbility()); + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility( + new MillCardsTargetEffect(1), false, true + )); // Sacrifice Merfolk Windrobber: Draw a card. Activate this ability only if an opponent has eight or more cards in their graveyard. this.addAbility(new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), + new DrawCardSourceControllerEffect(1), new SacrificeSourceCost(), CardsInOpponentGraveyardCondition.EIGHT ).addHint(CardsInOpponentGraveyardCondition.EIGHT.getHint())); } @@ -56,41 +52,3 @@ public final class MerfolkWindrobber extends CardImpl { return new MerfolkWindrobber(this); } } - -class MerfolkWindrobberTriggeredAbility extends TriggeredAbilityImpl { - - public MerfolkWindrobberTriggeredAbility() { - super(Zone.BATTLEFIELD, new MillCardsTargetEffect(1)); - } - - private MerfolkWindrobberTriggeredAbility(final MerfolkWindrobberTriggeredAbility ability) { - super(ability); - } - - @Override - public MerfolkWindrobberTriggeredAbility copy() { - return new MerfolkWindrobberTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event; - if (damageEvent.isCombatDamage() && event.getSourceId().equals(this.getSourceId())) { - for (Effect effect : this.getEffects()) { - effect.setTargetPointer(new FixedTarget(event.getPlayerId())); - } - return true; - } - return false; - } - - @Override - public String getRule() { - return "Whenever {this} deals combat damage to a player, that player mills a card."; - } -} diff --git a/Mage.Sets/src/mage/cards/m/MeriadocBrandybuck.java b/Mage.Sets/src/mage/cards/m/MeriadocBrandybuck.java index cde68efd66b..09c7d3c85cc 100644 --- a/Mage.Sets/src/mage/cards/m/MeriadocBrandybuck.java +++ b/Mage.Sets/src/mage/cards/m/MeriadocBrandybuck.java @@ -1,17 +1,16 @@ package mage.cards.m; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SetTargetPointer; import mage.constants.SubType; import mage.constants.SuperType; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.DefenderAttackedEvent; -import mage.game.events.GameEvent; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; import mage.game.permanent.token.FoodToken; import java.util.UUID; @@ -20,6 +19,7 @@ import java.util.UUID; * @author TheElk801 */ public final class MeriadocBrandybuck extends CardImpl { + FilterPermanent filter = new FilterControlledPermanent(SubType.HALFLING,"Halflings you control"); public MeriadocBrandybuck(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); @@ -31,7 +31,7 @@ public final class MeriadocBrandybuck extends CardImpl { this.toughness = new MageInt(2); // Whenever one or more Halflings you control attack a player, create a Food token. - this.addAbility(new MeriadocBrandybuckTriggeredAbility()); + this.addAbility(new AttacksPlayerWithCreaturesTriggeredAbility(new CreateTokenEffect(new FoodToken()), filter, SetTargetPointer.NONE)); } private MeriadocBrandybuck(final MeriadocBrandybuck card) { @@ -43,35 +43,3 @@ public final class MeriadocBrandybuck extends CardImpl { return new MeriadocBrandybuck(this); } } - -class MeriadocBrandybuckTriggeredAbility extends TriggeredAbilityImpl { - - MeriadocBrandybuckTriggeredAbility() { - super(Zone.BATTLEFIELD, new CreateTokenEffect(new FoodToken())); - setTriggerPhrase("Whenever one or more Halflings you control attack a player, "); - } - - private MeriadocBrandybuckTriggeredAbility(final MeriadocBrandybuckTriggeredAbility ability) { - super(ability); - } - - @Override - public MeriadocBrandybuckTriggeredAbility copy() { - return new MeriadocBrandybuckTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DEFENDER_ATTACKED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return isControlledBy(event.getPlayerId()) - && game.getPlayer(event.getTargetId()) != null - && ((DefenderAttackedEvent) event) - .getAttackers(game) - .stream() - .anyMatch(permanent -> permanent.hasSubtype(SubType.HALFLING, game)); - } -} diff --git a/Mage.Sets/src/mage/cards/m/MetallurgicSummonings.java b/Mage.Sets/src/mage/cards/m/MetallurgicSummonings.java index deb5729a571..42261b5ec34 100644 --- a/Mage.Sets/src/mage/cards/m/MetallurgicSummonings.java +++ b/Mage.Sets/src/mage/cards/m/MetallurgicSummonings.java @@ -1,26 +1,27 @@ - package mage.cards.m; import mage.abilities.Ability; import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.common.ExileSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.filter.FilterSpell; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.StaticFilters; import mage.filter.common.FilterControlledArtifactPermanent; -import mage.filter.common.FilterInstantOrSorceryCard; -import mage.filter.predicate.Predicates; import mage.game.Game; import mage.game.permanent.token.MetallurgicSummoningsConstructToken; import mage.game.stack.Spell; import mage.players.Player; +import java.util.Optional; import java.util.UUID; /** @@ -28,26 +29,23 @@ import java.util.UUID; */ public final class MetallurgicSummonings extends CardImpl { - private static final FilterSpell filter = new FilterSpell("an instant or sorcery spell"); - - static { - filter.add(Predicates.or( - CardType.INSTANT.getPredicate(), - CardType.SORCERY.getPredicate())); - } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledArtifactPermanent("you control six or more artifacts"), + ComparisonType.MORE_THAN, 5 + ); public MetallurgicSummonings(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}{U}"); // Whenever you cast an instant or sorcery spell, create an X/X colorless Construct artifact creature token, where X is that spell's converted mana cost. - this.addAbility(new SpellCastControllerTriggeredAbility(new MetallurgicSummoningsTokenEffect(), filter, false, SetTargetPointer.SPELL)); + this.addAbility(new SpellCastControllerTriggeredAbility( + new MetallurgicSummoningsTokenEffect(), StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false + )); // {3}{U}{U}, Exile Metallurgic Summons: Return all instant and sorcery cards from your graveyard to your hand. Activate this ability only if you control six or more artifacts. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, - new MetallurgicSummoningsReturnEffect(), new ManaCostsImpl<>("{3}{U}{U}"), - new PermanentsOnTheBattlefieldCondition(new FilterControlledArtifactPermanent(), ComparisonType.MORE_THAN, 5), - "{3}{U}{U}, Exile {this}: Return all instant and sorcery cards from your graveyard to your hand." - + " Activate only if you control six or more artifacts."); + Ability ability = new ActivateIfConditionActivatedAbility( + new MetallurgicSummoningsReturnEffect(), new ManaCostsImpl<>("{3}{U}{U}"), condition + ); ability.addCost(new ExileSourceCost()); this.addAbility(ability); } @@ -75,15 +73,11 @@ class MetallurgicSummoningsTokenEffect 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.getManaValue(); - if (cmc > 0) { - return new CreateTokenEffect(new MetallurgicSummoningsConstructToken(cmc)).apply(game, source); - } - return true; - } - return false; + int mv = Optional + .ofNullable((Spell) getValue("spellCast")) + .map(Spell::getManaValue) + .orElse(0); + return new MetallurgicSummoningsConstructToken(mv).putOntoBattlefield(1, game, source); } @Override @@ -96,7 +90,7 @@ class MetallurgicSummoningsReturnEffect extends OneShotEffect { MetallurgicSummoningsReturnEffect() { super(Outcome.PutCardInPlay); - this.staticText = "Return all instant and sorcery cards from your graveyard to your hand. Activate only if you control six or more artifacts"; + this.staticText = "return all instant and sorcery cards from your graveyard to your hand"; } private MetallurgicSummoningsReturnEffect(final MetallurgicSummoningsReturnEffect effect) { @@ -111,10 +105,11 @@ class MetallurgicSummoningsReturnEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - return controller.moveCards(controller.getGraveyard().getCards(new FilterInstantOrSorceryCard(), - source.getControllerId(), source, game), Zone.HAND, source, game); - } - return false; + return controller != null && controller.moveCards( + controller.getGraveyard().getCards( + StaticFilters.FILTER_CARDS_INSTANT_AND_SORCERY, + source.getControllerId(), source, game + ), Zone.HAND, source, game + ); } } diff --git a/Mage.Sets/src/mage/cards/m/MeticulousExcavation.java b/Mage.Sets/src/mage/cards/m/MeticulousExcavation.java index 3847f745780..7b31635c5e4 100644 --- a/Mage.Sets/src/mage/cards/m/MeticulousExcavation.java +++ b/Mage.Sets/src/mage/cards/m/MeticulousExcavation.java @@ -28,8 +28,7 @@ public final class MeticulousExcavation extends CardImpl { // {2}{W}: Return target permanent you control to its owner's hand. If it has unearth, instead exile it, then return that card to its owner's hand. Activate only during your turn. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new MeticulousExcavationEffect(), - new ManaCostsImpl<>("{2}{W}"), MyTurnCondition.instance + new MeticulousExcavationEffect(), new ManaCostsImpl<>("{2}{W}"), MyTurnCondition.instance ); ability.addTarget(new TargetControlledPermanent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/m/MightMakesRight.java b/Mage.Sets/src/mage/cards/m/MightMakesRight.java index 570b2f2a3af..4d45e70af2e 100644 --- a/Mage.Sets/src/mage/cards/m/MightMakesRight.java +++ b/Mage.Sets/src/mage/cards/m/MightMakesRight.java @@ -1,47 +1,48 @@ - package mage.cards.m; -import java.util.List; -import java.util.UUID; +import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.TriggeredAbility; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.abilities.keyword.HasteAbility; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.filter.StaticFilters; -import mage.filter.common.FilterCreaturePermanent; +import mage.game.Controllable; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.List; +import java.util.UUID; + +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * @author Quercitron */ public final class MightMakesRight extends CardImpl { - private static final String ruleText = "At the beginning of combat on your turn, if you control each creature on the battlefield with the greatest power, " - + "gain control of target creature an opponent controls until end of turn. Untap that creature. It gains haste until end of turn."; - public MightMakesRight(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{5}{R}"); - // At the beginning of combat on your turn, if you control each creature on the battlefield with the greatest power, gain control // of target creature an opponent controls until end of turn. Untap that creature. It gains haste until end of turn. - TriggeredAbility gainControlAbility = new BeginningOfCombatTriggeredAbility(new GainControlTargetEffect(Duration.EndOfTurn)); - gainControlAbility.addEffect(new UntapTargetEffect()); - gainControlAbility.addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn)); - gainControlAbility.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); - Ability conditionalAbility = new ConditionalInterveningIfTriggeredAbility(gainControlAbility, ControlsEachCreatureWithGreatestPowerCondition.instance, ruleText); - this.addAbility(conditionalAbility); + Ability ability = new BeginningOfCombatTriggeredAbility(new GainControlTargetEffect(Duration.EndOfTurn)) + .withInterveningIf(ControlsEachCreatureWithGreatestPowerCondition.instance); + ability.addEffect(new UntapTargetEffect("Untap that creature")); + ability.addEffect(new GainAbilityTargetEffect( + HasteAbility.getInstance(), Duration.EndOfTurn + ).setText("It gains haste until end of turn")); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); + this.addAbility(ability); } private MightMakesRight(final MightMakesRight card) { @@ -55,30 +56,31 @@ public final class MightMakesRight extends CardImpl { } enum ControlsEachCreatureWithGreatestPowerCondition implements Condition { - instance; - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); - @Override public boolean apply(Game game, Ability source) { - Integer maxPower = null; - boolean result = false; - List permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game); - for (Permanent permanent : permanents) { - if (permanent == null) { - continue; - } - int power = permanent.getPower().getValue(); - if (maxPower == null || power > maxPower) { - maxPower = permanent.getPower().getValue(); - result = true; - } - if (power == maxPower) { - result &= permanent.isControlledBy(source.getControllerId()); - } + List permanents = game.getBattlefield().getActivePermanents( + StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source, game + ); + if (permanents.isEmpty()) { + return false; } - return result; + int max = permanents + .stream() + .map(MageObject::getPower) + .mapToInt(MageInt::getValue) + .max() + .orElse(Integer.MIN_VALUE); + return permanents + .stream() + .filter(permanent -> permanent.getPower().getValue() >= max) + .map(Controllable::getControllerId) + .allMatch(source::isControlledBy); } + @Override + public String toString() { + return "you control each creature on the battlefield with the greatest power"; + } } diff --git a/Mage.Sets/src/mage/cards/m/MightWeaver.java b/Mage.Sets/src/mage/cards/m/MightWeaver.java index 29dc9d2cea2..8d2d8000e17 100644 --- a/Mage.Sets/src/mage/cards/m/MightWeaver.java +++ b/Mage.Sets/src/mage/cards/m/MightWeaver.java @@ -18,6 +18,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -42,7 +43,7 @@ public final class MightWeaver extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn), new GenericManaCost(2)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MightyEmergence.java b/Mage.Sets/src/mage/cards/m/MightyEmergence.java index be78171d7f6..f1bbae84c35 100644 --- a/Mage.Sets/src/mage/cards/m/MightyEmergence.java +++ b/Mage.Sets/src/mage/cards/m/MightyEmergence.java @@ -1,8 +1,6 @@ package mage.cards.m; -import java.util.UUID; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; -import mage.abilities.effects.Effect; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -11,28 +9,31 @@ import mage.constants.ComparisonType; import mage.constants.SetTargetPointer; import mage.constants.Zone; import mage.counters.CounterType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import java.util.UUID; + /** - * * @author Plopman */ public final class MightyEmergence extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("a creature with power 5 or greater"); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("a creature you control with power 5 or greater"); static { filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 4)); } public MightyEmergence(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); // Whenever a creature with power 5 or greater you control enters, you may put two +1/+1 counters on it. - Effect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance(2)); - effect.setText("you may put two +1/+1 counters on it"); - this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, effect, filter, true, SetTargetPointer.PERMANENT)); + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.P1P1.createInstance(2)) + .setText("put two +1/+1 counters on it"), filter, true, SetTargetPointer.PERMANENT + )); } private MightyEmergence(final MightyEmergence card) { diff --git a/Mage.Sets/src/mage/cards/m/MilesTailsPrower.java b/Mage.Sets/src/mage/cards/m/MilesTailsPrower.java new file mode 100644 index 00000000000..0c6d3459eee --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MilesTailsPrower.java @@ -0,0 +1,95 @@ +package mage.cards.m; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.FlashAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.game.Controllable; +import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.Optional; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class MilesTailsPrower extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.VEHICLE); + + public MilesTailsPrower(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{U}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.FOX); + this.subtype.add(SubType.ARTIFICER); + this.power = new MageInt(3); + this.toughness = new MageInt(1); + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Whenever a Vehicle you control enters, draw a card if it has flying. Otherwise, put a flying counter on it. + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + Zone.BATTLEFIELD, new MilesTailsProwerEffect(), filter, false, SetTargetPointer.PERMANENT + )); + } + + private MilesTailsPrower(final MilesTailsPrower card) { + super(card); + } + + @Override + public MilesTailsPrower copy() { + return new MilesTailsPrower(this); + } +} + +class MilesTailsProwerEffect extends OneShotEffect { + + MilesTailsProwerEffect() { + super(Outcome.Benefit); + staticText = "draw a card if it has flying. Otherwise, put a flying counter on it"; + } + + private MilesTailsProwerEffect(final MilesTailsProwerEffect effect) { + super(effect); + } + + @Override + public MilesTailsProwerEffect copy() { + return new MilesTailsProwerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = (Permanent) getValue("permanentEnteringBattlefield"); + if (permanent == null) { + return false; + } + if (permanent.hasAbility(FlyingAbility.getInstance(), game)) { + return Optional + .ofNullable(source) + .map(Controllable::getControllerId) + .map(game::getPlayer) + .filter(player -> player.drawCards(1, source, game) > 0) + .isPresent(); + } + return Optional + .ofNullable(getTargetPointer().getFirstTargetPermanentOrLKI(game, source)) + .filter(p -> p.addCounters(CounterType.FLYING.createInstance(), source, game)) + .isPresent(); + } +} diff --git a/Mage.Sets/src/mage/cards/m/MinamoSightbender.java b/Mage.Sets/src/mage/cards/m/MinamoSightbender.java index 5120222bc51..7b4b16a5072 100644 --- a/Mage.Sets/src/mage/cards/m/MinamoSightbender.java +++ b/Mage.Sets/src/mage/cards/m/MinamoSightbender.java @@ -13,6 +13,7 @@ import mage.constants.ComparisonType; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetadjustment.PowerTargetAdjuster; @@ -36,7 +37,7 @@ public final class MinamoSightbender extends CardImpl { // {X}, {T}: Target creature with power X or less can't be blocked this turn. Ability ability = new SimpleActivatedAbility(new CantBeBlockedTargetEffect(), new ManaCostsImpl<>("{X}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); ability.setTargetAdjuster(new PowerTargetAdjuster(ComparisonType.OR_LESS)); ability.addCost(new TapSourceCost()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/m/MinasTirith.java b/Mage.Sets/src/mage/cards/m/MinasTirith.java index a7ef0249a44..6e580899c59 100644 --- a/Mage.Sets/src/mage/cards/m/MinasTirith.java +++ b/Mage.Sets/src/mage/cards/m/MinasTirith.java @@ -16,7 +16,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SuperType; import mage.constants.WatcherScope; -import mage.constants.Zone; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.game.Game; @@ -54,7 +53,7 @@ public final class MinasTirith extends CardImpl { // {1}{W}, {T}: Draw a card. Activate only if you attacked with two or more creatures this turn. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), + new DrawCardSourceControllerEffect(1), new ManaCostsImpl<>("{1}{W}"), MinasTirithCondition.instance ); ability.addCost(new TapSourceCost()); diff --git a/Mage.Sets/src/mage/cards/m/MindlinkMech.java b/Mage.Sets/src/mage/cards/m/MindlinkMech.java index 4e7a8387228..c1f283c996c 100644 --- a/Mage.Sets/src/mage/cards/m/MindlinkMech.java +++ b/Mage.Sets/src/mage/cards/m/MindlinkMech.java @@ -12,25 +12,25 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.MageObjectReferencePredicate; import mage.filter.predicate.mageobject.ManaValuePredicate; +import mage.filter.predicate.permanent.CrewedSourceThisTurnPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; -import mage.util.CardUtil; import mage.util.functions.CopyApplier; import mage.watchers.Watcher; -import java.util.*; -import java.util.stream.Collectors; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; /** * @author TheElk801 */ public final class MindlinkMech extends CardImpl { - public MindlinkMech(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{U}"); @@ -60,9 +60,18 @@ public final class MindlinkMech extends CardImpl { class MindlinkMechTriggeredAbility extends TriggeredAbilityImpl { + private static final FilterPermanent filter = new FilterCreaturePermanent("nonlegendary creature that crewed it this turn"); + + static { + filter.add(CrewedSourceThisTurnPredicate.instance); + filter.add(Predicates.not(SuperType.LEGENDARY.getPredicate())); + } + MindlinkMechTriggeredAbility() { super(Zone.BATTLEFIELD, new MindlinkMechEffect()); this.addWatcher(new MindlinkMechWatcher()); + this.addTarget(new TargetPermanent(filter)); + this.setTriggerPhrase("Whenever {this} becomes crewed for the first time each turn"); } private MindlinkMechTriggeredAbility(final MindlinkMechTriggeredAbility ability) { @@ -81,26 +90,13 @@ class MindlinkMechTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (!event.getSourceId().equals(getSourceId()) || !MindlinkMechWatcher.checkVehicle(this, game)) { - return false; - } - this.getTargets().clear(); - this.addTarget(new TargetPermanent(MindlinkMechWatcher.makeFilter(this, game))); - return true; - } - - @Override - public String getRule() { - return "Whenever {this} becomes crewed for the first time each turn, until end of turn, " + - "{this} becomes a copy of target nonlegendary creature that crewed it this turn, " + - "except it's 4/3, it's a Vehicle artifact in addition to its other types, and it has flying."; + return event.getSourceId().equals(getSourceId()) && MindlinkMechWatcher.checkVehicle(this, game); } } class MindlinkMechWatcher extends Watcher { private final Map crewCount = new HashMap<>(); - private final Map> crewMap = new HashMap<>(); private static final FilterPermanent invalidFilter = new FilterPermanent(); static { @@ -114,34 +110,16 @@ class MindlinkMechWatcher extends Watcher { @Override public void watch(GameEvent event, Game game) { Permanent vehicle; - Permanent crewer; - switch (event.getType()) { - case VEHICLE_CREWED: - vehicle = game.getPermanent(event.getTargetId()); - crewer = null; - break; - case CREWED_VEHICLE: - vehicle = game.getPermanent(event.getSourceId()); - crewer = game.getPermanent(event.getTargetId()); - break; - default: - return; - } - if (vehicle == null) { - return; - } - if (crewer == null) { + if (event.getType() == GameEvent.EventType.VEHICLE_CREWED) { + vehicle = game.getPermanent(event.getTargetId()); crewCount.compute(new MageObjectReference(vehicle, game), (m, i) -> i == null ? 1 : Integer.sum(i, 1)); - return; } - crewMap.computeIfAbsent(new MageObjectReference(vehicle, game), x -> new HashSet<>()).add(new MageObjectReference(crewer, game)); } @Override public void reset() { super.reset(); crewCount.clear(); - crewMap.clear(); } public static boolean checkVehicle(Ability source, Game game) { @@ -151,34 +129,14 @@ class MindlinkMechWatcher extends Watcher { .crewCount .getOrDefault(new MageObjectReference(source), 0) < 2; } - - public static FilterPermanent makeFilter(Ability source, Game game) { - Set predicates = game - .getState() - .getWatcher(MindlinkMechWatcher.class) - .crewMap - .computeIfAbsent(new MageObjectReference(game.getPermanent(source.getSourceId()), game), x -> new HashSet<>()) - .stream() - .filter(mor -> { - Permanent permanent = mor.getPermanent(game); - return permanent != null && !permanent.isLegendary(game) && permanent.isCreature(game); - }).map(MageObjectReferencePredicate::new) - .collect(Collectors.toSet()); - if (predicates.isEmpty()) { - return invalidFilter; - } - FilterPermanent filterPermanent = new FilterPermanent( - "nonlegendary creature that crewed " + CardUtil.getSourceName(game, source) + " this turn" - ); - filterPermanent.add(Predicates.or(predicates)); - return filterPermanent; - } } class MindlinkMechEffect extends OneShotEffect { MindlinkMechEffect() { super(Outcome.Benefit); + this.setText("until end of turn, {this} becomes a copy of target nonlegendary creature that crewed it this turn, " + + "except it's 4/3, it's a Vehicle artifact in addition to its other types, and it has flying."); } private MindlinkMechEffect(final MindlinkMechEffect effect) { @@ -212,4 +170,4 @@ class MindlinkMechApplier extends CopyApplier { blueprint.getAbilities().add(FlyingAbility.getInstance()); return true; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/m/MindwrackDemon.java b/Mage.Sets/src/mage/cards/m/MindwrackDemon.java index c318d5a3d7f..119a9f2bbfd 100644 --- a/Mage.Sets/src/mage/cards/m/MindwrackDemon.java +++ b/Mage.Sets/src/mage/cards/m/MindwrackDemon.java @@ -1,29 +1,32 @@ package mage.cards.m; -import java.util.UUID; - import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.DeliriumCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.effects.common.LoseLifeSourceControllerEffect; import mage.abilities.effects.common.MillCardsControllerEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; +import java.util.UUID; + /** * @author fireshoes */ public final class MindwrackDemon extends CardImpl { + private static final Condition condition = new InvertCondition(DeliriumCondition.instance); + public MindwrackDemon(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{B}"); this.subtype.add(SubType.DEMON); @@ -40,12 +43,10 @@ public final class MindwrackDemon extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new MillCardsControllerEffect(4))); // At the beginning of your upkeep, if you don't have 4 or more card types in your graveyard, you lose 4 life. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new LoseLifeSourceControllerEffect(4)), - new InvertCondition(DeliriumCondition.instance), - "Delirium — At the beginning of your upkeep, you lose 4 life unless there are four or more card types among cards in your graveyard."); - ability.addHint(CardTypesInGraveyardCount.YOU.getHint()); - this.addAbility(ability); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new ConditionalOneShotEffect( + null, new LoseLifeSourceControllerEffect(4), DeliriumCondition.instance, + "you lose 4 life unless there are four or more card types among cards in your graveyard" + )).setAbilityWord(AbilityWord.DELIRIUM).addHint(CardTypesInGraveyardCount.YOU.getHint())); } private MindwrackDemon(final MindwrackDemon card) { diff --git a/Mage.Sets/src/mage/cards/m/MineRaider.java b/Mage.Sets/src/mage/cards/m/MineRaider.java index 48fbf632edb..d13f6f6cc4c 100644 --- a/Mage.Sets/src/mage/cards/m/MineRaider.java +++ b/Mage.Sets/src/mage/cards/m/MineRaider.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.hint.ConditionHint; import mage.abilities.hint.Hint; @@ -26,7 +25,7 @@ import java.util.UUID; */ public final class MineRaider extends CardImpl { - private static final FilterPermanent filter = new FilterControlledPermanent(); + private static final FilterPermanent filter = new FilterControlledPermanent("you control another outlaw"); static { filter.add(AnotherPredicate.instance); @@ -34,7 +33,7 @@ public final class MineRaider extends CardImpl { } private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); - private static final Hint hint = new ConditionHint(condition, "You control another outlaw"); + private static final Hint hint = new ConditionHint(condition); public MineRaider(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); @@ -48,10 +47,8 @@ public final class MineRaider extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // When Mine Raider enters the battlefield, if you control another outlaw, create a Treasure token. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new TreasureToken())), condition, - "When {this} enters, if you control another outlaw, create a Treasure token." - ).addHint(hint)); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new TreasureToken())) + .withInterveningIf(condition).addHint(hint)); } private MineRaider(final MineRaider card) { diff --git a/Mage.Sets/src/mage/cards/m/MirkwoodTrapper.java b/Mage.Sets/src/mage/cards/m/MirkwoodTrapper.java index 843aa8760e8..c92d3a26ff2 100644 --- a/Mage.Sets/src/mage/cards/m/MirkwoodTrapper.java +++ b/Mage.Sets/src/mage/cards/m/MirkwoodTrapper.java @@ -5,7 +5,6 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.PlayerAttacksTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.cards.CardImpl; @@ -40,11 +39,7 @@ public final class MirkwoodTrapper extends CardImpl { this.addAbility(new MirkwoodTrapperTriggerAttackYou()); // Whenever a player attacks, if they aren't attacking you, that player chooses an attacking creature. It gets +2/+0 until end of turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new PlayerAttacksTriggeredAbility(new MirkwoodTrapperEffect(), true), - NotAttackingSourceControllerCondition.instance, - "Whenever a player attacks, if they aren't attacking you, that player chooses an attacking creature. It gets +2/+0 until end of turn." - )); + this.addAbility(new PlayerAttacksTriggeredAbility(new MirkwoodTrapperEffect(), true).withInterveningIf(MirkwoodTrapperCondition.instance)); } private MirkwoodTrapper(final MirkwoodTrapper card) { @@ -85,15 +80,15 @@ class MirkwoodTrapperTriggerAttackYou extends TriggeredAbilityImpl { } } -enum NotAttackingSourceControllerCondition implements Condition { +enum MirkwoodTrapperCondition implements Condition { instance; @Override public boolean apply(Game game, Ability source) { return game.getCombat() - .getPlayerDefenders(game, false) - .stream() - .noneMatch(pId -> pId.equals(source.getControllerId())); + .getPlayerDefenders(game, false) + .stream() + .noneMatch(pId -> pId.equals(source.getControllerId())); } @Override @@ -143,4 +138,4 @@ class MirkwoodTrapperEffect extends OneShotEffect { return true; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/m/MirrorOfLifeTrapping.java b/Mage.Sets/src/mage/cards/m/MirrorOfLifeTrapping.java index 8e6e36841d4..d4e15becb54 100644 --- a/Mage.Sets/src/mage/cards/m/MirrorOfLifeTrapping.java +++ b/Mage.Sets/src/mage/cards/m/MirrorOfLifeTrapping.java @@ -104,7 +104,7 @@ class MirrorOfLifeTrappingEffect extends OneShotEffect { if (toBattlefield != null) { game.processAction(); controller.moveCards(toBattlefield.getCards(StaticFilters.FILTER_CARD_PERMANENT, game), - Zone.BATTLEFIELD, source, game, false, true, true, null); + Zone.BATTLEFIELD, source, game, false, false, true, null); } return true; diff --git a/Mage.Sets/src/mage/cards/m/MirrorSigilSergeant.java b/Mage.Sets/src/mage/cards/m/MirrorSigilSergeant.java index a57dd03d453..2731f6476a7 100644 --- a/Mage.Sets/src/mage/cards/m/MirrorSigilSergeant.java +++ b/Mage.Sets/src/mage/cards/m/MirrorSigilSergeant.java @@ -1,16 +1,12 @@ - package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; -import mage.abilities.TriggeredAbility; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.CreateTokenCopySourceEffect; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -18,19 +14,20 @@ import mage.constants.SubType; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class MirrorSigilSergeant extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent("blue permanent"); + private static final FilterControlledPermanent filter = new FilterControlledPermanent("you control a blue permanent"); static { filter.add(new ColorPredicate(ObjectColor.BLUE)); } - private static final String rule = "At the beginning of your upkeep, if you control a blue permanent, you may create a token that's a copy of {this}."; + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); public MirrorSigilSergeant(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{W}"); @@ -44,11 +41,9 @@ public final class MirrorSigilSergeant extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // At the beginning of your upkeep, if you control a blue permanent, you may create a token that's a copy of Mirror-Sigil Sergeant. - Effect effect = new CreateTokenCopySourceEffect(); - effect.setText("you may create a token that's a copy of {this}"); - TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(effect, true); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new PermanentsOnTheBattlefieldCondition(filter), rule)); - + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new CreateTokenCopySourceEffect(), true + ).withInterveningIf(condition)); } private MirrorSigilSergeant(final MirrorSigilSergeant card) { diff --git a/Mage.Sets/src/mage/cards/m/MirrorStrike.java b/Mage.Sets/src/mage/cards/m/MirrorStrike.java index 71b5fc782a6..f0c984ccebb 100644 --- a/Mage.Sets/src/mage/cards/m/MirrorStrike.java +++ b/Mage.Sets/src/mage/cards/m/MirrorStrike.java @@ -17,6 +17,7 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.UnblockedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -36,7 +37,7 @@ public final class MirrorStrike extends CardImpl { // All combat damage that would be dealt to you this turn by target unblocked creature is dealt to its controller instead. this.getSpellAbility().addEffect(new MirrorStrikeEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private MirrorStrike(final MirrorStrike card) { diff --git a/Mage.Sets/src/mage/cards/m/MirrorUniverse.java b/Mage.Sets/src/mage/cards/m/MirrorUniverse.java index 4f16b7e18ea..6137a7f16e3 100644 --- a/Mage.Sets/src/mage/cards/m/MirrorUniverse.java +++ b/Mage.Sets/src/mage/cards/m/MirrorUniverse.java @@ -1,22 +1,19 @@ - package mage.cards.m; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.ExchangeLifeControllerTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.PhaseStep; -import mage.constants.Zone; import mage.target.common.TargetOpponent; +import java.util.UUID; + /** - * * @author Styxo */ public final class MirrorUniverse extends CardImpl { @@ -25,11 +22,9 @@ public final class MirrorUniverse extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}"); // {tap}, Sacrifice Mirror Universe: Exchange life totals with target opponent. Activate this ability only during your upkeep. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, + Ability ability = new ActivateIfConditionActivatedAbility( new ExchangeLifeControllerTargetEffect(), - new TapSourceCost(), - new IsStepCondition(PhaseStep.UPKEEP) + new TapSourceCost(), IsStepCondition.getMyUpkeep() ); ability.addCost(new SacrificeSourceCost()); ability.addTarget(new TargetOpponent()); diff --git a/Mage.Sets/src/mage/cards/m/MischiefAndMayhem.java b/Mage.Sets/src/mage/cards/m/MischiefAndMayhem.java index 3b2c2c39d2e..cf420f4d3f4 100644 --- a/Mage.Sets/src/mage/cards/m/MischiefAndMayhem.java +++ b/Mage.Sets/src/mage/cards/m/MischiefAndMayhem.java @@ -1,16 +1,15 @@ package mage.cards.m; -import java.util.UUID; 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.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class MischiefAndMayhem extends CardImpl { @@ -20,7 +19,7 @@ public final class MischiefAndMayhem extends CardImpl { // Up to two target creatures each get +4/+4 until end of turn. this.getSpellAbility().addEffect(new BoostTargetEffect(4, 4, Duration.EndOfTurn)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 2, StaticFilters.FILTER_PERMANENT_CREATURES, false)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 2)); } private MischiefAndMayhem(final MischiefAndMayhem card) { diff --git a/Mage.Sets/src/mage/cards/m/MishrasFactory.java b/Mage.Sets/src/mage/cards/m/MishrasFactory.java index 28abadfa49c..8a2217455ca 100644 --- a/Mage.Sets/src/mage/cards/m/MishrasFactory.java +++ b/Mage.Sets/src/mage/cards/m/MishrasFactory.java @@ -13,6 +13,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.game.permanent.token.custom.CreatureToken; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -46,7 +47,7 @@ public final class MishrasFactory extends CardImpl { SimpleActivatedAbility ability = new SimpleActivatedAbility( new BoostTargetEffect(1, 1, Duration.EndOfTurn), new TapSourceCost() ); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MistbladeShinobi.java b/Mage.Sets/src/mage/cards/m/MistbladeShinobi.java index 9959e14301a..08d0839ba63 100644 --- a/Mage.Sets/src/mage/cards/m/MistbladeShinobi.java +++ b/Mage.Sets/src/mage/cards/m/MistbladeShinobi.java @@ -11,6 +11,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster; @@ -37,7 +38,7 @@ public final class MistbladeShinobi extends CardImpl { // Whenever Mistblade Shinobi deals combat damage to a player, you may return target creature that player controls to its owner's hand. Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new ReturnToHandTargetEffect(), true, true); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MistveilPlains.java b/Mage.Sets/src/mage/cards/m/MistveilPlains.java index 09cb3dea2eb..b6616d7597c 100644 --- a/Mage.Sets/src/mage/cards/m/MistveilPlains.java +++ b/Mage.Sets/src/mage/cards/m/MistveilPlains.java @@ -1,10 +1,10 @@ package mage.cards.m; -import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; @@ -20,6 +20,8 @@ import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; +import java.util.UUID; + /** * @author LevelX2 */ @@ -31,6 +33,8 @@ public final class MistveilPlains extends CardImpl { filter.add(new ColorPredicate(ObjectColor.WHITE)); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1); + public MistveilPlains(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); this.subtype.add(SubType.PLAINS); @@ -43,15 +47,11 @@ public final class MistveilPlains extends CardImpl { // {W}, {tap}: Put target card from your graveyard on the bottom of your library. Activate this ability only if you control two or more white permanents. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, - new MistveilPlainsGraveyardToLibraryEffect(), - new ManaCostsImpl<>("{W}"), - new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1) + new MistveilPlainsGraveyardToLibraryEffect(), new ManaCostsImpl<>("{W}"), condition ); ability.addTarget(new TargetCardInYourGraveyard()); ability.addCost(new TapSourceCost()); this.addAbility(ability); - } private MistveilPlains(final MistveilPlains card) { diff --git a/Mage.Sets/src/mage/cards/m/MizziumMortars.java b/Mage.Sets/src/mage/cards/m/MizziumMortars.java index af8e09f6bfc..e04f5b04a4b 100644 --- a/Mage.Sets/src/mage/cards/m/MizziumMortars.java +++ b/Mage.Sets/src/mage/cards/m/MizziumMortars.java @@ -8,10 +8,13 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author LevelX2 */ @@ -21,7 +24,7 @@ public final class MizziumMortars extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{R}"); // MizziumMortars deals 4 damage to target creature you don't control. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.getSpellAbility().addEffect(new DamageTargetEffect(4)); // Overload {3}{R}{R}{R} (You may cast this spell for its overload cost. If you do, change its text by replacing all instances of "target" with "each.") diff --git a/Mage.Sets/src/mage/cards/m/MizziumSkin.java b/Mage.Sets/src/mage/cards/m/MizziumSkin.java index 4e64224f007..1d70c946bec 100644 --- a/Mage.Sets/src/mage/cards/m/MizziumSkin.java +++ b/Mage.Sets/src/mage/cards/m/MizziumSkin.java @@ -14,8 +14,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_CONTROLLED; + /** * @@ -29,7 +32,7 @@ public final class MizziumSkin extends CardImpl { // Target creature you control gets +0/+1 and gains hexproof until end of turn. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_CONTROLLED)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_CONTROLLED)); this.getSpellAbility().addEffect(new BoostTargetEffect(0,1, Duration.EndOfTurn).setText("target creature you control gets +0/+1")); this.getSpellAbility().addEffect(new GainAbilityTargetEffect(HexproofAbility.getInstance(), Duration.EndOfTurn).setText("and gains hexproof until end of turn")); @@ -47,4 +50,4 @@ public final class MizziumSkin extends CardImpl { public MizziumSkin copy() { return new MizziumSkin(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/m/ModifyMemory.java b/Mage.Sets/src/mage/cards/m/ModifyMemory.java index aaa41a8fb68..b41118ba499 100644 --- a/Mage.Sets/src/mage/cards/m/ModifyMemory.java +++ b/Mage.Sets/src/mage/cards/m/ModifyMemory.java @@ -14,7 +14,7 @@ import mage.game.Controllable; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.Target; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.targetpointer.EachTargetPointer; import java.util.Collection; @@ -67,7 +67,7 @@ enum ModifyMemoryCondition implements Condition { } } -class ModifyMemoryTarget extends TargetCreaturePermanent { +class ModifyMemoryTarget extends TargetPermanent { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures controlled by different players"); diff --git a/Mage.Sets/src/mage/cards/m/MoltenEchoes.java b/Mage.Sets/src/mage/cards/m/MoltenEchoes.java index 6157be1cfd1..5b6493315b5 100644 --- a/Mage.Sets/src/mage/cards/m/MoltenEchoes.java +++ b/Mage.Sets/src/mage/cards/m/MoltenEchoes.java @@ -3,7 +3,7 @@ package mage.cards.m; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; import mage.abilities.common.AsEntersBattlefieldAbility; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ChooseCreatureTypeEffect; @@ -15,6 +15,7 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SetTargetPointer; import mage.constants.Zone; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.ChosenSubtypePredicate; import mage.filter.predicate.permanent.TokenPredicate; @@ -25,11 +26,17 @@ import mage.target.targetpointer.FixedTarget; import java.util.UUID; /** - * * @author ciaccona007 */ public final class MoltenEchoes extends CardImpl { + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("nontoken creature you control of the chosen type"); + + static { + filter.add(TokenPredicate.FALSE); + filter.add(ChosenSubtypePredicate.TRUE); + } + public MoltenEchoes(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}{R}"); @@ -37,14 +44,9 @@ public final class MoltenEchoes extends CardImpl { this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.Copy))); // Whenever a nontoken creature of the chosen type you control enters, create a token that's a copy of that creature. That token gains haste. Exile it at the beginning of the next end step. - FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("nontoken creature of the chosen type"); - filter.add(TokenPredicate.FALSE); - filter.add(ChosenSubtypePredicate.TRUE); - - Ability ability = new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new MoltenEchoesEffect(), - filter, false, SetTargetPointer.PERMANENT - ); - this.addAbility(ability); + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + Zone.BATTLEFIELD, new MoltenEchoesEffect(), filter, false, SetTargetPointer.PERMANENT + )); } private MoltenEchoes(final MoltenEchoes card) { diff --git a/Mage.Sets/src/mage/cards/m/MoltenFrame.java b/Mage.Sets/src/mage/cards/m/MoltenFrame.java index f36e9804ec9..2a889f2eeaa 100644 --- a/Mage.Sets/src/mage/cards/m/MoltenFrame.java +++ b/Mage.Sets/src/mage/cards/m/MoltenFrame.java @@ -10,6 +10,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -28,7 +29,7 @@ public final class MoltenFrame extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{R}"); this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{2}"))); } diff --git a/Mage.Sets/src/mage/cards/m/MoltenPsyche.java b/Mage.Sets/src/mage/cards/m/MoltenPsyche.java index f65d6f902a3..69011bd09ce 100644 --- a/Mage.Sets/src/mage/cards/m/MoltenPsyche.java +++ b/Mage.Sets/src/mage/cards/m/MoltenPsyche.java @@ -47,7 +47,7 @@ class MoltenPsycheEffect extends OneShotEffect { MoltenPsycheEffect() { super(Outcome.Neutral); - staticText = "Each player shuffles the cards from their hand into their library, then draws that many cards.\n" + staticText = "Each player shuffles the cards from their hand into their library, then draws that many cards.
" + "Metalcraft — If you control three or more artifacts, {this} deals damage to each opponent equal to the number of cards that player has drawn this turn."; } diff --git a/Mage.Sets/src/mage/cards/m/MomentOfValor.java b/Mage.Sets/src/mage/cards/m/MomentOfValor.java index dda0fef5ac3..400b9420ae6 100644 --- a/Mage.Sets/src/mage/cards/m/MomentOfValor.java +++ b/Mage.Sets/src/mage/cards/m/MomentOfValor.java @@ -12,6 +12,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -39,7 +40,7 @@ public final class MomentOfValor extends CardImpl { // * Destroy target creature with power 4 or greater. Mode mode = new Mode(new DestroyTargetEffect()); - mode.addTarget(new TargetCreaturePermanent(filter)); + mode.addTarget(new TargetPermanent(filter)); this.getSpellAbility().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/m/MomentumRumbler.java b/Mage.Sets/src/mage/cards/m/MomentumRumbler.java index b6875666aa8..debaaf01f2c 100644 --- a/Mage.Sets/src/mage/cards/m/MomentumRumbler.java +++ b/Mage.Sets/src/mage/cards/m/MomentumRumbler.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.DoubleStrikeAbility; @@ -33,20 +32,15 @@ public final class MomentumRumbler extends CardImpl { this.toughness = new MageInt(3); // Whenever Momentum Rumbler attacks, if it doesn't have first strike, put a first strike counter on it. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new AddCountersSourceEffect( - CounterType.FIRST_STRIKE.createInstance() - ), false), MomentumRumblerCondition.FALSE, "Whenever {this} attacks, " + - "if it doesn't have first strike, put a first strike counter on it." - )); + this.addAbility(new AttacksTriggeredAbility( + new AddCountersSourceEffect(CounterType.FIRST_STRIKE.createInstance()) + .setText("put a first strike counter on it"), false + ).withInterveningIf(MomentumRumblerCondition.FALSE)); // Whenever Momentum Rumbler attacks, if it has first strike, it gains double strike until end of turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new GainAbilitySourceEffect( - DoubleStrikeAbility.getInstance(), Duration.EndOfTurn - ), false), MomentumRumblerCondition.TRUE, "Whenever {this} attacks, " + - "if it has first strike, it gains double strike until end of turn." - )); + this.addAbility(new AttacksTriggeredAbility(new GainAbilitySourceEffect( + DoubleStrikeAbility.getInstance(), Duration.EndOfTurn + ).setText("it gains double strike until end of turn")).withInterveningIf(MomentumRumblerCondition.TRUE)); } private MomentumRumbler(final MomentumRumbler card) { @@ -77,4 +71,9 @@ enum MomentumRumblerCondition implements Condition { } return hasAbility == permanent.hasAbility(FirstStrikeAbility.getInstance(), game); } -} \ No newline at end of file + + @Override + public String toString() { + return "it " + (hasAbility ? "has" : "doesn't have") + " first strike"; + } +} diff --git a/Mage.Sets/src/mage/cards/m/Monsoon.java b/Mage.Sets/src/mage/cards/m/Monsoon.java index 809f56f15f3..d13893597fd 100644 --- a/Mage.Sets/src/mage/cards/m/Monsoon.java +++ b/Mage.Sets/src/mage/cards/m/Monsoon.java @@ -1,19 +1,17 @@ package mage.cards.m; import mage.abilities.Ability; -import mage.abilities.TriggeredAbility; -import mage.abilities.common.OnEventTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; 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.predicate.permanent.TappedPredicate; import mage.game.Game; -import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; @@ -28,8 +26,9 @@ public final class Monsoon extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}{G}"); // At the beginning of each player's end step, tap all untapped Islands that player controls and Monsoon deals X damage to the player, where X is the number of Islands tapped this way. - TriggeredAbility ability = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of each player's end step", true, new MonsoonEffect()); - this.addAbility(ability); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.EACH_PLAYER, new MonsoonEffect(), false + )); } private Monsoon(final Monsoon card) { diff --git a/Mage.Sets/src/mage/cards/m/MonumentToPerfection.java b/Mage.Sets/src/mage/cards/m/MonumentToPerfection.java index 45371e91954..deddca2a48d 100644 --- a/Mage.Sets/src/mage/cards/m/MonumentToPerfection.java +++ b/Mage.Sets/src/mage/cards/m/MonumentToPerfection.java @@ -56,7 +56,6 @@ public final class MonumentToPerfection extends CardImpl { // {3}: Monument to Perfection becomes a 9/9 Phyrexian Construct artifact creature, loses all abilities, and gains indestructible and toxic 9. Activate only if there are nine or more lands with different names among the basic, Sphere, and Locus lands you control. this.addAbility(new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new CreatureToken( 9, 9, "9/9 Phyrexian Construct artifact creature, " + "loses all abilities, and gains indestructible and toxic 9", SubType.PHYREXIAN, SubType.CONSTRUCT diff --git a/Mage.Sets/src/mage/cards/m/MoonlightHunt.java b/Mage.Sets/src/mage/cards/m/MoonlightHunt.java index 43afb96001b..941a51b1a72 100644 --- a/Mage.Sets/src/mage/cards/m/MoonlightHunt.java +++ b/Mage.Sets/src/mage/cards/m/MoonlightHunt.java @@ -13,10 +13,13 @@ import mage.filter.predicate.Predicates; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author LevelX2 */ @@ -27,7 +30,7 @@ public final class MoonlightHunt extends CardImpl { // Choose target creature you don't control. Each creature you control that's a Wolf or Werewolf deals damage equal to its power to that creature. this.getSpellAbility().addEffect(new MoonlightHuntEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); } private MoonlightHunt(final MoonlightHunt card) { diff --git a/Mage.Sets/src/mage/cards/m/MoonlitScavengers.java b/Mage.Sets/src/mage/cards/m/MoonlitScavengers.java index 1fe3f432ba7..d7419a1fa3b 100644 --- a/Mage.Sets/src/mage/cards/m/MoonlitScavengers.java +++ b/Mage.Sets/src/mage/cards/m/MoonlitScavengers.java @@ -5,14 +5,11 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandTargetEffect; 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.common.TargetOpponentsCreaturePermanent; @@ -23,13 +20,9 @@ import java.util.UUID; */ public final class MoonlitScavengers extends CardImpl { - private static final FilterPermanent filter = new FilterArtifactOrEnchantmentPermanent(); - - static { - filter.add(TargetController.YOU.getControllerPredicate()); - } - - private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterArtifactOrEnchantmentPermanent("you control an artifact or enchantment"), true + ); public MoonlitScavengers(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{U}"); @@ -40,11 +33,7 @@ public final class MoonlitScavengers extends CardImpl { this.toughness = new MageInt(5); // When Moonlit Scavengers enters the battlefield, if you control an artifact or enchantment, return target creature an opponent controls to its owner's hand. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()), condition, - "When {this} enters, if you control an artifact or enchantment, " + - "return target creature an opponent controls to its owner's hand." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()).withInterveningIf(condition); ability.addTarget(new TargetOpponentsCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MoonringIsland.java b/Mage.Sets/src/mage/cards/m/MoonringIsland.java index 2af09f8d935..f3f8e983da0 100644 --- a/Mage.Sets/src/mage/cards/m/MoonringIsland.java +++ b/Mage.Sets/src/mage/cards/m/MoonringIsland.java @@ -1,28 +1,27 @@ - package mage.cards.m; -import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTappedAbility; +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.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.LookLibraryTopCardTargetPlayerEffect; import mage.abilities.mana.BlueManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.ComparisonType; -import mage.constants.Zone; +import mage.constants.SubType; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.ColorPredicate; import mage.target.TargetPlayer; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class MoonringIsland extends CardImpl { @@ -33,8 +32,10 @@ public final class MoonringIsland extends CardImpl { filter.add(new ColorPredicate(ObjectColor.BLUE)); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1); + public MoonringIsland(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.LAND},""); + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); this.subtype.add(SubType.ISLAND); // ({tap}: Add {U}.) @@ -44,14 +45,12 @@ public final class MoonringIsland extends CardImpl { this.addAbility(new EntersBattlefieldTappedAbility()); // {U}, {tap}: Look at the top card of target player's library. Activate this ability only if you control two or more blue permanents. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, - new LookLibraryTopCardTargetPlayerEffect(), - new ManaCostsImpl<>("{U}"), - new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1)); + Ability ability = new ActivateIfConditionActivatedAbility( + new LookLibraryTopCardTargetPlayerEffect(), new ManaCostsImpl<>("{U}"), condition + ); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetPlayer()); this.addAbility(ability); - } private MoonringIsland(final MoonringIsland card) { diff --git a/Mage.Sets/src/mage/cards/m/MoorlandDrifter.java b/Mage.Sets/src/mage/cards/m/MoorlandDrifter.java index 6210d3e77cb..90a8de5c777 100644 --- a/Mage.Sets/src/mage/cards/m/MoorlandDrifter.java +++ b/Mage.Sets/src/mage/cards/m/MoorlandDrifter.java @@ -11,6 +11,7 @@ import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; @@ -26,8 +27,8 @@ public final class MoorlandDrifter extends CardImpl { this.toughness = new MageInt(2); // Delirium — Moorland Drifter has flying as long as there are four or more card types among cards in your graveyard. - ConditionalContinuousEffect effect = new ConditionalContinuousEffect(new GainAbilitySourceEffect(FlyingAbility.getInstance()), DeliriumCondition.instance, "Delirium — Moorland Drifter has flying as long as there are four or more card types among cards in your graveyard."); - this.addAbility(new SimpleStaticAbility(effect).addHint(CardTypesInGraveyardCount.YOU.getHint())); + ConditionalContinuousEffect effect = new ConditionalContinuousEffect(new GainAbilitySourceEffect(FlyingAbility.getInstance()), DeliriumCondition.instance, "{this} has flying as long as there are four or more card types among cards in your graveyard."); + this.addAbility(new SimpleStaticAbility(effect).setAbilityWord(AbilityWord.DELIRIUM).addHint(CardTypesInGraveyardCount.YOU.getHint())); } private MoorlandDrifter(final MoorlandDrifter card) { diff --git a/Mage.Sets/src/mage/cards/m/MoraugFuryOfAkoum.java b/Mage.Sets/src/mage/cards/m/MoraugFuryOfAkoum.java index 3843f45540f..addd453c276 100644 --- a/Mage.Sets/src/mage/cards/m/MoraugFuryOfAkoum.java +++ b/Mage.Sets/src/mage/cards/m/MoraugFuryOfAkoum.java @@ -1,13 +1,11 @@ package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; import mage.abilities.common.LandfallAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.IsMainPhaseCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.UntapAllControllerEffect; @@ -22,6 +20,8 @@ import mage.game.turn.TurnMod; import mage.watchers.Watcher; import mage.watchers.common.AttackedThisTurnWatcher; +import java.util.UUID; + /** * @author TheElk801 */ @@ -40,12 +40,7 @@ public final class MoraugFuryOfAkoum extends CardImpl { this.addAbility(new SimpleStaticAbility(new MoraugFuryOfAkoumBoostEffect())); // Landfall — Whenever a land you control enters, if it's your main phase, there's an additional combat phase after this phase. At the beginning of that combat, untap all creatures you control. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new LandfallAbility(new MoraugFuryOfAkoumCombatEffect()), IsMainPhaseCondition.YOUR, - "Landfall — Whenever a land you control enters, " + - "if it's your main phase, there's an additional combat phase after this phase. " + - "At the beginning of that combat, untap all creatures you control." - ), new MoraugFuryOfAkoumWatcher()); + this.addAbility(new LandfallAbility(new MoraugFuryOfAkoumCombatEffect()).withInterveningIf(IsMainPhaseCondition.YOUR), new MoraugFuryOfAkoumWatcher()); } private MoraugFuryOfAkoum(final MoraugFuryOfAkoum card) { @@ -91,6 +86,7 @@ class MoraugFuryOfAkoumCombatEffect extends OneShotEffect { MoraugFuryOfAkoumCombatEffect() { super(Outcome.Benefit); + staticText = "there's an additional combat phase after this phase. At the beginning of that combat, untap all creatures you control"; } private MoraugFuryOfAkoumCombatEffect(final MoraugFuryOfAkoumCombatEffect effect) { @@ -189,4 +185,4 @@ class MoraugFuryOfAkoumWatcher extends Watcher { } } } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/m/MorkrutBanshee.java b/Mage.Sets/src/mage/cards/m/MorkrutBanshee.java index 2256df34c35..68a34548722 100644 --- a/Mage.Sets/src/mage/cards/m/MorkrutBanshee.java +++ b/Mage.Sets/src/mage/cards/m/MorkrutBanshee.java @@ -1,30 +1,27 @@ - package mage.cards.m; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.MorbidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.hint.common.MorbidHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Duration; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * @author nantuko */ public final class MorkrutBanshee extends CardImpl { - private static final String staticText = "Morbid — When {this} enters, if a creature died this turn, target creature gets -4/-4 until end of turn."; - public MorkrutBanshee(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.SPIRIT); this.color.setBlack(true); @@ -32,10 +29,10 @@ public final class MorkrutBanshee extends CardImpl { this.toughness = new MageInt(4); // Morbid — When Morkut Banshee enters the battlefield, if a creature died this turn, target creature gets -4/-4 until end of turn. - TriggeredAbility triggeredAbility = new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(-4, -4, Duration.EndOfTurn)); - TriggeredAbility ability = new ConditionalInterveningIfTriggeredAbility(triggeredAbility, MorbidCondition.instance, staticText); + Ability ability = new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(-4, -4)) + .withInterveningIf(MorbidCondition.instance); ability.addTarget(new TargetCreaturePermanent()); - this.addAbility(ability.addHint(MorbidHint.instance)); + this.addAbility(ability.setAbilityWord(AbilityWord.MORBID).addHint(MorbidHint.instance)); } private MorkrutBanshee(final MorkrutBanshee card) { diff --git a/Mage.Sets/src/mage/cards/m/MortalCombat.java b/Mage.Sets/src/mage/cards/m/MortalCombat.java index cb72ca3dfe1..be419afcc78 100644 --- a/Mage.Sets/src/mage/cards/m/MortalCombat.java +++ b/Mage.Sets/src/mage/cards/m/MortalCombat.java @@ -1,32 +1,28 @@ package mage.cards.m; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.CardsInControllerGraveyardCondition; import mage.abilities.effects.common.WinGameSourceControllerEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; -import mage.game.Game; -import mage.players.Player; + +import java.util.UUID; /** - * * @author daagar */ public final class MortalCombat extends CardImpl { + private static final Condition condition = new CardsInControllerGraveyardCondition(20, StaticFilters.FILTER_CARD_CREATURES); + public MortalCombat(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{B}"); // At the beginning of your upkeep, if twenty or more creature cards are in your graveyard, you win the game. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect()), - new TwentyGraveyardCreatureCondition(), - "At the beginning of your upkeep, if twenty or more creature cards are in your graveyard, you win the game.")); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect()).withInterveningIf(condition)); } private MortalCombat(final MortalCombat card) { @@ -38,12 +34,3 @@ public final class MortalCombat extends CardImpl { return new MortalCombat(this); } } - -class TwentyGraveyardCreatureCondition implements Condition { - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - return player != null && player.getGraveyard().count(StaticFilters.FILTER_CARD_CREATURE, game) >= 20; - } -} diff --git a/Mage.Sets/src/mage/cards/m/MossPitSkeleton.java b/Mage.Sets/src/mage/cards/m/MossPitSkeleton.java index c839f412218..089ee27b195 100644 --- a/Mage.Sets/src/mage/cards/m/MossPitSkeleton.java +++ b/Mage.Sets/src/mage/cards/m/MossPitSkeleton.java @@ -59,7 +59,7 @@ public final class MossPitSkeleton extends CardImpl { class MossPitSkeletonTriggeredAbility extends TriggeredAbilityImpl { MossPitSkeletonTriggeredAbility() { - super(Zone.GRAVEYARD, new PutOnLibrarySourceEffect(true).setText("put {this} on top of your library"), true); + super(Zone.GRAVEYARD, new PutOnLibrarySourceEffect(true).setText("put this card on top of your library"), true); this.withInterveningIf(SourceInGraveyardCondition.instance); setTriggerPhrase("Whenever one or more +1/+1 counters are put on a creature you control, "); } diff --git a/Mage.Sets/src/mage/cards/m/MossbridgeTroll.java b/Mage.Sets/src/mage/cards/m/MossbridgeTroll.java index cd63deca655..ac1e44e7b7a 100644 --- a/Mage.Sets/src/mage/cards/m/MossbridgeTroll.java +++ b/Mage.Sets/src/mage/cards/m/MossbridgeTroll.java @@ -18,7 +18,7 @@ import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; import java.util.UUID; @@ -108,7 +108,7 @@ class MossbridgeTrollCost extends CostImpl { } public MossbridgeTrollCost() { - this.addTarget(new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, filter, true)); + this.addTarget(new TargetControlledPermanent(0, Integer.MAX_VALUE, filter, true)); this.text = "tap any number of untapped creatures you control other than {this} with total power 10 or greater"; } diff --git a/Mage.Sets/src/mage/cards/m/Mosstodon.java b/Mage.Sets/src/mage/cards/m/Mosstodon.java index 96b104ab4e8..f2f8295d7a9 100644 --- a/Mage.Sets/src/mage/cards/m/Mosstodon.java +++ b/Mage.Sets/src/mage/cards/m/Mosstodon.java @@ -16,6 +16,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -41,7 +42,7 @@ public final class Mosstodon extends CardImpl { SimpleActivatedAbility ability = new SimpleActivatedAbility( new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{1}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/Mournwillow.java b/Mage.Sets/src/mage/cards/m/Mournwillow.java index 993ede54731..e6bdde9bae8 100644 --- a/Mage.Sets/src/mage/cards/m/Mournwillow.java +++ b/Mage.Sets/src/mage/cards/m/Mournwillow.java @@ -4,12 +4,12 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.DeliriumCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.effects.RestrictionEffect; import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; @@ -35,13 +35,10 @@ public final class Mournwillow extends CardImpl { // Delirium — When Mournwillow enters the battlefield, if there are four or more card types among cards in your graveyard, // creatures with power 2 or less can't block this turn. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new MournwillowEffect(), false), - DeliriumCondition.instance, - "Delirium — When {this} enters, if there are four or more card types among cards in your graveyard, " - + "creatures with power 2 or less can't block this turn."); - ability.addHint(CardTypesInGraveyardCount.YOU.getHint()); - this.addAbility(ability); + this.addAbility(new EntersBattlefieldTriggeredAbility(new MournwillowEffect()) + .withInterveningIf(DeliriumCondition.instance) + .setAbilityWord(AbilityWord.DELIRIUM) + .addHint(CardTypesInGraveyardCount.YOU.getHint())); } private Mournwillow(final Mournwillow card) { diff --git a/Mage.Sets/src/mage/cards/m/MrHousePresidentAndCEO.java b/Mage.Sets/src/mage/cards/m/MrHousePresidentAndCEO.java index 5b537b0c5c8..f7840701dcd 100644 --- a/Mage.Sets/src/mage/cards/m/MrHousePresidentAndCEO.java +++ b/Mage.Sets/src/mage/cards/m/MrHousePresidentAndCEO.java @@ -14,7 +14,7 @@ import mage.cards.CardSetInfo; import mage.game.Game; import mage.game.events.DieRolledEvent; import mage.game.events.GameEvent; -import mage.game.permanent.token.RobotToken; +import mage.game.permanent.token.Robot33Token; import mage.game.permanent.token.Token; import mage.game.permanent.token.TreasureToken; import mage.players.Player; @@ -116,7 +116,7 @@ class MrHousePresidentAndCEOTokenEffect extends OneShotEffect { int amount = (Integer) getValue("rolled"); if (amount >= 4) { - Token robotToken = new RobotToken(); + Token robotToken = new Robot33Token(); robotToken.putOntoBattlefield(1, game, source); } if (amount >= 6) { diff --git a/Mage.Sets/src/mage/cards/m/MsBumbleflower.java b/Mage.Sets/src/mage/cards/m/MsBumbleflower.java index ecf246926ce..59bcd8bb050 100644 --- a/Mage.Sets/src/mage/cards/m/MsBumbleflower.java +++ b/Mage.Sets/src/mage/cards/m/MsBumbleflower.java @@ -1,36 +1,37 @@ package mage.cards.m; -import java.util.*; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SpellCastControllerTriggeredAbility; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.DrawCardTargetEffect; import mage.abilities.effects.common.IfAbilityHasResolvedXTimesEffect; 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.constants.*; -import mage.counters.CounterType; -import mage.filter.StaticFilters; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.counters.CounterType; +import mage.filter.StaticFilters; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetOpponent; import mage.target.targetpointer.FirstTargetPointer; import mage.target.targetpointer.SecondTargetPointer; import mage.watchers.common.AbilityResolvedWatcher; +import java.util.UUID; + /** - * * @author DreamWaker */ public final class MsBumbleflower extends CardImpl { public MsBumbleflower(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[] { CardType.CREATURE }, "{1}{G}{W}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}{W}{U}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.RABBIT); @@ -43,18 +44,18 @@ public final class MsBumbleflower extends CardImpl { // Whenever you cast a spell, target opponent draws a card. Put a +1/+1 counter on target creature. It gains // flying until end of turn. If this is the second time this ability has resolved this turn, you draw two cards. - Effect draw = new DrawCardTargetEffect(1); - draw.setTargetPointer(new FirstTargetPointer()); - Effect counters = new AddCountersTargetEffect(CounterType.P1P1.createInstance()); - counters.setTargetPointer(new SecondTargetPointer()); - Effect flying = new GainAbilityTargetEffect(FlyingAbility.getInstance()).setText("It gains flying until end of turn."); - flying.setTargetPointer(new SecondTargetPointer()); - Ability ability = new SpellCastControllerTriggeredAbility(draw,StaticFilters.FILTER_SPELL_A, false); + Ability ability = new SpellCastControllerTriggeredAbility( + new DrawCardTargetEffect(1), StaticFilters.FILTER_SPELL_A, false + ); ability.addTarget(new TargetOpponent()); - ability.addEffect(counters); - ability.addEffect(flying); - ability.addTarget(new TargetCreaturePermanent(1)); - ability.addEffect(new IfAbilityHasResolvedXTimesEffect(2, new DrawCardSourceControllerEffect(2, true))); + ability.addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance()) + .setTargetPointer(new SecondTargetPointer())); + ability.addEffect(new GainAbilityTargetEffect(FlyingAbility.getInstance()) + .setText("It gains flying until end of turn.").setTargetPointer(new SecondTargetPointer())); + ability.addTarget(new TargetCreaturePermanent()); + ability.addEffect(new IfAbilityHasResolvedXTimesEffect( + 2, new DrawCardSourceControllerEffect(2, true + ))); this.addAbility(ability, new AbilityResolvedWatcher()); } diff --git a/Mage.Sets/src/mage/cards/m/MtendaGriffin.java b/Mage.Sets/src/mage/cards/m/MtendaGriffin.java index d79901ea18b..1813bd7cea5 100644 --- a/Mage.Sets/src/mage/cards/m/MtendaGriffin.java +++ b/Mage.Sets/src/mage/cards/m/MtendaGriffin.java @@ -1,59 +1,51 @@ - package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.Effect; +import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; import mage.abilities.effects.common.ReturnToHandSourceEffect; -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.PhaseStep; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.FilterCard; -import mage.target.Target; import mage.target.common.TargetCardInYourGraveyard; +import java.util.UUID; + /** - * * @author fireshoes */ public final class MtendaGriffin extends CardImpl { - + private static final FilterCard filter = new FilterCard("Griffin card from your graveyard"); static { filter.add(SubType.GRIFFIN.getPredicate()); -} + } public MtendaGriffin(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.GRIFFIN); this.power = new MageInt(2); this.toughness = new MageInt(2); // Flying this.addAbility(FlyingAbility.getInstance()); - + // {W}, {tap}: Return Mtenda Griffin to its owner's hand and return target Griffin card from your graveyard to your hand. Activate this ability only during your upkeep. - Effect effect = new ReturnToHandSourceEffect(true); - effect.setText("Return Mtenda Griffin to its owner's hand"); - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - effect, new ManaCostsImpl<>("{W}"), new IsStepCondition(PhaseStep.UPKEEP)); - effect = new ReturnToHandTargetEffect(); + Ability ability = new ActivateIfConditionActivatedAbility( + new ReturnToHandSourceEffect(true), + new ManaCostsImpl<>("{W}"), IsStepCondition.getMyUpkeep() + ); ability.addCost(new TapSourceCost()); - effect.setText("and return target Griffin card from your graveyard to your hand"); - ability.addEffect(effect); - Target target = new TargetCardInYourGraveyard(filter); - ability.addTarget(target); + ability.addEffect(new ReturnFromGraveyardToHandTargetEffect().concatBy("and")); + ability.addTarget(new TargetCardInYourGraveyard(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/Mudslide.java b/Mage.Sets/src/mage/cards/m/Mudslide.java index 90e7097ea6d..6429d26d481 100644 --- a/Mage.Sets/src/mage/cards/m/Mudslide.java +++ b/Mage.Sets/src/mage/cards/m/Mudslide.java @@ -1,15 +1,18 @@ package mage.cards.m; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.Cost; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DontUntapInControllersUntapStepAllEffect; import mage.abilities.keyword.FlyingAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; @@ -19,7 +22,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; import mage.util.ManaUtil; import java.util.UUID; @@ -86,7 +89,8 @@ class MudslideEffect extends OneShotEffect { if (player != null && sourcePermanent != null) { int countBattlefield = game.getBattlefield().getAllActivePermanents(filter, game.getActivePlayerId(), game).size(); while (player.canRespond() && countBattlefield > 0 && player.chooseUse(Outcome.Benefit, "Pay {2} and untap a tapped creature without flying under your control?", source, game)) { - Target tappedCreatureTarget = new TargetControlledCreaturePermanent(1, 1, filter, true); + Target tappedCreatureTarget = new TargetControlledPermanent(filter); + tappedCreatureTarget.withNotTarget(true); if (player.choose(Outcome.Untap, tappedCreatureTarget, source, game)) { Cost cost = ManaUtil.createManaCost(2, false); Permanent tappedCreature = game.getPermanent(tappedCreatureTarget.getFirstTarget()); diff --git a/Mage.Sets/src/mage/cards/m/MurasaSproutling.java b/Mage.Sets/src/mage/cards/m/MurasaSproutling.java index 09beac04b30..cbad132fbe6 100644 --- a/Mage.Sets/src/mage/cards/m/MurasaSproutling.java +++ b/Mage.Sets/src/mage/cards/m/MurasaSproutling.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -40,11 +39,7 @@ public final class MurasaSproutling extends CardImpl { this.addAbility(new KickerAbility("{1}{G}")); // When Murasa Sproutling enters the battlefield, if it was kicked, return target card with a kicker ability from your graveyard to your hand. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect()), - KickedCondition.ONCE, "When {this} enters, if it was kicked, " + - "return target card with a kicker ability from your graveyard to your hand." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect()).withInterveningIf(KickedCondition.ONCE); ability.addTarget(new TargetCardInYourGraveyard(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MurderousBetrayal.java b/Mage.Sets/src/mage/cards/m/MurderousBetrayal.java index 4c6f66c45a0..21d3bacf9e3 100644 --- a/Mage.Sets/src/mage/cards/m/MurderousBetrayal.java +++ b/Mage.Sets/src/mage/cards/m/MurderousBetrayal.java @@ -15,9 +15,12 @@ import mage.constants.Zone; import mage.filter.StaticFilters; import mage.game.Game; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.util.CardUtil; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author choiseul11 @@ -31,7 +34,7 @@ public final class MurderousBetrayal extends CardImpl { Effect effect = new DestroyTargetEffect(true); Ability ability = new SimpleActivatedAbility(effect, new MurderousBetrayalCost()); ability.addCost(new ManaCostsImpl<>("{B}{B}")); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + ability.addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MurderousCompulsion.java b/Mage.Sets/src/mage/cards/m/MurderousCompulsion.java index 0ceae7d2435..e410c72f58c 100644 --- a/Mage.Sets/src/mage/cards/m/MurderousCompulsion.java +++ b/Mage.Sets/src/mage/cards/m/MurderousCompulsion.java @@ -10,6 +10,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -29,7 +30,7 @@ public final class MurderousCompulsion extends CardImpl { // Destroy target tapped creature. getSpellAbility().addEffect(new DestroyTargetEffect()); - getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + getSpellAbility().addTarget(new TargetPermanent(filter)); // Madness {1}{B} (If you discard card, discard it into exile. When you do, cast it for its madness cost or put it into your graveyard.) this.addAbility(new MadnessAbility(new ManaCostsImpl<>("{1}{B}"))); diff --git a/Mage.Sets/src/mage/cards/m/MurderousSpoils.java b/Mage.Sets/src/mage/cards/m/MurderousSpoils.java index e400860f079..50255a1a2a0 100644 --- a/Mage.Sets/src/mage/cards/m/MurderousSpoils.java +++ b/Mage.Sets/src/mage/cards/m/MurderousSpoils.java @@ -16,9 +16,12 @@ import mage.constants.Outcome; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author wetterlicht @@ -29,7 +32,7 @@ public final class MurderousSpoils extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{5}{B}"); // Destroy target nonblack creature. It can't be regenerated. You gain control of all Equipment that was attached to it. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.getSpellAbility().addEffect(new MurderousSpoilsEffect()); } diff --git a/Mage.Sets/src/mage/cards/m/MutantsPrey.java b/Mage.Sets/src/mage/cards/m/MutantsPrey.java index bad72bb85fa..a05b6763b25 100644 --- a/Mage.Sets/src/mage/cards/m/MutantsPrey.java +++ b/Mage.Sets/src/mage/cards/m/MutantsPrey.java @@ -1,15 +1,13 @@ - - package mage.cards.m; -import java.util.UUID; import mage.abilities.effects.common.FightTargetsEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; -import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** * @author LevelX2 @@ -17,12 +15,12 @@ import mage.target.common.TargetCreaturePermanent; public final class MutantsPrey extends CardImpl { public MutantsPrey(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{G}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{G}"); // Target creature you control with a +1/+1 counter on it fights target creature an opponent controls. this.getSpellAbility().addEffect(new FightTargetsEffect()); - this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_CONTROLLED_CREATURE_P1P1)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_CONTROLLED_CREATURE_P1P1)); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); } private MutantsPrey(final MutantsPrey card) { diff --git a/Mage.Sets/src/mage/cards/m/Mutiny.java b/Mage.Sets/src/mage/cards/m/Mutiny.java index 23ab622d0ed..40caae27b00 100644 --- a/Mage.Sets/src/mage/cards/m/Mutiny.java +++ b/Mage.Sets/src/mage/cards/m/Mutiny.java @@ -15,6 +15,7 @@ import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -30,8 +31,7 @@ public final class Mutiny extends CardImpl { // Target creature an opponent controls deals damage equal to its power to another target creature that player controls. this.getSpellAbility().addEffect(new MutinyEffect()); this.getSpellAbility().addTarget(new MutinyFirstTarget(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("another target creature that player controls"))); - + this.getSpellAbility().addTarget(new TargetPermanent(new FilterCreaturePermanent("another target creature that player controls"))); } private Mutiny(final Mutiny card) { @@ -75,7 +75,7 @@ class MutinyEffect extends OneShotEffect { } -class MutinyFirstTarget extends TargetCreaturePermanent { +class MutinyFirstTarget extends TargetPermanent { public MutinyFirstTarget(FilterCreaturePermanent filter) { super(1, 1, filter, false); diff --git a/Mage.Sets/src/mage/cards/m/MyrServitor.java b/Mage.Sets/src/mage/cards/m/MyrServitor.java index a2024a5a332..bbd9cb03402 100644 --- a/Mage.Sets/src/mage/cards/m/MyrServitor.java +++ b/Mage.Sets/src/mage/cards/m/MyrServitor.java @@ -1,44 +1,38 @@ - package mage.cards.m; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.SourceOnBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.FilterCard; import mage.filter.predicate.mageobject.NamePredicate; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class MyrServitor extends CardImpl { public MyrServitor(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{1}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{1}"); this.subtype.add(SubType.MYR); this.power = new MageInt(1); this.toughness = new MageInt(1); // At the beginning of your upkeep, if Myr Servitor is on the battlefield, each player returns all cards named Myr Servitor from their graveyard to the battlefield. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new MyrServitorReturnEffect()), - SourceOnBattlefieldCondition.instance, - "At the beginning of your upkeep, if {this} is on the battlefield, each player returns all cards named Myr Servitor from their graveyard to the battlefield" - )); - + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new MyrServitorReturnEffect()) + .withInterveningIf(SourceOnBattlefieldCondition.instance)); } private MyrServitor(final MyrServitor card) { @@ -61,7 +55,7 @@ class MyrServitorReturnEffect extends OneShotEffect { public MyrServitorReturnEffect() { super(Outcome.PutCardInPlay); - this.staticText = "if {this} is on the battlefield, each player returns all cards named Myr Servitor from their graveyard to the battlefield"; + this.staticText = "each player returns all cards named Myr Servitor from their graveyard to the battlefield"; } private MyrServitorReturnEffect(final MyrServitorReturnEffect effect) { @@ -75,16 +69,12 @@ class MyrServitorReturnEffect 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) { - controller.moveCards(player.getGraveyard().getCards(filter, game), Zone.BATTLEFIELD, source, game); - } + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + player.moveCards(player.getGraveyard().getCards(filter, game), Zone.BATTLEFIELD, source, game); } - return true; } - return false; + return true; } } diff --git a/Mage.Sets/src/mage/cards/m/MysteriousStranger.java b/Mage.Sets/src/mage/cards/m/MysteriousStranger.java new file mode 100644 index 00000000000..21c1f5eaab8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MysteriousStranger.java @@ -0,0 +1,126 @@ +package mage.cards.m; + +import mage.ApprovingObject; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.FlashAbility; +import mage.cards.*; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.StaticFilters; +import mage.filter.common.FilterInstantOrSorceryCard; +import mage.filter.predicate.card.OwnerIdPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInGraveyard; +import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetpointer.EachTargetPointer; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class MysteriousStranger extends CardImpl { + + public MysteriousStranger(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ROGUE); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // When Mysterious Stranger enters the battlefield, for each graveyard with an instant or sorcery card in it, exile target instant or sorcery card from that graveyard. If two or more cards are exiled this way, choose one of them at random and copy it. You may cast the copy without paying its mana cost. + this.addAbility(new EntersBattlefieldTriggeredAbility(new MysteriousStrangerEffect()) + .setTargetAdjuster(MysteriousStrangerAdjuster.instance)); + } + + private MysteriousStranger(final MysteriousStranger card) { + super(card); + } + + @Override + public MysteriousStranger copy() { + return new MysteriousStranger(this); + } +} + +enum MysteriousStrangerAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + for (UUID playerId : game.getState().getPlayersInRange(ability.getControllerId(), game)) { + Player player = game.getPlayer(playerId); + if (player == null || player.getGraveyard().count(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY, game) < 1) { + continue; + } + FilterCard filter = new FilterInstantOrSorceryCard("instant or sorcery card (owned by " + + (ability.isControlledBy(playerId) ? "you" : player.getLogName()) + ')'); + filter.add(new OwnerIdPredicate(playerId)); + ability.addTarget(new TargetCardInGraveyard(filter)); + } + } +} + +class MysteriousStrangerEffect extends OneShotEffect { + + MysteriousStrangerEffect() { + super(Outcome.Benefit); + staticText = "for each graveyard with an instant or sorcery card in it, " + + "exile target instant or sorcery card from that graveyard. " + + "If two or more cards are exiled this way, choose one of them at random and copy it. " + + "You may cast the copy without paying its mana cost"; + this.setTargetPointer(new EachTargetPointer()); + } + + private MysteriousStrangerEffect(final MysteriousStrangerEffect effect) { + super(effect); + } + + @Override + public MysteriousStrangerEffect copy() { + return new MysteriousStrangerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Cards cards = new CardsImpl(getTargetPointer().getTargets(game, source)); + cards.retainZone(Zone.GRAVEYARD, game); + if (player == null || cards.isEmpty()) { + return false; + } + player.moveCards(cards, Zone.EXILED, source, game); + cards.retainZone(Zone.EXILED, game); + if (cards.size() < 2) { + return true; + } + Card card = cards.getRandom(game); + if (card == null) { + return true; + } + Card copiedCard = game.copyCard(card, source, source.getControllerId()); + if (!player.chooseUse(Outcome.PlayForFree, "Cast a copy of " + + card.getLogName() + " without paying its mana cost?", source, game)) { + return true; + } + game.getState().setValue("PlayFromNotOwnHandZone" + copiedCard.getId(), Boolean.TRUE); + player.cast( + player.chooseAbilityForCast(copiedCard, game, true), + game, true, new ApprovingObject(source, game) + ); + game.getState().setValue("PlayFromNotOwnHandZone" + copiedCard.getId(), null); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/m/MystifyingMaze.java b/Mage.Sets/src/mage/cards/m/MystifyingMaze.java index 6ff0835d94f..cb9104a1ba4 100644 --- a/Mage.Sets/src/mage/cards/m/MystifyingMaze.java +++ b/Mage.Sets/src/mage/cards/m/MystifyingMaze.java @@ -19,6 +19,7 @@ import mage.constants.Zone; import mage.filter.common.FilterAttackingCreature; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; @@ -44,7 +45,7 @@ public final class MystifyingMaze extends CardImpl { // {4}, {T}: Exile target attacking creature an opponent controls. At the beginning of the next end step, return it to the battlefield tapped under its owner's control. Ability ability = new SimpleActivatedAbility(new MystifyingMazeEffect(), new ManaCostsImpl<>("{4}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/m/MythosOfIlluna.java b/Mage.Sets/src/mage/cards/m/MythosOfIlluna.java index 606f0b9ee2a..7a1c03f658f 100644 --- a/Mage.Sets/src/mage/cards/m/MythosOfIlluna.java +++ b/Mage.Sets/src/mage/cards/m/MythosOfIlluna.java @@ -5,16 +5,16 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.CompoundCondition; import mage.abilities.condition.Condition; import mage.abilities.condition.common.ManaWasSpentCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.SourceMatchesFilterCondition; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenCopyTargetEffect; import mage.abilities.effects.common.FightTargetSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.ColoredManaSymbol; import mage.constants.Outcome; import mage.filter.StaticFilters; +import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; @@ -50,12 +50,13 @@ class MythosOfIllunaEffect extends OneShotEffect { ManaWasSpentCondition.RED, ManaWasSpentCondition.GREEN ); + private static final Condition condition2 = new SourceMatchesFilterCondition(new FilterCreaturePermanent("it's a creature")); MythosOfIllunaEffect() { super(Outcome.Benefit); staticText = "Create a token that's a copy of target permanent. " + "If {R}{G} was spent to cast this spell, instead create a token that's a copy of that permanent, " + - "except the token has \"When this permanent enters the battlefield, if it's a creature, " + + "except the token has \"When this token enters, if it's a creature, " + "it fights up to one target creature you don't control.\""; } @@ -75,15 +76,15 @@ class MythosOfIllunaEffect extends OneShotEffect { return false; } CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(source.getControllerId()); - if (condition.apply(game, source)) { - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new FightTargetSourceEffect()), - MythosOfIllunaCondition.instance, "When this permanent enters, " + - "if it's a creature, it fights up to one target creature you don't control." - ); - ability.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL, false)); - effect.addAdditionalAbilities(ability); + if (!condition.apply(game, source)) { + return effect.apply(game, source); } + Ability ability = new EntersBattlefieldTriggeredAbility(new FightTargetSourceEffect() + .setText("it fights up to one target creature you don't control")) + .setTriggerPhrase("When this token enters, ") + .withInterveningIf(condition2); + ability.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + effect.addAdditionalAbilities(ability); return effect.apply(game, source); } diff --git a/Mage.Sets/src/mage/cards/n/N1Starfighter.java b/Mage.Sets/src/mage/cards/n/N1Starfighter.java index 2d7997412ad..807950858b7 100644 --- a/Mage.Sets/src/mage/cards/n/N1Starfighter.java +++ b/Mage.Sets/src/mage/cards/n/N1Starfighter.java @@ -13,6 +13,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import java.util.UUID; @@ -37,7 +38,7 @@ public final class N1Starfighter extends CardImpl { doIfCostPaid.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false).concatBy(", then")); Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(doIfCostPaid, false); - ability.addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/n/NahiriHeirOfTheAncients.java b/Mage.Sets/src/mage/cards/n/NahiriHeirOfTheAncients.java index a3971466c9f..e1776c59374 100644 --- a/Mage.Sets/src/mage/cards/n/NahiriHeirOfTheAncients.java +++ b/Mage.Sets/src/mage/cards/n/NahiriHeirOfTheAncients.java @@ -1,6 +1,5 @@ package mage.cards.n; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; import mage.abilities.dynamicvalue.DynamicValue; @@ -15,7 +14,7 @@ import mage.filter.FilterCard; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.Predicates; -import mage.filter.predicate.permanent.PermanentIdPredicate; +import mage.filter.predicate.permanent.PermanentReferenceInCollectionPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.KorWarriorToken; @@ -119,12 +118,7 @@ class NahiriHeirOfTheAncientsEffect extends OneShotEffect { Permanent tokenCreature = tokens.get(0); if (tokens.size() > 1) { FilterPermanent tokenFilter = new FilterPermanent("token"); - tokenFilter.add(Predicates.or( - tokens.stream() - .map(MageObject::getId) - .map(PermanentIdPredicate::new) - .collect(Collectors.toSet()) - )); + tokenFilter.add(new PermanentReferenceInCollectionPredicate(tokens, game)); TargetPermanent target = new TargetPermanent(tokenFilter); target.withNotTarget(true); player.choose(outcome, target, source, game); diff --git a/Mage.Sets/src/mage/cards/n/NahirisMachinations.java b/Mage.Sets/src/mage/cards/n/NahirisMachinations.java index a37a28dda48..284d29c2d7f 100644 --- a/Mage.Sets/src/mage/cards/n/NahirisMachinations.java +++ b/Mage.Sets/src/mage/cards/n/NahirisMachinations.java @@ -15,6 +15,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterBlockingCreature; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; @@ -34,7 +35,7 @@ public final class NahirisMachinations extends CardImpl { // {1}{R}: Nahiri's Machinations deals 1 damage to target blocking creature. ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new ManaCostsImpl<>("{1}{R}")); - ability.addTarget(new TargetCreaturePermanent(new FilterBlockingCreature("blocking creature"))); + ability.addTarget(new TargetPermanent(new FilterBlockingCreature("blocking creature"))); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/n/NajeelaTheBladeBlossom.java b/Mage.Sets/src/mage/cards/n/NajeelaTheBladeBlossom.java index 95d30ba9b08..c335bce3ad6 100644 --- a/Mage.Sets/src/mage/cards/n/NajeelaTheBladeBlossom.java +++ b/Mage.Sets/src/mage/cards/n/NajeelaTheBladeBlossom.java @@ -1,13 +1,13 @@ package mage.cards.n; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksAllTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.IsPhaseCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.common.AdditionalCombatPhaseEffect; import mage.abilities.effects.common.CreateTokenTargetEffect; @@ -18,24 +18,20 @@ import mage.abilities.keyword.LifelinkAbility; import mage.abilities.keyword.TrampleAbility; 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.SuperType; -import mage.constants.TurnPhase; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.game.permanent.token.WarriorToken; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class NajeelaTheBladeBlossom extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.WARRIOR, "Warrior"); + private static final Condition condition = new IsPhaseCondition(TurnPhase.COMBAT); public NajeelaTheBladeBlossom(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); @@ -54,25 +50,20 @@ public final class NajeelaTheBladeBlossom extends CardImpl { )); // {W}{U}{B}{R}{G}: Untap all attacking creatures. They gain trample, lifelink, and haste until end of turn. After this phase, there is an additional combat phase. Activate this ability only during combat. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, + Ability ability = new ActivateIfConditionActivatedAbility( new UntapAllEffect(StaticFilters.FILTER_ATTACKING_CREATURES), - new ManaCostsImpl<>("{W}{U}{B}{R}{G}"), - new IsPhaseCondition(TurnPhase.COMBAT) + new ManaCostsImpl<>("{W}{U}{B}{R}{G}"), condition ); ability.addEffect(new GainAbilityAllEffect( - TrampleAbility.getInstance(), - Duration.EndOfTurn, + TrampleAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_ATTACKING_CREATURES ).setText("They gain trample")); ability.addEffect(new GainAbilityAllEffect( - LifelinkAbility.getInstance(), - Duration.EndOfTurn, + LifelinkAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_ATTACKING_CREATURES ).setText(", lifelink")); ability.addEffect(new GainAbilityAllEffect( - HasteAbility.getInstance(), - Duration.EndOfTurn, + HasteAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_ATTACKING_CREATURES ).setText(", and haste until end of turn")); ability.addEffect(new AdditionalCombatPhaseEffect()); diff --git a/Mage.Sets/src/mage/cards/n/NaliaDeArnise.java b/Mage.Sets/src/mage/cards/n/NaliaDeArnise.java index 3101cd723a5..f1a1a484728 100644 --- a/Mage.Sets/src/mage/cards/n/NaliaDeArnise.java +++ b/Mage.Sets/src/mage/cards/n/NaliaDeArnise.java @@ -2,19 +2,21 @@ package mage.cards.n; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.FullPartyCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.abilities.effects.common.continuous.LookAtTopCardOfLibraryAnyTimeEffect; import mage.abilities.effects.common.continuous.PlayFromTopOfLibraryEffect; import mage.abilities.effects.common.counter.AddCountersAllEffect; import mage.abilities.hint.common.PartyCountHint; import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.counters.CounterType; import mage.filter.FilterCard; import mage.filter.StaticFilters; @@ -54,17 +56,13 @@ public final class NaliaDeArnise extends CardImpl { this.addAbility(new SimpleStaticAbility(new PlayFromTopOfLibraryEffect(filter))); // At the beginning of combat on your turn, if you have a full party, put a +1/+1 counter on each creature you control and those creatures gain deathtouch until end of turn. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility(new AddCountersAllEffect( - CounterType.P1P1.createInstance(), StaticFilters.FILTER_CONTROLLED_CREATURE - )), FullPartyCondition.instance, "At the beginning " + - "of combat on your turn, if you have a full party, put a +1/+1 counter on each creature " + - "you control and those creatures gain deathtouch until end of turn." - ); + Ability ability = new BeginningOfCombatTriggeredAbility(new AddCountersAllEffect( + CounterType.P1P1.createInstance(), StaticFilters.FILTER_CONTROLLED_CREATURE + )).withInterveningIf(FullPartyCondition.instance); ability.addEffect(new GainAbilityAllEffect( DeathtouchAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURE - )); + ).setText("and those creatures gain deathtouch until end of turn")); this.addAbility(ability.addHint(PartyCountHint.instance)); } diff --git a/Mage.Sets/src/mage/cards/n/NantukoMonastery.java b/Mage.Sets/src/mage/cards/n/NantukoMonastery.java index 2d5d06dff11..167a029fb6d 100644 --- a/Mage.Sets/src/mage/cards/n/NantukoMonastery.java +++ b/Mage.Sets/src/mage/cards/n/NantukoMonastery.java @@ -3,7 +3,7 @@ package mage.cards.n; import mage.MageInt; import mage.abilities.condition.common.ThresholdCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.mana.ColorlessManaAbility; @@ -29,7 +29,7 @@ public final class NantukoMonastery extends CardImpl { this.addAbility(new ColorlessManaAbility()); // Threshold - {G}{W}: Nantuko Monastery becomes a 4/4 green and white Insect Monk creature with first strike until end of turn. It's still a land. Activate this ability only if seven or more cards are in your graveyard. - this.addAbility(new ConditionalActivatedAbility(new BecomesCreatureSourceEffect( + this.addAbility(new ActivateIfConditionActivatedAbility(new BecomesCreatureSourceEffect( new NantukoMonasteryToken(), CardType.LAND, Duration.EndOfTurn), new ManaCostsImpl<>("{G}{W}"), ThresholdCondition.instance ).setAbilityWord(AbilityWord.THRESHOLD)); diff --git a/Mage.Sets/src/mage/cards/n/NantukoShaman.java b/Mage.Sets/src/mage/cards/n/NantukoShaman.java index fb71f184ff2..7c5c9b60473 100644 --- a/Mage.Sets/src/mage/cards/n/NantukoShaman.java +++ b/Mage.Sets/src/mage/cards/n/NantukoShaman.java @@ -1,36 +1,37 @@ - package mage.cards.n; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.keyword.SuspendAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.ComparisonType; +import mage.constants.SubType; import mage.filter.common.FilterLandPermanent; import mage.filter.predicate.permanent.TappedPredicate; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class NantukoShaman extends CardImpl { - private static final FilterLandPermanent filter = new FilterLandPermanent(); + private static final FilterLandPermanent filter = new FilterLandPermanent("you control no tapped lands"); + static { filter.add(TappedPredicate.TAPPED); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.EQUAL_TO, 0); + public NantukoShaman(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); this.subtype.add(SubType.INSECT); this.subtype.add(SubType.SHAMAN); @@ -38,11 +39,7 @@ public final class NantukoShaman extends CardImpl { this.toughness = new MageInt(2); // When Nantuko Shaman enters the battlefield, if you control no tapped lands, draw a card. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)), - new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.EQUAL_TO, 0), - "When {this} enters, if you control no tapped lands, draw a card."); - this.addAbility(ability); + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)).withInterveningIf(condition)); // Suspend 1-{2}{G}{G} this.addAbility(new SuspendAbility(1, new ManaCostsImpl<>("{2}{G}{G}"), this)); diff --git a/Mage.Sets/src/mage/cards/n/NaomiPillarOfOrder.java b/Mage.Sets/src/mage/cards/n/NaomiPillarOfOrder.java index 411846fd272..78f56a14c48 100644 --- a/Mage.Sets/src/mage/cards/n/NaomiPillarOfOrder.java +++ b/Mage.Sets/src/mage/cards/n/NaomiPillarOfOrder.java @@ -3,7 +3,6 @@ package mage.cards.n; import mage.MageInt; import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility; import mage.abilities.condition.common.ControlArtifactAndEnchantmentCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.hint.common.ControlArtifactAndEnchantmentHint; import mage.cards.CardImpl; @@ -30,11 +29,8 @@ public final class NaomiPillarOfOrder extends CardImpl { this.toughness = new MageInt(4); // Whenever Naomi, Pillar of Order enters the battlefield or attacks, if you control an artifact and an enchantment, create a 2/2 white Samurai creature token with vigilance. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldOrAttacksSourceTriggeredAbility(new CreateTokenEffect(new SamuraiToken())), - ControlArtifactAndEnchantmentCondition.instance, "Whenever {this} enters or " + - "attacks, if you control an artifact and an enchantment, create a 2/2 white Samurai creature token with vigilance." - ).addHint(ControlArtifactAndEnchantmentHint.instance)); + this.addAbility(new EntersBattlefieldOrAttacksSourceTriggeredAbility(new CreateTokenEffect(new SamuraiToken())) + .withInterveningIf(ControlArtifactAndEnchantmentCondition.instance).addHint(ControlArtifactAndEnchantmentHint.instance)); } private NaomiPillarOfOrder(final NaomiPillarOfOrder card) { diff --git a/Mage.Sets/src/mage/cards/n/NaturesWay.java b/Mage.Sets/src/mage/cards/n/NaturesWay.java index 451ade62eef..aa31e9ba1ac 100644 --- a/Mage.Sets/src/mage/cards/n/NaturesWay.java +++ b/Mage.Sets/src/mage/cards/n/NaturesWay.java @@ -9,11 +9,14 @@ 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 mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author LevelX2 */ @@ -31,7 +34,7 @@ public final class NaturesWay extends CardImpl { // It deals damage equal to its power to target creature you don't control. this.getSpellAbility().addEffect(new DamageWithPowerFromOneToAnotherTargetEffect("It")); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); // second target + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); // second target } private NaturesWay(final NaturesWay card) { diff --git a/Mage.Sets/src/mage/cards/n/NavigatorsRuin.java b/Mage.Sets/src/mage/cards/n/NavigatorsRuin.java index 846b7b84c20..0b6f0995e22 100644 --- a/Mage.Sets/src/mage/cards/n/NavigatorsRuin.java +++ b/Mage.Sets/src/mage/cards/n/NavigatorsRuin.java @@ -1,11 +1,10 @@ package mage.cards.n; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.MillCardsTargetEffect; import mage.abilities.hint.common.RaidHint; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AbilityWord; @@ -24,16 +23,10 @@ public final class NavigatorsRuin extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); // 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 MillCardsTargetEffect(4)), - RaidCondition.instance, - "At the beginning of your end step, " + - "if you attacked this turn, target opponent mills four cards." - ); + Ability ability = new BeginningOfEndStepTriggeredAbility(new MillCardsTargetEffect(4)) + .withInterveningIf(RaidCondition.instance); ability.addTarget(new TargetOpponent()); - ability.setAbilityWord(AbilityWord.RAID); - ability.addHint(RaidHint.instance); - this.addAbility(ability, new PlayerAttackedWatcher()); + this.addAbility(ability.setAbilityWord(AbilityWord.RAID).addHint(RaidHint.instance), new PlayerAttackedWatcher()); } private NavigatorsRuin(final NavigatorsRuin card) { diff --git a/Mage.Sets/src/mage/cards/n/NazahnReveredBladesmith.java b/Mage.Sets/src/mage/cards/n/NazahnReveredBladesmith.java index 190e36257b9..8abdfc14b67 100644 --- a/Mage.Sets/src/mage/cards/n/NazahnReveredBladesmith.java +++ b/Mage.Sets/src/mage/cards/n/NazahnReveredBladesmith.java @@ -21,8 +21,8 @@ import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.filter.predicate.permanent.EquippedPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCardInLibrary; -import mage.target.common.TargetCreaturePermanent; import mage.target.targetadjustment.TargetAdjuster; import java.util.UUID; @@ -61,7 +61,7 @@ public final class NazahnReveredBladesmith extends CardImpl { // Whenever an equipped creature you control attacks, you may tap target creature defending player controls. Ability ability = new AttacksCreatureYouControlTriggeredAbility(new NazahnTapEffect(), true, equippedFilter, true); - ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature defending player controls"))); + ability.addTarget(new TargetPermanent(new FilterCreaturePermanent("creature defending player controls"))); ability.setTargetAdjuster(NazahnReveredBladesmithAdjuster.instance); this.addAbility(ability); } @@ -89,8 +89,7 @@ enum NazahnReveredBladesmithAdjuster implements TargetAdjuster { } } ability.getTargets().clear(); - TargetCreaturePermanent target = new TargetCreaturePermanent(filterDefender); - ability.addTarget(target); + ability.addTarget(new TargetPermanent(filterDefender)); } } diff --git a/Mage.Sets/src/mage/cards/n/Nebuchadnezzar.java b/Mage.Sets/src/mage/cards/n/Nebuchadnezzar.java index 20048051a12..39eeffa252b 100644 --- a/Mage.Sets/src/mage/cards/n/Nebuchadnezzar.java +++ b/Mage.Sets/src/mage/cards/n/Nebuchadnezzar.java @@ -9,9 +9,11 @@ import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ChooseACardNameEffect; -import mage.abilities.hint.common.MyTurnHint; import mage.cards.*; -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.players.Player; import mage.target.common.TargetOpponent; @@ -33,11 +35,13 @@ public final class Nebuchadnezzar extends CardImpl { this.toughness = new MageInt(3); // {X}, {T}: Choose a card name. Target opponent reveals X cards at random from their hand. Then that player discards all cards with that name revealed this way. Activate this ability only during your turn. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL), new ManaCostsImpl<>("{X}"), MyTurnCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL), + new ManaCostsImpl<>("{X}"), MyTurnCondition.instance + ); ability.addCost(new TapSourceCost()); ability.addEffect(new NebuchadnezzarEffect()); ability.addTarget(new TargetOpponent()); - ability.addHint(MyTurnHint.instance); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/n/NecraSanctuary.java b/Mage.Sets/src/mage/cards/n/NecraSanctuary.java index 4696cd265c8..c998f69081c 100644 --- a/Mage.Sets/src/mage/cards/n/NecraSanctuary.java +++ b/Mage.Sets/src/mage/cards/n/NecraSanctuary.java @@ -1,18 +1,17 @@ - package mage.cards.n; -import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.common.SanctuaryInterveningIfTriggeredAbility; +import mage.abilities.common.SanctuaryTriggeredAbility; import mage.abilities.effects.common.LoseLifeTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.target.TargetPlayer; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class NecraSanctuary extends CardImpl { @@ -21,10 +20,9 @@ public final class NecraSanctuary extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}"); // At the beginning of your upkeep, if you control a green or white permanent, target player loses 1 life. If you control a green permanent and a white permanent, that player loses 3 life instead. - Ability ability = new SanctuaryInterveningIfTriggeredAbility( + Ability ability = new SanctuaryTriggeredAbility( new LoseLifeTargetEffect(1), new LoseLifeTargetEffect(3), ObjectColor.GREEN, ObjectColor.WHITE, - "At the beginning of your upkeep, if you control a green or white permanent, " - + "target player loses 1 life. If you control a green permanent and a white permanent, that player loses 3 life instead." + "target player loses 1 life. If you control a green permanent and a white permanent, that player loses 3 life instead." ); ability.addTarget(new TargetPlayer()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/n/Necrite.java b/Mage.Sets/src/mage/cards/n/Necrite.java index bc0b994b982..0ce99f7ef0e 100644 --- a/Mage.Sets/src/mage/cards/n/Necrite.java +++ b/Mage.Sets/src/mage/cards/n/Necrite.java @@ -1,44 +1,42 @@ - package mage.cards.n; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksAndIsNotBlockedTriggeredAbility; import mage.abilities.costs.common.SacrificeSourceCost; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.DoIfCostPaid; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SetTargetPointer; import mage.constants.SubType; import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.target.Target; import mage.target.TargetPermanent; +import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster; + +import java.util.UUID; /** - * * @author MarcoMarin */ public final class Necrite extends CardImpl { + private static final FilterPermanent filter = new FilterCreaturePermanent("creature defending player controls"); + public Necrite(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.THRULL); this.power = new MageInt(2); this.toughness = new MageInt(2); // Whenever Necrite attacks and isn't blocked, you may sacrifice it. If you do, destroy target creature defending player controls. It can't be regenerated. DoIfCostPaid effect = new DoIfCostPaid(new DestroyTargetEffect(true), new SacrificeSourceCost(), "Sacrifice {this} to destroy target creature defending player controls?"); - effect.setText("you may sacrifice it. If you do, destroy target creature defending player controls. It can't be regenerated."); - Ability ability = new NecriteTriggeredAbility(effect); + Ability ability = new AttacksAndIsNotBlockedTriggeredAbility(effect, false, SetTargetPointer.PLAYER); + ability.addTarget(new TargetPermanent(filter)); + ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster()); this.addAbility(ability); - } private Necrite(final Necrite card) { @@ -50,33 +48,3 @@ public final class Necrite extends CardImpl { return new Necrite(this); } } - -class NecriteTriggeredAbility extends AttacksAndIsNotBlockedTriggeredAbility{ - - public NecriteTriggeredAbility(Effect effect) { - super(effect); - } - - private NecriteTriggeredAbility(final NecriteTriggeredAbility ability) { - super(ability); - } - - @Override - public NecriteTriggeredAbility copy() { - return new NecriteTriggeredAbility(this); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (super.checkTrigger(event, game)){ - UUID defendingPlayerId = game.getCombat().getDefendingPlayerId(getSourceId(), game); - FilterPermanent filter = new FilterCreaturePermanent(); - filter.add(new ControllerIdPredicate(defendingPlayerId)); - Target target = new TargetPermanent(filter); - this.getTargets().clear(); - this.addTarget(target); - return true; - } - return false; - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/n/Necrosavant.java b/Mage.Sets/src/mage/cards/n/Necrosavant.java index 44c5d86dc5e..65e33666d87 100644 --- a/Mage.Sets/src/mage/cards/n/Necrosavant.java +++ b/Mage.Sets/src/mage/cards/n/Necrosavant.java @@ -1,25 +1,22 @@ - package mage.cards.n; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.PhaseStep; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.StaticFilters; -import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; /** - * * @author Quercitron */ public final class Necrosavant extends CardImpl { @@ -33,11 +30,10 @@ public final class Necrosavant extends CardImpl { this.toughness = new MageInt(5); // {3}{B}{B}, Sacrifice a creature: Return Necrosavant from your graveyard to the battlefield. Activate this ability only during your upkeep. - Ability ability = new ConditionalActivatedAbility(Zone.GRAVEYARD, - new ReturnSourceFromGraveyardToBattlefieldEffect(false,false), - new ManaCostsImpl<>("{3}{B}{B}"), - new IsStepCondition(PhaseStep.UPKEEP), - null + Ability ability = new ActivateIfConditionActivatedAbility( + Zone.GRAVEYARD, + new ReturnSourceFromGraveyardToBattlefieldEffect(false, false), + new ManaCostsImpl<>("{3}{B}{B}"), IsStepCondition.getMyUpkeep() ); ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_CREATURE)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/n/NecroticPlague.java b/Mage.Sets/src/mage/cards/n/NecroticPlague.java index 3827b308fc9..91bfa44657b 100644 --- a/Mage.Sets/src/mage/cards/n/NecroticPlague.java +++ b/Mage.Sets/src/mage/cards/n/NecroticPlague.java @@ -85,6 +85,7 @@ enum NecroticPlagueAdjuster implements TargetAdjuster { ability.setControllerId(creatureController.getId()); ability.getTargets().clear(); TargetPermanent target = new TargetOpponentsCreaturePermanent(); + target.setAbilityController(ability.getControllerId()); target.setTargetController(creatureController.getId()); ability.getTargets().add(target); } diff --git a/Mage.Sets/src/mage/cards/n/NeedletoothRaptor.java b/Mage.Sets/src/mage/cards/n/NeedletoothRaptor.java index d69ab55059b..17a6e1e8ebb 100644 --- a/Mage.Sets/src/mage/cards/n/NeedletoothRaptor.java +++ b/Mage.Sets/src/mage/cards/n/NeedletoothRaptor.java @@ -11,8 +11,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author L_J @@ -27,7 +30,7 @@ public final class NeedletoothRaptor extends CardImpl { // Enrage — Whenever Needletooth Raptor is dealt damage, it deals 5 damage to target creature an opponent controls. Ability ability = new DealtDamageToSourceTriggeredAbility(new DamageTargetEffect(5).setText("it deals 5 damage to target creature an opponent controls"), false, true); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/n/NeighborhoodGuardian.java b/Mage.Sets/src/mage/cards/n/NeighborhoodGuardian.java index 9e6d8fd9a4a..64f85fb2446 100644 --- a/Mage.Sets/src/mage/cards/n/NeighborhoodGuardian.java +++ b/Mage.Sets/src/mage/cards/n/NeighborhoodGuardian.java @@ -2,7 +2,7 @@ package mage.cards.n; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -10,7 +10,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.SubType; import mage.filter.FilterPermanent; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.mageobject.PowerPredicate; import mage.target.common.TargetControlledCreaturePermanent; @@ -22,7 +22,7 @@ import java.util.UUID; */ public final class NeighborhoodGuardian extends CardImpl { - private static final FilterPermanent filter = new FilterCreaturePermanent("another creature with power 2 or less"); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("another creature you control with power 2 or less"); static { filter.add(AnotherPredicate.instance); @@ -37,7 +37,7 @@ public final class NeighborhoodGuardian extends CardImpl { this.toughness = new MageInt(2); // Whenever another creature with power 2 or less you control enters, target creature you control gets +1/+1 until end of turn. - Ability ability = new EntersBattlefieldControlledTriggeredAbility(new BoostTargetEffect(1, 1), filter); + Ability ability = new EntersBattlefieldAllTriggeredAbility(new BoostTargetEffect(1, 1), filter); ability.addTarget(new TargetControlledCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/n/Nekrataal.java b/Mage.Sets/src/mage/cards/n/Nekrataal.java index 4b257515b8c..3de53b4175a 100644 --- a/Mage.Sets/src/mage/cards/n/Nekrataal.java +++ b/Mage.Sets/src/mage/cards/n/Nekrataal.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -44,7 +45,7 @@ public final class Nekrataal extends CardImpl { // When Nekrataal enters the battlefield, destroy target nonartifact, nonblack creature. That creature can't be regenerated. Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(true)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/n/NemesisPhoenix.java b/Mage.Sets/src/mage/cards/n/NemesisPhoenix.java index d58da3b3b3e..9bf9a9f8466 100644 --- a/Mage.Sets/src/mage/cards/n/NemesisPhoenix.java +++ b/Mage.Sets/src/mage/cards/n/NemesisPhoenix.java @@ -39,7 +39,7 @@ public final class NemesisPhoenix extends CardImpl { this.addAbility(new ActivateIfConditionActivatedAbility( Zone.GRAVEYARD, new ReturnToBattlefieldUnderOwnerControlSourceEffect(true, true, -1) - .setText("return {this} from your graveyard to the battlefield tapped and attacking"), + .setText("return this card from your graveyard to the battlefield tapped and attacking"), new ManaCostsImpl<>("{2}{R}"), NemesisPhoenixCondition.instance )); } diff --git a/Mage.Sets/src/mage/cards/n/NephaliaSmuggler.java b/Mage.Sets/src/mage/cards/n/NephaliaSmuggler.java index 42bb23a4cad..02aa626caeb 100644 --- a/Mage.Sets/src/mage/cards/n/NephaliaSmuggler.java +++ b/Mage.Sets/src/mage/cards/n/NephaliaSmuggler.java @@ -10,9 +10,8 @@ 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.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -32,7 +31,7 @@ public final class NephaliaSmuggler extends CardImpl { // {3}{U}, {tap}: Exile another target creature you control, then return that card to the battlefield under your control. Ability ability = new SimpleActivatedAbility(new ExileThenReturnTargetEffect(true, true), new ManaCostsImpl<>("{3}{U}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/n/NerdRage.java b/Mage.Sets/src/mage/cards/n/NerdRage.java index e1a8568bd12..2f45373c802 100644 --- a/Mage.Sets/src/mage/cards/n/NerdRage.java +++ b/Mage.Sets/src/mage/cards/n/NerdRage.java @@ -1,31 +1,32 @@ package mage.cards.n; -import java.util.UUID; - import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInHandCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.Effect; +import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.effects.common.continuous.MaximumHandSizeControllerEffect; -import mage.constants.*; -import mage.target.common.TargetCreaturePermanent; -import mage.abilities.effects.common.AttachEffect; -import mage.target.TargetPermanent; import mage.abilities.keyword.EnchantAbility; 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 Cguy7777 */ public final class NerdRage extends CardImpl { + private static final Condition condition = new CardsInHandCondition(ComparisonType.MORE_THAN, 9); + public NerdRage(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); @@ -42,22 +43,17 @@ public final class NerdRage extends CardImpl { // Enchanted creature has "You have no maximum hand size" and "Whenever this creature attacks, // if you have ten or more cards in hand, it gets +10/+10 until end of turn." - SimpleStaticAbility noMaxHandSizeAbility = new SimpleStaticAbility(new MaximumHandSizeControllerEffect( - Integer.MAX_VALUE, - Duration.WhileOnBattlefield, - MaximumHandSizeControllerEffect.HandSizeModification.SET)); - ConditionalInterveningIfTriggeredAbility attacksBoostAbility = new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new BoostSourceEffect(10, 10, Duration.EndOfTurn)), - new CardsInHandCondition(ComparisonType.MORE_THAN, 9), - "Whenever {this} attacks, if you have ten or more cards in hand, it gets +10/+10 until end of turn."); - - Effect gainNoMaxHandSizeEffect = new GainAbilityAttachedEffect(noMaxHandSizeAbility, AttachmentType.AURA) - .setText("Enchanted creature has \"You have no maximum hand size\""); - Effect gainAttacksBoostEffect = new GainAbilityAttachedEffect(attacksBoostAbility, AttachmentType.AURA) - .setText("\"Whenever this creature attacks, if you have ten or more cards in hand, it gets +10/+10 until end of turn.\""); - - Ability ability = new SimpleStaticAbility(gainNoMaxHandSizeEffect); - ability.addEffect(gainAttacksBoostEffect.concatBy("and")); + Ability ability = new SimpleStaticAbility(new GainAbilityAttachedEffect( + new SimpleStaticAbility(new MaximumHandSizeControllerEffect( + Integer.MAX_VALUE, Duration.WhileOnBattlefield, + MaximumHandSizeControllerEffect.HandSizeModification.SET + )), AttachmentType.AURA + ).setText("Enchanted creature has \"You have no maximum hand size\"")); + ability.addEffect(new GainAbilityAttachedEffect( + new AttacksTriggeredAbility(new BoostSourceEffect( + 10, 10, Duration.EndOfTurn, "it" + )).withInterveningIf(condition), AttachmentType.AURA + ).setText("and \"Whenever this creature attacks, if you have ten or more cards in hand, it gets +10/+10 until end of turn.\"")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/n/NessianDemolok.java b/Mage.Sets/src/mage/cards/n/NessianDemolok.java index 2091b1ddbde..aa6f76928ff 100644 --- a/Mage.Sets/src/mage/cards/n/NessianDemolok.java +++ b/Mage.Sets/src/mage/cards/n/NessianDemolok.java @@ -1,12 +1,9 @@ - package mage.cards.n; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TributeNotPaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.TributeAbility; import mage.cards.CardImpl; @@ -17,8 +14,9 @@ import mage.filter.FilterPermanent; import mage.filter.predicate.Predicates; import mage.target.TargetPermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class NessianDemolok extends CardImpl { @@ -30,19 +28,20 @@ public final class NessianDemolok extends CardImpl { } public NessianDemolok(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}"); this.subtype.add(SubType.BEAST); this.power = new MageInt(3); this.toughness = new MageInt(3); - // Tribute 3 + // Tribute 3 this.addAbility(new TributeAbility(3)); + // When Nessian Demolok enters the battlefield, if tribute wasn't paid, destroy target noncreature permanent. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), false); + Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()) + .withInterveningIf(TributeNotPaidCondition.instance); ability.addTarget(new TargetPermanent(filter)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TributeNotPaidCondition.instance, - "When {this} enters, if tribute wasn't paid, destroy target noncreature permanent.")); + this.addAbility(ability); } private NessianDemolok(final NessianDemolok card) { diff --git a/Mage.Sets/src/mage/cards/n/NessianHornbeetle.java b/Mage.Sets/src/mage/cards/n/NessianHornbeetle.java index bf85dd5896a..2d4799e8af9 100644 --- a/Mage.Sets/src/mage/cards/n/NessianHornbeetle.java +++ b/Mage.Sets/src/mage/cards/n/NessianHornbeetle.java @@ -1,11 +1,10 @@ package mage.cards.n; import mage.MageInt; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -14,8 +13,8 @@ import mage.constants.SubType; import mage.counters.CounterType; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.mageobject.PowerPredicate; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.predicate.mageobject.PowerPredicate; import java.util.UUID; @@ -24,7 +23,8 @@ import java.util.UUID; */ public final class NessianHornbeetle extends CardImpl { - private static final FilterPermanent filter = new FilterControlledCreaturePermanent(); + private static final FilterPermanent filter + = new FilterControlledCreaturePermanent("you control another creature with power 4 or greater"); static { filter.add(AnotherPredicate.instance); @@ -41,12 +41,9 @@ public final class NessianHornbeetle extends CardImpl { this.toughness = new MageInt(2); // At the beginning of combat on your turn, if you control another creature with power 4 or greater, put a +1/+1 counter on Nessian Hornbeetle. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility( - new AddCountersSourceEffect(CounterType.P1P1.createInstance()) - ), condition, "At the beginning of combat on your turn, if you control " + - "another creature with power 4 or greater, put a +1/+1 counter on {this}." - )); + this.addAbility(new BeginningOfCombatTriggeredAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance()) + ).withInterveningIf(condition)); } private NessianHornbeetle(final NessianHornbeetle card) { diff --git a/Mage.Sets/src/mage/cards/n/NessianWildsRavager.java b/Mage.Sets/src/mage/cards/n/NessianWildsRavager.java index 71ada8edfe5..4079623e1a7 100644 --- a/Mage.Sets/src/mage/cards/n/NessianWildsRavager.java +++ b/Mage.Sets/src/mage/cards/n/NessianWildsRavager.java @@ -1,35 +1,27 @@ - package mage.cards.n; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TributeNotPaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.FightTargetSourceEffect; import mage.abilities.keyword.TributeAbility; 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.AnotherPredicate; -import mage.target.common.TargetCreaturePermanent; +import mage.filter.StaticFilters; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class NessianWildsRavager extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); - static { - filter.add(AnotherPredicate.instance); - } - public NessianWildsRavager(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}{G}"); this.subtype.add(SubType.HYDRA); this.power = new MageInt(6); @@ -37,15 +29,13 @@ public final class NessianWildsRavager extends CardImpl { // Tribute 6 this.addAbility(new TributeAbility(6)); + // When Nessian Wilds Ravager enters the battlefield, if tribute wasn't paid, you may have Nessian Wilds Ravager fight another target creature. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new FightTargetSourceEffect(), true); - ability.addTarget(new TargetCreaturePermanent(filter)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - ability, - TributeNotPaidCondition.instance, - "When {this} enters, if tribute wasn't paid, " + - "you may have {this} fight another target creature. " + - "(Each deals damage equal to its power to the other.)")); + Ability ability = new EntersBattlefieldTriggeredAbility( + new FightTargetSourceEffect().setText("have {this} fight another target creature"), true + ).withInterveningIf(TributeNotPaidCondition.instance); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + this.addAbility(ability); } private NessianWildsRavager(final NessianWildsRavager card) { diff --git a/Mage.Sets/src/mage/cards/n/NestOfScarabs.java b/Mage.Sets/src/mage/cards/n/NestOfScarabs.java index 66c39c6f280..d4545e85df7 100644 --- a/Mage.Sets/src/mage/cards/n/NestOfScarabs.java +++ b/Mage.Sets/src/mage/cards/n/NestOfScarabs.java @@ -20,8 +20,10 @@ public final class NestOfScarabs extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}"); // Whenever you put one or more -1/-1 counters on a creature, create that many 1/1 black Insect creature tokens. - this.addAbility(new PutCounterOnCreatureTriggeredAbility(new CreateTokenEffect(new NestOfScarabsBlackInsectToken(), new EffectKeyValue("countersAdded")) - .setText("create that many 1/1 black Insect creature tokens"), CounterType.M1M1.createInstance())); + this.addAbility(new PutCounterOnCreatureTriggeredAbility( + new CreateTokenEffect(new NestOfScarabsBlackInsectToken(), + new EffectKeyValue("countersAdded", "that many")), + CounterType.M1M1.createInstance())); } private NestOfScarabs(final NestOfScarabs card) { diff --git a/Mage.Sets/src/mage/cards/n/NetherSpirit.java b/Mage.Sets/src/mage/cards/n/NetherSpirit.java index 4dcc774254c..77c06aec98b 100644 --- a/Mage.Sets/src/mage/cards/n/NetherSpirit.java +++ b/Mage.Sets/src/mage/cards/n/NetherSpirit.java @@ -33,7 +33,7 @@ public final class NetherSpirit extends CardImpl { // At the beginning of your upkeep, if Nether Spirit is the only creature card in your graveyard, you may return Nether Spirit to the battlefield. this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.GRAVEYARD, - TargetController.YOU, new ReturnSourceFromGraveyardToBattlefieldEffect().setText("return {this} to the battlefield"), + TargetController.YOU, new ReturnSourceFromGraveyardToBattlefieldEffect().setText("return this card to the battlefield"), true).withInterveningIf(NetherSpiritCondition.instance)); } @@ -60,6 +60,6 @@ enum NetherSpiritCondition implements Condition { @Override public String toString() { - return "{this} is the only creature card in your graveyard"; + return "this card is the only creature card in your graveyard"; } } diff --git a/Mage.Sets/src/mage/cards/n/NettlingImp.java b/Mage.Sets/src/mage/cards/n/NettlingImp.java index 4f7898080c5..2726cec45c9 100644 --- a/Mage.Sets/src/mage/cards/n/NettlingImp.java +++ b/Mage.Sets/src/mage/cards/n/NettlingImp.java @@ -1,14 +1,14 @@ package mage.cards.n; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.common.OpponentsTurnCondition; import mage.abilities.condition.common.TargetAttackedThisTurnCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.combat.AttacksIfAbleTargetEffect; @@ -19,24 +19,23 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.ControlledFromStartOfControllerTurnPredicate; import mage.game.Game; -import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; -import mage.watchers.common.AttackedThisTurnWatcher; + +import java.util.UUID; /** - * * @author MTGfan */ public final class NettlingImp extends CardImpl { - static final FilterCreaturePermanent filter = new FilterCreaturePermanent("non-Wall"); + static final FilterCreaturePermanent filter = new FilterCreaturePermanent("non-Wall creature the active player has controlled continuously since the beginning of the turn"); static { filter.add(Predicates.not(SubType.WALL.getPredicate())); filter.add(new ControlledFromStartOfControllerTurnPredicate()); filter.add(TargetController.ACTIVE.getControllerPredicate()); - filter.setMessage("non-Wall creature the active player has controlled continuously since the beginning of the turn."); } public NettlingImp(UUID ownerId, CardSetInfo setInfo) { @@ -47,13 +46,14 @@ public final class NettlingImp extends CardImpl { this.toughness = new MageInt(1); // {T}: Choose target non-Wall creature the active player has controlled continuously since the beginning of the turn. That creature attacks this turn if able. If it doesn't, destroy it at the beginning of the next end step. Activate this ability only during an opponent's turn, before attackers are declared. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new AttacksIfAbleTargetEffect(Duration.EndOfTurn), - new TapSourceCost(), new NettlingImpTurnCondition(), - "{T}: Choose target non-Wall creature the active player has controlled continuously since the beginning of the turn. " - + "That creature attacks this turn if able. If it doesn't, destroy it at the beginning of the next end step. " - + "Activate only during an opponent's turn, before attackers are declared."); + Ability ability = new ActivateIfConditionActivatedAbility( + new AttacksIfAbleTargetEffect(Duration.EndOfTurn) + .setText("choose target non-Wall creature the active player has controlled " + + "continuously since the beginning of the turn. That creature attacks this turn if able"), + new TapSourceCost(), NettlingImpTurnCondition.instance + ); ability.addEffect(new NettlingImpDelayedDestroyEffect()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } @@ -68,17 +68,17 @@ public final class NettlingImp extends CardImpl { } } -class NettlingImpTurnCondition implements Condition { +enum NettlingImpTurnCondition implements Condition { + instance; @Override public boolean apply(Game game, Ability source) { - Player activePlayer = game.getPlayer(game.getActivePlayerId()); - return activePlayer != null && activePlayer.hasOpponent(source.getControllerId(), game) && game.getPhase().getStep().getType().getIndex() < 5; + return OpponentsTurnCondition.instance.apply(game, source) && !game.getTurn().isDeclareAttackersStepStarted(); } @Override public String toString() { - return ""; + return "during an opponent's turn, before attackers are declared"; } } @@ -86,7 +86,7 @@ class NettlingImpDelayedDestroyEffect extends OneShotEffect { NettlingImpDelayedDestroyEffect() { super(Outcome.Detriment); - this.staticText = "If it doesn't, destroy it at the beginning of the next end step"; + this.staticText = "Destroy it at the beginning of the next end step if it didn't attack this turn"; } private NettlingImpDelayedDestroyEffect(final NettlingImpDelayedDestroyEffect effect) { diff --git a/Mage.Sets/src/mage/cards/n/NeurokTransmuter.java b/Mage.Sets/src/mage/cards/n/NeurokTransmuter.java index 0e81a40e425..6d0df71f8d2 100644 --- a/Mage.Sets/src/mage/cards/n/NeurokTransmuter.java +++ b/Mage.Sets/src/mage/cards/n/NeurokTransmuter.java @@ -17,6 +17,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -47,7 +48,7 @@ public final class NeurokTransmuter extends CardImpl { Effect blueEffect = new BecomesColorTargetEffect(ObjectColor.BLUE, Duration.EndOfTurn); blueEffect.setText("Until end of turn, target artifact creature becomes blue"); Ability becomeBlueAbility = new SimpleActivatedAbility(blueEffect, new ManaCostsImpl<>("{U}")); - becomeBlueAbility.addTarget(new TargetCreaturePermanent(filter)); + becomeBlueAbility.addTarget(new TargetPermanent(filter)); Effect loseArtifactEffect = new LoseArtifactTypeTargetEffect(Duration.EndOfTurn); loseArtifactEffect.setText("and isn't an artifact"); becomeBlueAbility.addEffect(loseArtifactEffect); diff --git a/Mage.Sets/src/mage/cards/n/NeyaliSunsVanguard.java b/Mage.Sets/src/mage/cards/n/NeyaliSunsVanguard.java index 6955a000629..10e73a88ab8 100644 --- a/Mage.Sets/src/mage/cards/n/NeyaliSunsVanguard.java +++ b/Mage.Sets/src/mage/cards/n/NeyaliSunsVanguard.java @@ -2,7 +2,7 @@ package mage.cards.n; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; @@ -12,11 +12,10 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.permanent.AttackingPredicate; import mage.filter.predicate.permanent.TokenPredicate; -import mage.game.Controllable; import mage.game.Game; -import mage.game.events.DefenderAttackedEvent; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.permanent.PermanentToken; @@ -33,11 +32,13 @@ import java.util.UUID; */ public final class NeyaliSunsVanguard extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("attacking tokens"); + private static final FilterPermanent filterAttacking = new FilterPermanent("attacking tokens"); + private static final FilterPermanent filterControlled = new FilterControlledPermanent("tokens you control"); static { - filter.add(AttackingPredicate.instance); - filter.add(TokenPredicate.TRUE); + filterAttacking.add(AttackingPredicate.instance); + filterAttacking.add(TokenPredicate.TRUE); + filterControlled.add(TokenPredicate.TRUE); } public NeyaliSunsVanguard(UUID ownerId, CardSetInfo setInfo) { @@ -51,11 +52,13 @@ public final class NeyaliSunsVanguard extends CardImpl { // Attacking tokens you control have double strike. this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect( - DoubleStrikeAbility.getInstance(), Duration.WhileOnBattlefield, filter + DoubleStrikeAbility.getInstance(), Duration.WhileOnBattlefield, filterAttacking ))); // Whenever one or more tokens you control attack a player, exile the top card of your library. During any turn you attacked with a token, you may play that card. - this.addAbility(new NeyaliSunsVanguardTriggeredAbility()); + Ability ability = new AttacksPlayerWithCreaturesTriggeredAbility(new NeyaliSunsVanguardEffect(), filterControlled, SetTargetPointer.NONE); + ability.addWatcher(new NeyaliSunsVanguardWatcher()); + this.addAbility(ability); } private NeyaliSunsVanguard(final NeyaliSunsVanguard card) { @@ -68,49 +71,11 @@ public final class NeyaliSunsVanguard extends CardImpl { } } -class NeyaliSunsVanguardTriggeredAbility extends TriggeredAbilityImpl { - - NeyaliSunsVanguardTriggeredAbility() { - super(Zone.BATTLEFIELD, new NeyaliSunsVanguardEffect()); - this.addWatcher(new NeyaliSunsVanguardWatcher()); - } - - private NeyaliSunsVanguardTriggeredAbility(final NeyaliSunsVanguardTriggeredAbility ability) { - super(ability); - } - - @Override - public NeyaliSunsVanguardTriggeredAbility copy() { - return new NeyaliSunsVanguardTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DEFENDER_ATTACKED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return game.getPlayer(event.getTargetId()) != null - && ((DefenderAttackedEvent) event) - .getAttackers(game) - .stream() - .filter(PermanentToken.class::isInstance) - .map(Controllable::getControllerId) - .anyMatch(this::isControlledBy); - } - - @Override - public String getRule() { - return "Whenever one or more tokens you control attack a player, exile the top card of your library. " + - "During any turn you attacked with a token, you may play that card."; - } -} - class NeyaliSunsVanguardEffect extends OneShotEffect { NeyaliSunsVanguardEffect() { super(Outcome.Benefit); + this.setText("exile the top card of your library. During any turn you attacked with a token, you may play that card."); } private NeyaliSunsVanguardEffect(final NeyaliSunsVanguardEffect effect) { diff --git a/Mage.Sets/src/mage/cards/n/NeyamShaiMurad.java b/Mage.Sets/src/mage/cards/n/NeyamShaiMurad.java index f66a570ca28..94a351ee75a 100644 --- a/Mage.Sets/src/mage/cards/n/NeyamShaiMurad.java +++ b/Mage.Sets/src/mage/cards/n/NeyamShaiMurad.java @@ -7,11 +7,15 @@ import mage.abilities.effects.OneShotEffect; 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.FilterCard; +import mage.filter.common.FilterPermanentCard; +import mage.filter.predicate.card.OwnerIdPredicate; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInGraveyard; +import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster; import java.util.UUID; @@ -21,6 +25,8 @@ import java.util.UUID; */ public final class NeyamShaiMurad extends CardImpl { + private static final FilterCard filter = new FilterPermanentCard("permanent card from their graveyard"); + public NeyamShaiMurad(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{B}"); @@ -32,10 +38,11 @@ public final class NeyamShaiMurad extends CardImpl { // Rogue Trader -- Whenever Neyam Shai Murad deals combat damage to a player, you may have that player return target permanent card from their graveyard to their hand. // If you do, that player chooses a permanent card in your graveyard, then you put it onto the battlefield under your control. - - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new NeyamShaiMuradEffect(), true, true) - .withFlavorWord("Rogue Trader") - ); //TODO: The first should target when triggered, not on resolution + Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new NeyamShaiMuradEffect(), true, true) + .withFlavorWord("Rogue Trader"); + ability.addTarget(new TargetCardInGraveyard(filter)); + ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster(true)); + this.addAbility(ability); } private NeyamShaiMurad(final NeyamShaiMurad card) { @@ -67,28 +74,26 @@ class NeyamShaiMuradEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); + Object playerId = getValue("damagedPlayer"); Player controller = game.getPlayer(source.getControllerId()); - Cards playerGraveyard = player.getGraveyard(); + if (controller == null || !(playerId instanceof UUID)) { + return false; + } + + Player player = game.getPlayer((UUID) playerId); + Cards cards = new CardsImpl(getTargetPointer().getTargets(game, source)); + cards.retainZone(Zone.GRAVEYARD, game); //verify the target card is still in the graveyard + if (player == null || cards.isEmpty() || !player.moveCards(cards, Zone.HAND, source, game)) { + return false; + } + Cards controllerGraveyard = controller.getGraveyard(); - if (player == null || controller == null || playerGraveyard.isEmpty()) { + FilterCard filter = new FilterPermanentCard("a permanent card in your graveyard"); + filter.add(new OwnerIdPredicate(source.getControllerId())); + TargetCardInGraveyard target = new TargetCardInGraveyard(1, 1, filter, true); + if (!target.choose(Outcome.PutCreatureInPlay, player.getId(), source, game)) { return false; } - - TargetCardInGraveyard target = new TargetCardInGraveyard(StaticFilters.FILTER_CARD_PERMANENT); - - if (!controller.chooseTarget(Outcome.ReturnToHand, playerGraveyard, target, source, game) - || !playerGraveyard.contains(target.getFirstTarget()) - || !player.moveCards(playerGraveyard.get(target.getFirstTarget(), game), Zone.HAND, source, game)) { - return false; - } - - target.clearChosen(); - target.withNotTarget(true); - if (!player.choose(Outcome.PutCreatureInPlay, controllerGraveyard, target, source, game)) { - return false; - } - return controllerGraveyard.contains(target.getFirstTarget()) && controller.moveCards(controllerGraveyard.get(target.getFirstTarget(), game), Zone.BATTLEFIELD, source, game); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/n/NiblisOfFrost.java b/Mage.Sets/src/mage/cards/n/NiblisOfFrost.java index 37f28345f74..ab718b6eb53 100644 --- a/Mage.Sets/src/mage/cards/n/NiblisOfFrost.java +++ b/Mage.Sets/src/mage/cards/n/NiblisOfFrost.java @@ -12,10 +12,13 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * @author fireshoes */ @@ -35,7 +38,7 @@ public final class NiblisOfFrost extends CardImpl { // Whenever you cast an instant or sorcery spell, tap target creature an opponent controls. That creature doesn't untap during its controller's next untap step. Ability ability = new SpellCastControllerTriggeredAbility(new TapTargetEffect(), StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); ability.addEffect(new DontUntapInControllersNextUntapStepTargetEffect("That creature")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/n/NightpackAmbusher.java b/Mage.Sets/src/mage/cards/n/NightpackAmbusher.java index 0287715e60d..2bbf4a83e84 100644 --- a/Mage.Sets/src/mage/cards/n/NightpackAmbusher.java +++ b/Mage.Sets/src/mage/cards/n/NightpackAmbusher.java @@ -2,13 +2,12 @@ package mage.cards.n; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.keyword.FlashAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -53,12 +52,8 @@ public final class NightpackAmbusher extends CardImpl { ))); // At the beginning of your end step, if you didn't cast a spell this turn, create a 2/2 green Wolf creature token. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - new CreateTokenEffect(new WolfToken()) - ), NightpackAmbusherCondition.instance, "At the beginning of your end step, " + - "if you didn't cast a spell this turn, create a 2/2 green Wolf creature token." - )); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new CreateTokenEffect(new WolfToken())) + .withInterveningIf(NightpackAmbusherCondition.instance)); } private NightpackAmbusher(final NightpackAmbusher card) { @@ -79,4 +74,9 @@ enum NightpackAmbusherCondition implements Condition { CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); return watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(source.getControllerId()) == 0; } + + @Override + public String toString() { + return "you didn't cast a spell this turn"; + } } diff --git a/Mage.Sets/src/mage/cards/n/NightscapeBattlemage.java b/Mage.Sets/src/mage/cards/n/NightscapeBattlemage.java index 9015c8818c1..7cce905a035 100644 --- a/Mage.Sets/src/mage/cards/n/NightscapeBattlemage.java +++ b/Mage.Sets/src/mage/cards/n/NightscapeBattlemage.java @@ -1,11 +1,10 @@ package mage.cards.n; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.KickedCostCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.abilities.keyword.KickerAbility; @@ -14,18 +13,21 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetLandPermanent; -/** - * - * @author LoneFox +import java.util.UUID; +/** + * @author LoneFox */ public final class NightscapeBattlemage extends CardImpl { + private static final Condition condition = new KickedCostCondition("{2}{U}"); + private static final Condition condition2 = new KickedCostCondition("{2}{R}"); + public NightscapeBattlemage(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.ZOMBIE); this.subtype.add(SubType.WIZARD); this.power = new MageInt(2); @@ -35,16 +37,16 @@ public final class NightscapeBattlemage extends CardImpl { KickerAbility kickerAbility = new KickerAbility("{2}{U}"); kickerAbility.addKickerCost("{2}{R}"); this.addAbility(kickerAbility); + // When Nightscape Battlemage enters the battlefield, if it was kicked with its {2}{U} kicker, return up to two target nonblack creatures to their owners' hands. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), false); - ability.addTarget(new TargetCreaturePermanent(0, 2, StaticFilters.FILTER_PERMANENT_CREATURES_NON_BLACK, false)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new KickedCostCondition("{2}{U}"), - "When {this} enters, if it was kicked with its {2}{U} kicker, return up to two target nonblack creatures to their owners' hands.")); + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), false).withInterveningIf(condition); + ability.addTarget(new TargetPermanent(0, 2, StaticFilters.FILTER_PERMANENT_CREATURES_NON_BLACK)); + this.addAbility(ability); + // When Nightscape Battlemage enters the battlefield, if it was kicked with its {2}{R} kicker, destroy target land. - ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), false); + ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), false).withInterveningIf(condition2); ability.addTarget(new TargetLandPermanent()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new KickedCostCondition("{2}{R}"), - "When {this} enters, if it was kicked with its {2}{R} kicker, destroy target land.")); + this.addAbility(ability); } private NightscapeBattlemage(final NightscapeBattlemage card) { diff --git a/Mage.Sets/src/mage/cards/n/NightsquadCommando.java b/Mage.Sets/src/mage/cards/n/NightsquadCommando.java index 387cf95ce49..def1b83c2d2 100644 --- a/Mage.Sets/src/mage/cards/n/NightsquadCommando.java +++ b/Mage.Sets/src/mage/cards/n/NightsquadCommando.java @@ -3,7 +3,6 @@ package mage.cards.n; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.hint.common.RaidHint; import mage.cards.CardImpl; @@ -29,11 +28,8 @@ public final class NightsquadCommando extends CardImpl { this.toughness = new MageInt(3); // When Nightsquad Commando enters the battlefield, if you attacked this turn, create a 1/1 white Human Soldier creature token. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new HumanSoldierToken())), - RaidCondition.instance, "When {this} enters, " + - "if you attacked this turn, create a 1/1 white Human Soldier creature token." - ).addHint(RaidHint.instance), new PlayerAttackedWatcher()); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new HumanSoldierToken())) + .withInterveningIf(RaidCondition.instance).addHint(RaidHint.instance), new PlayerAttackedWatcher()); } private NightsquadCommando(final NightsquadCommando card) { diff --git a/Mage.Sets/src/mage/cards/n/NihilisticGlee.java b/Mage.Sets/src/mage/cards/n/NihilisticGlee.java index 8975f9cd2f5..05645305410 100644 --- a/Mage.Sets/src/mage/cards/n/NihilisticGlee.java +++ b/Mage.Sets/src/mage/cards/n/NihilisticGlee.java @@ -7,7 +7,7 @@ import mage.abilities.costs.common.DiscardCardCost; import mage.abilities.costs.common.PayLifeCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.LoseLifeTargetEffect; @@ -15,7 +15,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AbilityWord; import mage.constants.CardType; -import mage.constants.Zone; import mage.target.common.TargetOpponent; import java.util.UUID; @@ -39,15 +38,12 @@ public final class NihilisticGlee extends CardImpl { this.addAbility(ability); // Hellbent - {1}, Pay 2 life: Draw a card. Activate this ability only if you have no cards in hand. - ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, + ability = new ActivateIfConditionActivatedAbility( new DrawCardSourceControllerEffect(1), - new GenericManaCost(1), - HellbentCondition.instance + new GenericManaCost(1), HellbentCondition.instance ); ability.addCost(new PayLifeCost(2)); - ability.setAbilityWord(AbilityWord.HELLBENT); - this.addAbility(ability); + this.addAbility(ability.setAbilityWord(AbilityWord.HELLBENT)); } private NihilisticGlee(final NihilisticGlee card) { diff --git a/Mage.Sets/src/mage/cards/n/Nihilith.java b/Mage.Sets/src/mage/cards/n/Nihilith.java index e612be96fd2..144dfcff9d9 100644 --- a/Mage.Sets/src/mage/cards/n/Nihilith.java +++ b/Mage.Sets/src/mage/cards/n/Nihilith.java @@ -1,51 +1,42 @@ - package mage.cards.n; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.PutCardIntoGraveFromAnywhereAllTriggeredAbility; import mage.abilities.condition.common.SuspendedCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; import mage.abilities.keyword.FearAbility; import mage.abilities.keyword.SuspendAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.SetTargetPointer; -import mage.constants.TargetController; -import mage.constants.Zone; +import mage.constants.*; import mage.counters.CounterType; -import mage.filter.FilterCard; +import mage.filter.StaticFilters; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class Nihilith extends CardImpl { public Nihilith(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}{B}"); this.subtype.add(SubType.HORROR); this.power = new MageInt(4); this.toughness = new MageInt(4); // Fear this.addAbility(FearAbility.getInstance()); - + // Suspend 7-{1}{B} this.addAbility(new SuspendAbility(7, new ManaCostsImpl<>("{1}{B}"), this, false)); - + // Whenever a card is put into an opponent's graveyard from anywhere, if Nihilith is suspended, you may remove a time counter from Nihilith. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new PutCardIntoGraveFromAnywhereAllTriggeredAbility(Zone.EXILED, new RemoveCounterSourceEffect(CounterType.TIME.createInstance()), true, - new FilterCard(), TargetController.OPPONENT, SetTargetPointer.NONE), - SuspendedCondition.instance, - "Whenever a card is put into an opponent's graveyard from anywhere, if {this} is suspended, you may remove a time counter from {this}." - )); - + this.addAbility(new PutCardIntoGraveFromAnywhereAllTriggeredAbility( + Zone.EXILED, new RemoveCounterSourceEffect(CounterType.TIME.createInstance()).setText("remove a time counter from this card"), true, + StaticFilters.FILTER_CARD_A, TargetController.OPPONENT, SetTargetPointer.NONE + ).withInterveningIf(SuspendedCondition.instance)); } private Nihilith(final Nihilith card) { diff --git a/Mage.Sets/src/mage/cards/n/NikoLightOfHope.java b/Mage.Sets/src/mage/cards/n/NikoLightOfHope.java index 3422ccb86fc..654f6be857e 100644 --- a/Mage.Sets/src/mage/cards/n/NikoLightOfHope.java +++ b/Mage.Sets/src/mage/cards/n/NikoLightOfHope.java @@ -1,9 +1,7 @@ package mage.cards.n; -import java.util.UUID; - -import mage.abilities.Ability; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; @@ -14,9 +12,9 @@ import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect; import mage.cards.Card; -import mage.constants.*; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.*; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.Predicates; @@ -25,17 +23,18 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.ShardToken; import mage.players.Player; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.targetpointer.FixedTarget; import mage.util.functions.EmptyCopyApplier; +import java.util.UUID; + /** - * * @author Grath */ public final class NikoLightOfHope extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("nonlegendary creature you control"); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("nonlegendary creature you control"); static { filter.add(Predicates.not(SuperType.LEGENDARY.getPredicate())); @@ -43,7 +42,7 @@ public final class NikoLightOfHope extends CardImpl { public NikoLightOfHope(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{U}"); - + this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WIZARD); @@ -56,7 +55,7 @@ public final class NikoLightOfHope extends CardImpl { // {2}, {T}: Exile target nonlegendary creature you control. Shards you control become copies of it until the beginning of the next end step. Return it to the battlefield under its owner's control at the beginning of the next end step. Ability ability = new SimpleActivatedAbility(new NikoLightOfHopeEffect(), new GenericManaCost(2)); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetControlledCreaturePermanent(1, 1, filter, false)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } @@ -90,26 +89,27 @@ class NikoLightOfHopeEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getFirstTarget()); - if (permanent != null && controller != null) { - if (permanent.moveToExile(source.getSourceId(), "Niko, Light of Hope", source, game)) { - FilterPermanent filter = new FilterPermanent("shards"); - filter.add(SubType.SHARD.getPredicate()); - for (Permanent copyTo : game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game)) { - game.copyPermanent(Duration.UntilNextEndStep, permanent, copyTo.getId(), source, new EmptyCopyApplier()); - } - ExileZone exile = game.getExile().getExileZone(source.getSourceId()); - if (exile != null && !exile.isEmpty()) { - Card card = game.getCard(permanent.getId()); - if (card != null) { - Effect effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false); - effect.setTargetPointer(new FixedTarget(card.getId())); - game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source); - } - } - return true; - } + if (permanent == null || controller == null + || !permanent.moveToExile(source.getSourceId(), "Niko, Light of Hope", source, game)) { + return false; } - return false; + FilterPermanent filter = new FilterPermanent("shards"); + filter.add(SubType.SHARD.getPredicate()); + for (Permanent copyTo : game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game)) { + game.copyPermanent(Duration.UntilNextEndStep, permanent, copyTo.getId(), source, new EmptyCopyApplier()); + } + ExileZone exile = game.getExile().getExileZone(source.getSourceId()); + if (exile == null || exile.isEmpty()) { + return true; + } + Card card = game.getCard(permanent.getId()); + if (card == null) { + return true; + } + Effect effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(false, false); + effect.setTargetPointer(new FixedTarget(card.getId())); + game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect), source); + return true; } } diff --git a/Mage.Sets/src/mage/cards/n/NimDevourer.java b/Mage.Sets/src/mage/cards/n/NimDevourer.java index 62146fa374c..4f014a147dc 100644 --- a/Mage.Sets/src/mage/cards/n/NimDevourer.java +++ b/Mage.Sets/src/mage/cards/n/NimDevourer.java @@ -5,7 +5,7 @@ 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.common.ActivateIfConditionActivatedAbility; import mage.abilities.dynamicvalue.common.ArtifactYouControlCount; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect; @@ -14,7 +14,10 @@ import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.hint.common.ArtifactYouControlHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; import mage.filter.StaticFilters; import java.util.UUID; @@ -37,10 +40,9 @@ public final class NimDevourer extends CardImpl { ); // {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(false, false), - new ManaCostsImpl<>("{B}{B}"), - new IsStepCondition(PhaseStep.UPKEEP), null); + Ability ability = new ActivateIfConditionActivatedAbility( + Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldEffect(false, false), + new ManaCostsImpl<>("{B}{B}"), IsStepCondition.getMyUpkeep()); ability.addEffect(new SacrificeControllerEffect(StaticFilters.FILTER_PERMANENT_A_CREATURE, 1, ", then")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/n/NimbleTrapfinder.java b/Mage.Sets/src/mage/cards/n/NimbleTrapfinder.java index 99ac134be42..c9c4a5ecf94 100644 --- a/Mage.Sets/src/mage/cards/n/NimbleTrapfinder.java +++ b/Mage.Sets/src/mage/cards/n/NimbleTrapfinder.java @@ -3,12 +3,10 @@ package mage.cards.n; import mage.MageInt; import mage.MageObjectReference; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.FullPartyCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.decorator.ConditionalRestrictionEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.combat.CantBeBlockedSourceEffect; @@ -16,9 +14,13 @@ import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.abilities.hint.ConditionHint; import mage.abilities.hint.Hint; import mage.abilities.hint.common.PartyCountHint; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.WatcherScope; import mage.filter.FilterPermanent; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; @@ -51,15 +53,13 @@ public final class NimbleTrapfinder extends CardImpl { )).addHint(NimbleTrapfinderCondition.getHint()), new NimbleTrapfinderWatcher()); // At the beginning of combat on your turn, if you have a full party, creatures you control gain "Whenever this creature deals combat damage to a player, draw a card" until end of turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility( - new GainAbilityAllEffect(new DealsCombatDamageToAPlayerTriggeredAbility( - new DrawCardSourceControllerEffect(1), false - ), Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURES) - ), FullPartyCondition.instance, "At the beginning of combat on your turn, " + - "if you have a full party, creatures you control gain " + - "\"Whenever this creature deals combat damage to a player, draw a card\" until end of turn." - ).addHint(PartyCountHint.instance)); + this.addAbility(new BeginningOfCombatTriggeredAbility(new GainAbilityAllEffect( + new DealsCombatDamageToAPlayerTriggeredAbility( + new DrawCardSourceControllerEffect(1), false + ), Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURES + ).setText("creatures you control gain \"Whenever this creature " + + "deals combat damage to a player, draw a card\" until end of turn")) + .withInterveningIf(FullPartyCondition.instance).addHint(PartyCountHint.instance)); } private NimbleTrapfinder(final NimbleTrapfinder card) { diff --git a/Mage.Sets/src/mage/cards/n/NineLivesFamiliar.java b/Mage.Sets/src/mage/cards/n/NineLivesFamiliar.java index 0fcd7ecfcdc..c6502d09e93 100644 --- a/Mage.Sets/src/mage/cards/n/NineLivesFamiliar.java +++ b/Mage.Sets/src/mage/cards/n/NineLivesFamiliar.java @@ -7,7 +7,6 @@ import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.CastFromEverywhereSourceCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldWithCounterEffect; @@ -20,18 +19,18 @@ import mage.constants.SubType; import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.util.CardUtil; import java.util.UUID; /** - * * @author ciaconna007 */ public final class NineLivesFamiliar extends CardImpl { public NineLivesFamiliar(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}{B}"); - + this.subtype.add(SubType.CAT); this.power = new MageInt(1); this.toughness = new MageInt(1); @@ -44,15 +43,10 @@ public final class NineLivesFamiliar extends CardImpl { )); // When this creature dies, if it had a revival counter on it, return it to the battlefield with one fewer revival counter on it at the beginning of the next end step. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new DiesSourceTriggeredAbility(new CreateDelayedTriggeredAbilityEffect( - new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new NineLivesFamiliarEffect()) - )), - NineLivesFamiliarCondition.instance, - "When this creature dies, if it had a revival counter on it, " - + "return it to the battlefield with one fewer revival counter on it " - + "at the beginning of the next end step." - )); + this.addAbility(new DiesSourceTriggeredAbility(new CreateDelayedTriggeredAbilityEffect( + new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new NineLivesFamiliarEffect()) + ).setText("return it to the battlefield with one fewer revival counter " + + "on it at the beginning of the next end step")).withInterveningIf(NineLivesFamiliarCondition.instance)); } private NineLivesFamiliar(final NineLivesFamiliar card) { @@ -70,8 +64,15 @@ enum NineLivesFamiliarCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = (Permanent) source.getEffects().get(0).getValue("permanentLeftBattlefield"); - return permanent != null && permanent.getCounters(game).getCount(CounterType.REVIVAL) > 0; + return CardUtil + .getEffectValueFromAbility(source, "permanentLeftBattlefield", Permanent.class) + .filter(permanent -> permanent.getCounters(game).getCount(CounterType.REVIVAL) > 0) + .isPresent(); + } + + @Override + public String toString() { + return "it had a revival counter on it"; } } diff --git a/Mage.Sets/src/mage/cards/n/NissaVastwoodSeer.java b/Mage.Sets/src/mage/cards/n/NissaVastwoodSeer.java index dc7261ef512..14fac45f978 100644 --- a/Mage.Sets/src/mage/cards/n/NissaVastwoodSeer.java +++ b/Mage.Sets/src/mage/cards/n/NissaVastwoodSeer.java @@ -1,13 +1,10 @@ - package mage.cards.n; -import java.util.UUID; import mage.MageInt; -import mage.constants.Pronoun; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.LandfallAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ExileAndReturnSourceEffect; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; import mage.abilities.keyword.TransformAbility; @@ -18,20 +15,27 @@ import mage.filter.FilterCard; import mage.filter.common.FilterLandPermanent; import mage.target.common.TargetCardInLibrary; +import java.util.UUID; + /** - * * @author emerald000 */ public final class NissaVastwoodSeer extends CardImpl { - + private static final FilterCard filter = new FilterCard("basic Forest card"); + static { filter.add(SuperType.BASIC.getPredicate()); filter.add(SubType.FOREST.getPredicate()); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterLandPermanent("you control seven or more lands"), + ComparisonType.MORE_THAN, 6, true + ); + public NissaVastwoodSeer(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.ELF); this.subtype.add(SubType.SCOUT); @@ -41,14 +45,15 @@ public final class NissaVastwoodSeer extends CardImpl { this.secondSideCardClazz = mage.cards.n.NissaSageAnimist.class; // When Nissa, Vastwood Seer enters the battlefield, you may search your library for a basic Forest card, reveal it, put it into your hand, then shuffle your library. - this.addAbility(new EntersBattlefieldTriggeredAbility(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter), true), true)); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter), true), true + )); // Whenever a land you control enters, if you control seven or more lands, exile Nissa, then return her to the battlefield transformed under her owner's control. this.addAbility(new TransformAbility()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldControlledTriggeredAbility(new ExileAndReturnSourceEffect(PutCards.BATTLEFIELD_TRANSFORMED,Pronoun.SHE), new FilterLandPermanent()), - new PermanentsOnTheBattlefieldCondition(new FilterLandPermanent(), ComparisonType.MORE_THAN, 6, true), - "Whenever a land you control enters, if you control seven or more lands, exile {this}, then return her to the battlefield transformed under her owner's control.")); + this.addAbility(new LandfallAbility(new ExileAndReturnSourceEffect( + PutCards.BATTLEFIELD_TRANSFORMED, Pronoun.SHE + )).withInterveningIf(condition).setAbilityWord(null)); } private NissaVastwoodSeer(final NissaVastwoodSeer card) { diff --git a/Mage.Sets/src/mage/cards/n/NissasJudgment.java b/Mage.Sets/src/mage/cards/n/NissasJudgment.java index 55e9a5bbf26..288b4560ca5 100644 --- a/Mage.Sets/src/mage/cards/n/NissasJudgment.java +++ b/Mage.Sets/src/mage/cards/n/NissasJudgment.java @@ -1,6 +1,5 @@ package mage.cards.n; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; @@ -13,11 +12,12 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.common.TargetCreaturePermanent; +import mage.target.common.TargetOpponentsCreaturePermanent; import mage.target.targetpointer.SecondTargetPointer; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class NissasJudgment extends CardImpl { @@ -32,7 +32,7 @@ public final class NissasJudgment extends CardImpl { // Choose up to one target creature an opponent controls. Each creature you control with a +1/+1 counter on it deals damage equal to its power to that creature. effect = new NissasJudgmentEffect(); effect.setTargetPointer(new SecondTargetPointer()); // First target is used by Support - getSpellAbility().addTarget(new TargetCreaturePermanent(0, 1, StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE, false)); + getSpellAbility().addTarget(new TargetOpponentsCreaturePermanent(0, 1)); getSpellAbility().addEffect(effect); } diff --git a/Mage.Sets/src/mage/cards/n/NivMizzetVisionary.java b/Mage.Sets/src/mage/cards/n/NivMizzetVisionary.java index 226519cb674..05bda5060ee 100644 --- a/Mage.Sets/src/mage/cards/n/NivMizzetVisionary.java +++ b/Mage.Sets/src/mage/cards/n/NivMizzetVisionary.java @@ -1,21 +1,21 @@ package mage.cards.n; -import java.util.Objects; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.SourceDealsNoncombatDamageToOpponentTriggeredAbility; import mage.abilities.dynamicvalue.common.SavedDamageValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.continuous.MaximumHandSizeControllerEffect; -import mage.constants.*; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.game.Game; -import mage.game.events.DamagedPlayerEvent; -import mage.game.events.GameEvent; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; + +import java.util.UUID; /** * @@ -40,7 +40,7 @@ public final class NivMizzetVisionary extends CardImpl { this.addAbility(new SimpleStaticAbility(effect)); // Whenever a source you control deals noncombat damage to an opponent, you draw that many cards. - this.addAbility(new NivMizzetVisionaryAbility()); + this.addAbility(new SourceDealsNoncombatDamageToOpponentTriggeredAbility(new DrawCardSourceControllerEffect(SavedDamageValue.MANY, true))); } private NivMizzetVisionary(final NivMizzetVisionary card) { @@ -52,41 +52,3 @@ public final class NivMizzetVisionary extends CardImpl { return new NivMizzetVisionary(this); } } - -class NivMizzetVisionaryAbility extends TriggeredAbilityImpl { - - NivMizzetVisionaryAbility() { - super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(SavedDamageValue.MANY)); - } - - private NivMizzetVisionaryAbility(final NivMizzetVisionaryAbility ability) { - super(ability); - } - - @Override - public NivMizzetVisionaryAbility copy() { - return new NivMizzetVisionaryAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event; - if (damageEvent.isCombatDamage() - || !game.getOpponents(controllerId).contains(event.getTargetId()) - || !Objects.equals(controllerId, game.getControllerId(event.getSourceId()))) { - return false; - } - getAllEffects().setValue("damage", event.getAmount()); - return true; - } - - @Override - public String getRule() { - return "Whenever a source you control deals noncombat damage to an opponent, you draw that many cards."; - } -} diff --git a/Mage.Sets/src/mage/cards/n/NobleHeritage.java b/Mage.Sets/src/mage/cards/n/NobleHeritage.java index 34827c2dc04..39734f0f957 100644 --- a/Mage.Sets/src/mage/cards/n/NobleHeritage.java +++ b/Mage.Sets/src/mage/cards/n/NobleHeritage.java @@ -14,7 +14,6 @@ import mage.constants.*; import mage.counters.CounterType; import mage.filter.FilterPlayer; import mage.filter.StaticFilters; -import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.other.PlayerIdPredicate; import mage.game.Game; import mage.game.events.GameEvent; @@ -25,7 +24,7 @@ import mage.target.common.TargetControlledCreaturePermanent; import java.util.ArrayList; import java.util.List; -import java.util.Objects; +import java.util.Optional; import java.util.UUID; /** @@ -40,7 +39,8 @@ public final class NobleHeritage extends CardImpl { this.subtype.add(SubType.BACKGROUND); // Commander creatures you own have “When this creature enters the battlefield and at the beginning of your upkeep, each player may put two +1/+1 counters on a creature they control. For each opponent who does, you gain protection from that player until your next turn.” (You can’t be targeted, dealt damage, or enchanted by anything controlled by that player.) - this.addAbility(new SimpleStaticAbility(new GainAbilityAllEffect(new NobleHeritageTriggeredAbility(), Duration.WhileOnBattlefield, + this.addAbility(new SimpleStaticAbility(new GainAbilityAllEffect( + new NobleHeritageTriggeredAbility(), Duration.WhileOnBattlefield, StaticFilters.FILTER_CREATURES_OWNED_COMMANDER ))); } @@ -122,39 +122,44 @@ class NobleHeritageEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - List players = new ArrayList<>(); - List creatures = new ArrayList<>(); - for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { - Player player = game.getPlayer(playerId); - if (player != null) { - if (player.chooseUse(outcome, "Put two +1/+1 counters on a creature you control?", source, game)) { - Target target = new TargetControlledCreaturePermanent(new FilterControlledCreaturePermanent("a creature you control (to add two +1/+1 counters on it)")); - if (player.choose(outcome, target, source, game)) { - creatures.add(target.getFirstTarget()); - players.add(player.getId()); - } - - } - } - } - for (UUID creatureId : creatures) { - Permanent creature = game.getPermanent(creatureId); - if (creature != null) { - creature.addCounters(CounterType.P1P1.createInstance(2), creature.getControllerId(), source, game); - } - } - for (UUID playerId : players) { - if (!Objects.equals(playerId, source.getControllerId())) { - FilterPlayer filter = new FilterPlayer(); - filter.add(new PlayerIdPredicate(playerId)); - game.addEffect(new GainAbilityControllerEffect( - new ProtectionAbility(filter), Duration.UntilYourNextTurn - ), source); - } - } - return true; + if (controller == null) { + return false; } - return false; + List players = new ArrayList<>(); + List creatures = new ArrayList<>(); + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player == null || !player.chooseUse(outcome, "Put two +1/+1 counters on a creature you control?", source, game)) { + continue; + } + Target target = new TargetControlledCreaturePermanent(0, 1); + target.withNotTarget(true); + target.withChooseHint("to add counters to"); + player.choose(outcome, target, source, game); + Optional.ofNullable(target) + .map(Target::getFirstTarget) + .map(game::getPermanent) + .ifPresent(permanent -> { + creatures.add(permanent.getId()); + players.add(player.getId()); + }); + } + for (UUID creatureId : creatures) { + Permanent creature = game.getPermanent(creatureId); + if (creature != null) { + creature.addCounters(CounterType.P1P1.createInstance(2), creature.getControllerId(), source, game); + } + } + for (UUID playerId : players) { + if (source.isControlledBy(playerId)) { + continue; + } + FilterPlayer filter = new FilterPlayer(); + filter.add(new PlayerIdPredicate(playerId)); + game.addEffect(new GainAbilityControllerEffect( + new ProtectionAbility(filter), Duration.UntilYourNextTurn + ), source); + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/n/NoggleHedgeMage.java b/Mage.Sets/src/mage/cards/n/NoggleHedgeMage.java index 0a274af4c38..2abf9a9d54b 100644 --- a/Mage.Sets/src/mage/cards/n/NoggleHedgeMage.java +++ b/Mage.Sets/src/mage/cards/n/NoggleHedgeMage.java @@ -1,12 +1,10 @@ - package mage.cards.n; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.TapTargetEffect; import mage.cards.CardImpl; @@ -14,28 +12,26 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.SubType; -import mage.filter.FilterPermanent; -import mage.filter.common.FilterLandPermanent; +import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledPermanent; import mage.target.TargetPermanent; import mage.target.common.TargetPlayerOrPlaneswalker; +import java.util.UUID; + /** - * * @author jeffwadsworth - * */ public final class NoggleHedgeMage extends CardImpl { - private static final FilterLandPermanent filter = new FilterLandPermanent(); - private static final FilterLandPermanent filter2 = new FilterLandPermanent(); - - static { - filter.add(SubType.ISLAND.getPredicate()); - filter2.add(SubType.MOUNTAIN.getPredicate()); - } - - private static final String rule = "When {this} enters, if you control two or more Islands, you may tap two target permanents."; - private static final String rule2 = "When {this} enters, if you control two or more Mountains, you may have {this} deal 2 damage to target player or planeswalker."; + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPermanent(SubType.ISLAND, "you control two or more Islands"), + ComparisonType.MORE_THAN, 1 + ); + private static final Condition condition2 = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPermanent(SubType.MOUNTAIN, "you control two or more Mountains"), + ComparisonType.MORE_THAN, 1 + ); public NoggleHedgeMage(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U/R}"); @@ -46,14 +42,14 @@ public final class NoggleHedgeMage extends CardImpl { this.toughness = new MageInt(2); // When Noggle Hedge-Mage enters the battlefield, if you control two or more Islands, you may tap two target permanents. - Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new TapTargetEffect(), true), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1), rule); - ability.addTarget(new TargetPermanent(2, new FilterPermanent())); + Ability ability = new EntersBattlefieldTriggeredAbility(new TapTargetEffect(), true).withInterveningIf(condition); + ability.addTarget(new TargetPermanent(2, StaticFilters.FILTER_PERMANENTS)); this.addAbility(ability); // When Noggle Hedge-Mage enters the battlefield, if you control two or more Mountains, you may have Noggle Hedge-Mage deal 2 damage to target player. - Ability ability2 = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2), true), new PermanentsOnTheBattlefieldCondition(filter2, ComparisonType.MORE_THAN, 1), rule2); - ability2.addTarget(new TargetPlayerOrPlaneswalker()); - this.addAbility(ability2); + ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2), true).withInterveningIf(condition2); + ability.addTarget(new TargetPlayerOrPlaneswalker()); + this.addAbility(ability); } private NoggleHedgeMage(final NoggleHedgeMage card) { diff --git a/Mage.Sets/src/mage/cards/n/NogiDracoZealot.java b/Mage.Sets/src/mage/cards/n/NogiDracoZealot.java index 3c4d704ea80..226d1b4b1b5 100644 --- a/Mage.Sets/src/mage/cards/n/NogiDracoZealot.java +++ b/Mage.Sets/src/mage/cards/n/NogiDracoZealot.java @@ -1,12 +1,10 @@ package mage.cards.n; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; @@ -28,11 +26,10 @@ import java.util.UUID; */ public final class NogiDracoZealot extends CardImpl { - private static final FilterPermanent filter = new FilterControlledPermanent(); + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.DRAGON, "you control three or more Dragons"); private static final FilterCard filter2 = new FilterCard("Dragon spells"); static { - filter.add(SubType.DRAGON.getPredicate()); filter2.add(SubType.DRAGON.getPredicate()); } @@ -54,16 +51,12 @@ public final class NogiDracoZealot extends CardImpl { // Whenever Nogi, Draco-Zealot attacks, if you control three or more Dragons, until end // of turn, Nogi becomes a Dragon with base power and toughness 5/5 and gains flying. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new BecomesCreatureSourceEffect( - new CreatureToken(5, 5, "Dragon with base power and toughness 5/5 and gains flying") - .withSubType(SubType.DRAGON) - .withAbility(FlyingAbility.getInstance()), - CardType.CREATURE, Duration.EndOfTurn), false - ), condition, "Whenever {this} attacks, if you control three or more Dragons, until end of turn, " + - "{this} becomes a Dragon with base power and toughness 5/5 and gains flying" - ); - this.addAbility(ability.addHint(hint)); + this.addAbility(new AttacksTriggeredAbility(new BecomesCreatureSourceEffect( + new CreatureToken( + 5, 5, "Dragon with base power and toughness 5/5 and gains flying" + ).withSubType(SubType.DRAGON).withAbility(FlyingAbility.getInstance()), + CardType.CREATURE, Duration.EndOfTurn + ), false).withInterveningIf(condition).addHint(hint)); } private NogiDracoZealot(final NogiDracoZealot card) { diff --git a/Mage.Sets/src/mage/cards/n/NomadDecoy.java b/Mage.Sets/src/mage/cards/n/NomadDecoy.java index ae6c27590a6..dae84f6f8d9 100644 --- a/Mage.Sets/src/mage/cards/n/NomadDecoy.java +++ b/Mage.Sets/src/mage/cards/n/NomadDecoy.java @@ -2,11 +2,11 @@ package mage.cards.n; import mage.MageInt; import mage.abilities.Ability; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.ThresholdCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; import mage.abilities.effects.common.TapTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -37,7 +37,7 @@ public final class NomadDecoy extends CardImpl { this.addAbility(ability); // Threshold - {W}{W}, {T}: Tap two target creatures. Activate this ability only if seven or more cards are in your graveyard. - Ability thresholdAbility = new ConditionalActivatedAbility( + Ability thresholdAbility = new ActivateIfConditionActivatedAbility( new TapTargetEffect(), new ManaCostsImpl<>("{W}{W}"), ThresholdCondition.instance ); thresholdAbility.addCost(new TapSourceCost()); diff --git a/Mage.Sets/src/mage/cards/n/NomadStadium.java b/Mage.Sets/src/mage/cards/n/NomadStadium.java index 5bca3530f0a..67b7d234c84 100644 --- a/Mage.Sets/src/mage/cards/n/NomadStadium.java +++ b/Mage.Sets/src/mage/cards/n/NomadStadium.java @@ -5,7 +5,7 @@ import mage.abilities.condition.common.ThresholdCondition; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DamageControllerEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.mana.WhiteManaAbility; @@ -30,7 +30,7 @@ public final class NomadStadium extends CardImpl { this.addAbility(manaAbility); // Threshold - {W}, {tap}, Sacrifice Nomad Stadium: You gain 4 life. Activate this ability only if seven or more cards are in your graveyard. - Ability thresholdAbility = new ConditionalActivatedAbility( + Ability thresholdAbility = new ActivateIfConditionActivatedAbility( new GainLifeEffect(4), new ManaCostsImpl<>("{W}"), ThresholdCondition.instance ); thresholdAbility.addCost(new TapSourceCost()); diff --git a/Mage.Sets/src/mage/cards/n/NornsDecree.java b/Mage.Sets/src/mage/cards/n/NornsDecree.java index f3b013b4745..b41b1a3d6f8 100644 --- a/Mage.Sets/src/mage/cards/n/NornsDecree.java +++ b/Mage.Sets/src/mage/cards/n/NornsDecree.java @@ -1,37 +1,41 @@ package mage.cards.n; -import java.util.UUID; - +import mage.abilities.Ability; import mage.abilities.common.CombatDamageDealtToYouTriggeredAbility; import mage.abilities.common.PlayerAttacksTriggeredAbility; -import mage.abilities.condition.common.AttackedPlayersPoisonedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.effects.common.DrawCardTargetEffect; import mage.abilities.effects.common.counter.AddPoisonCounterTargetEffect; 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.combat.CombatGroup; + +import java.util.Objects; +import java.util.UUID; /** - * * @author alexander-novo */ public final class NornsDecree extends CardImpl { public NornsDecree(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[] { CardType.ENCHANTMENT }, "{2}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}"); // Whenever one or more creatures an opponent controls deal combat damage to you, that opponent gets a poison counter. - this.addAbility(new CombatDamageDealtToYouTriggeredAbility(Zone.BATTLEFIELD, + this.addAbility(new CombatDamageDealtToYouTriggeredAbility( + Zone.BATTLEFIELD, new AddPoisonCounterTargetEffect(1).setText("that opponent gets a poison counter"), - true, false)); + true, false + )); // Whenever a player attacks, if one or more players being attacked are poisoned, the attacking player draws a card. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new PlayerAttacksTriggeredAbility(new DrawCardTargetEffect(1), true), - AttackedPlayersPoisonedCondition.instance, - "Whenever a player attacks, if one or more players being attacked are poisoned, the attacking player draws a card.")); + this.addAbility(new PlayerAttacksTriggeredAbility( + new DrawCardTargetEffect(1).setText("the attacking player draws a card"), true + ).withInterveningIf(NornsDecreeCondition.instance)); } private NornsDecree(final NornsDecree card) { @@ -44,3 +48,25 @@ public final class NornsDecree extends CardImpl { } } + +enum NornsDecreeCondition implements Condition { + instance; + + @Override + public boolean apply(Game game, Ability source) { + return game.getCombat() + .getGroups() + .stream() + .map(CombatGroup::getDefenderId) + .filter(Objects::nonNull) + .distinct() + .map(game::getPlayer) + .filter(Objects::nonNull) + .anyMatch(player -> player.getCountersCount(CounterType.POISON) > 0); + } + + @Override + public String toString() { + return "one or more players being attacked are poisoned"; + } +} diff --git a/Mage.Sets/src/mage/cards/n/Norritt.java b/Mage.Sets/src/mage/cards/n/Norritt.java index 6d00e0954ba..c76919d7ec1 100644 --- a/Mage.Sets/src/mage/cards/n/Norritt.java +++ b/Mage.Sets/src/mage/cards/n/Norritt.java @@ -1,6 +1,5 @@ package mage.cards.n; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; import mage.abilities.Ability; @@ -10,7 +9,7 @@ import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.BeforeAttackersAreDeclaredCondition; import mage.abilities.condition.common.TargetAttackedThisTurnCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.UntapTargetEffect; @@ -23,11 +22,13 @@ import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.permanent.ControlledFromStartOfControllerTurnPredicate; import mage.game.Game; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author MTGfan & L_J */ public final class Norritt extends CardImpl { @@ -38,13 +39,12 @@ public final class Norritt extends CardImpl { filterBlue.add(new ColorPredicate(ObjectColor.BLUE)); } - private static final FilterCreaturePermanent filterCreature = new FilterCreaturePermanent("non-Wall creature"); + private static final FilterCreaturePermanent filterCreature = new FilterCreaturePermanent("non-Wall creature the active player has controlled continuously since the beginning of the turn"); static { filterCreature.add(Predicates.not(SubType.WALL.getPredicate())); filterCreature.add(new ControlledFromStartOfControllerTurnPredicate()); filterCreature.add(TargetController.ACTIVE.getControllerPredicate()); - filterCreature.setMessage("non-Wall creature the active player has controlled continuously since the beginning of the turn."); } public Norritt(UUID ownerId, CardSetInfo setInfo) { @@ -56,17 +56,18 @@ public final class Norritt extends CardImpl { // {T}: Untap target blue creature. Ability ability1 = new SimpleActivatedAbility(new UntapTargetEffect(), new TapSourceCost()); - ability1.addTarget(new TargetCreaturePermanent(filterBlue)); + ability1.addTarget(new TargetPermanent(filterBlue)); this.addAbility(ability1); // {T}: Choose target non-Wall creature the active player has controlled continuously since the beginning of the turn. That creature attacks this turn if able. If it doesn't, destroy it at the beginning of the next end step. Activate this ability only before attackers are declared. - Ability ability2 = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new AttacksIfAbleTargetEffect(Duration.EndOfTurn), - new TapSourceCost(), BeforeAttackersAreDeclaredCondition.instance, - "{T}: Choose target non-Wall creature the active player has controlled continuously since the beginning of the turn. " - + "That creature attacks this turn if able. Destroy it at the beginning of the next end step if it didn't attack this turn. " - + "Activate only before attackers are declared."); + Ability ability2 = new ActivateIfConditionActivatedAbility( + new AttacksIfAbleTargetEffect(Duration.EndOfTurn) + .setText("choose target non-Wall creature the active player has controlled continuously " + + "since the beginning of the turn. That creature attacks this turn if able"), + new TapSourceCost(), BeforeAttackersAreDeclaredCondition.instance + ); ability2.addEffect(new NorrittDelayedDestroyEffect()); - ability2.addTarget(new TargetCreaturePermanent(filterCreature)); + ability2.addTarget(new TargetPermanent(filterCreature)); this.addAbility(ability2); } @@ -85,7 +86,7 @@ class NorrittDelayedDestroyEffect extends OneShotEffect { NorrittDelayedDestroyEffect() { super(Outcome.Detriment); - this.staticText = "If it doesn't, destroy it at the beginning of the next end step"; + this.staticText = "Destroy it at the beginning of the next end step if it didn't attack this turn"; } private NorrittDelayedDestroyEffect(final NorrittDelayedDestroyEffect effect) { diff --git a/Mage.Sets/src/mage/cards/n/NorwoodPriestess.java b/Mage.Sets/src/mage/cards/n/NorwoodPriestess.java index 671936209f3..dcba5817404 100644 --- a/Mage.Sets/src/mage/cards/n/NorwoodPriestess.java +++ b/Mage.Sets/src/mage/cards/n/NorwoodPriestess.java @@ -1,7 +1,5 @@ - package mage.cards.n; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; import mage.abilities.common.ActivateIfConditionActivatedAbility; @@ -12,17 +10,18 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; +import mage.filter.FilterCard; import mage.filter.common.FilterCreatureCard; import mage.filter.predicate.mageobject.ColorPredicate; +import java.util.UUID; + /** - * * @author fireshoes */ public final class NorwoodPriestess extends CardImpl { - private static final FilterCreatureCard filter = new FilterCreatureCard("a green creature card"); + private static final FilterCard filter = new FilterCreatureCard("a green creature card"); static { filter.add(new ColorPredicate(ObjectColor.GREEN)); @@ -37,10 +36,8 @@ public final class NorwoodPriestess extends CardImpl { // {tap}: You may put a green creature card from your hand onto the battlefield. Activate this ability only during your turn, before attackers are declared. this.addAbility(new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new PutCardFromHandOntoBattlefieldEffect(filter), - new TapSourceCost(), - MyTurnBeforeAttackersDeclaredCondition.instance + new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance )); } diff --git a/Mage.Sets/src/mage/cards/n/NosyGoblin.java b/Mage.Sets/src/mage/cards/n/NosyGoblin.java index aef639a100d..5ff6ce49e53 100644 --- a/Mage.Sets/src/mage/cards/n/NosyGoblin.java +++ b/Mage.Sets/src/mage/cards/n/NosyGoblin.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.card.FaceDownPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,7 +39,7 @@ public final class NosyGoblin extends CardImpl { // {tap}, Sacrifice Nosy Goblin: Destroy target face-down creature. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/n/NotoriousAssassin.java b/Mage.Sets/src/mage/cards/n/NotoriousAssassin.java index 95def99ef00..88ec18e7f11 100644 --- a/Mage.Sets/src/mage/cards/n/NotoriousAssassin.java +++ b/Mage.Sets/src/mage/cards/n/NotoriousAssassin.java @@ -14,8 +14,11 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author LoneFox @@ -34,7 +37,7 @@ public final class NotoriousAssassin extends CardImpl { Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(true), new ManaCostsImpl<>("{2}{B}")); ability.addCost(new TapSourceCost()); ability.addCost(new DiscardCardCost()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + ability.addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/n/NoxiousDragon.java b/Mage.Sets/src/mage/cards/n/NoxiousDragon.java index 457d9dcdb89..f8ff2ac679d 100644 --- a/Mage.Sets/src/mage/cards/n/NoxiousDragon.java +++ b/Mage.Sets/src/mage/cards/n/NoxiousDragon.java @@ -14,6 +14,7 @@ import mage.constants.SubType; import mage.constants.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ManaValuePredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -39,7 +40,7 @@ public final class NoxiousDragon extends CardImpl { // When Noxious Dragon dies, you may destroy target creature with converted mana cost 3 or less. Ability ability = new DiesSourceTriggeredAbility(new DestroyTargetEffect(), true); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/n/NoxiousGearhulk.java b/Mage.Sets/src/mage/cards/n/NoxiousGearhulk.java index cfc81a62686..e4786a4964f 100644 --- a/Mage.Sets/src/mage/cards/n/NoxiousGearhulk.java +++ b/Mage.Sets/src/mage/cards/n/NoxiousGearhulk.java @@ -16,8 +16,11 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * * @author fireshoes @@ -35,7 +38,7 @@ public final class NoxiousGearhulk extends CardImpl { // When Noxious Gearhulk enters the battlefield, you may destroy another target creature. If a creature is destroyed this way, you gain life equal to its toughness. Ability ability = new EntersBattlefieldTriggeredAbility(new NoxiousGearhulkEffect()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/n/NukaNukeLauncher.java b/Mage.Sets/src/mage/cards/n/NukaNukeLauncher.java new file mode 100644 index 00000000000..61f42edf696 --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NukaNukeLauncher.java @@ -0,0 +1,116 @@ +package mage.cards.n; + +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.AttacksAttachedTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.continuous.BoostEquippedEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.keyword.EquipAbility; +import mage.abilities.keyword.IntimidateAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.stack.Spell; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class NukaNukeLauncher extends CardImpl { + + public NukaNukeLauncher(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); + + this.subtype.add(SubType.EQUIPMENT); + + // Equipped creature gets +3/+0 and has intimidate. + Ability ability = new SimpleStaticAbility(new BoostEquippedEffect(3, 0)); + ability.addEffect(new GainAbilityAttachedEffect( + IntimidateAbility.getInstance(), AttachmentType.EQUIPMENT + ).setText("and has intimidate")); + this.addAbility(ability); + + // Whenever equipped creature attacks, until the end of defending player's next turn, that player gets two rad counters whenever they cast a spell. + this.addAbility(new AttacksAttachedTriggeredAbility( + new CreateDelayedTriggeredAbilityEffect(new NukaNukeLauncherDelayedTriggeredAbility()), + AttachmentType.EQUIPMENT, false, SetTargetPointer.PLAYER + )); + + // Equip {3} + this.addAbility(new EquipAbility(3)); + } + + private NukaNukeLauncher(final NukaNukeLauncher card) { + super(card); + } + + @Override + public NukaNukeLauncher copy() { + return new NukaNukeLauncher(this); + } +} + +class NukaNukeLauncherDelayedTriggeredAbility extends DelayedTriggeredAbility { + + private UUID playerId = null; + + NukaNukeLauncherDelayedTriggeredAbility() { + super(new AddCountersTargetEffect(CounterType.RAD.createInstance(2)), Duration.Custom, false, false); + } + + private NukaNukeLauncherDelayedTriggeredAbility(final NukaNukeLauncherDelayedTriggeredAbility ability) { + super(ability); + } + + @Override + public NukaNukeLauncherDelayedTriggeredAbility copy() { + return new NukaNukeLauncherDelayedTriggeredAbility(this); + } + + @Override + public void init(Game game) { + super.init(game); + this.playerId = this + .getEffects() + .stream() + .map(Effect::getTargetPointer) + .map(targetPointer -> targetPointer.getFirst(game, this)) + .findAny() + .orElse(null); + } + + @Override + public boolean isInactive(Game game) { + if (playerId == null) { + return true; + } + if (game.isActivePlayer(playerId)) { + this.setDuration(Duration.EndOfTurn); + } + return super.isInactive(game); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.SPELL_CAST; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Spell spell = game.getSpell(event.getTargetId()); + return spell != null && spell.isControlledBy(playerId); + } + + @Override + public String getRule() { + return "Until the end of defending player's next turn, that player gets two rad counters whenever they cast a spell"; + } +} diff --git a/Mage.Sets/src/mage/cards/n/NullmageShepherd.java b/Mage.Sets/src/mage/cards/n/NullmageShepherd.java index 1918253be4c..e70d5b0d187 100644 --- a/Mage.Sets/src/mage/cards/n/NullmageShepherd.java +++ b/Mage.Sets/src/mage/cards/n/NullmageShepherd.java @@ -1,4 +1,3 @@ - package mage.cards.n; import mage.MageInt; @@ -10,28 +9,18 @@ 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.FilterControlledCreaturePermanent; -import mage.filter.predicate.permanent.TappedPredicate; import mage.target.TargetPermanent; -import mage.target.common.TargetControlledCreaturePermanent; import java.util.UUID; /** - * * @author Loki */ public final class NullmageShepherd extends CardImpl { - private static final FilterControlledCreaturePermanent filterCost = new FilterControlledCreaturePermanent("untapped creatures you control"); - static { - filterCost.add(TappedPredicate.UNTAPPED); - } - public NullmageShepherd(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.ELF); this.subtype.add(SubType.SHAMAN); @@ -39,7 +28,7 @@ public final class NullmageShepherd extends CardImpl { this.toughness = new MageInt(4); // Tap four untapped creatures you control: Destroy target artifact or enchantment. - Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new TapTargetCost(new TargetControlledCreaturePermanent(4, 4, filterCost, true))); + Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new TapTargetCost(4, StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURES)); ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/n/NullpriestOfOblivion.java b/Mage.Sets/src/mage/cards/n/NullpriestOfOblivion.java index 498c3ca4f47..1f7eb3d2dc0 100644 --- a/Mage.Sets/src/mage/cards/n/NullpriestOfOblivion.java +++ b/Mage.Sets/src/mage/cards/n/NullpriestOfOblivion.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.keyword.KickerAbility; import mage.abilities.keyword.LifelinkAbility; @@ -41,11 +40,8 @@ public final class NullpriestOfOblivion extends CardImpl { this.addAbility(LifelinkAbility.getInstance()); // When this creature enters the battlefield, if it was kicked, return target creature card from your graveyard to the battlefield. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect()), - KickedCondition.ONCE, "When this creature enters, if it was kicked, " + - "return target creature card from your graveyard to the battlefield." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect()) + .withInterveningIf(KickedCondition.ONCE); ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/o/OKagachiVengefulKami.java b/Mage.Sets/src/mage/cards/o/OKagachiVengefulKami.java index 403faf3ab60..8fb3f30b2c9 100644 --- a/Mage.Sets/src/mage/cards/o/OKagachiVengefulKami.java +++ b/Mage.Sets/src/mage/cards/o/OKagachiVengefulKami.java @@ -1,22 +1,26 @@ package mage.cards.o; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.Effect; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbility; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.keyword.FlyingAbility; 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.SuperType; +import mage.constants.WatcherScope; import mage.filter.FilterPermanent; import mage.filter.common.FilterNonlandPermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; -import mage.game.events.DamagedPlayerEvent; import mage.game.events.GameEvent; -import mage.players.Player; import mage.target.TargetPermanent; +import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster; +import mage.util.CardUtil; import mage.watchers.Watcher; import java.util.*; @@ -26,6 +30,8 @@ import java.util.*; */ public final class OKagachiVengefulKami extends CardImpl { + private static final FilterPermanent filter = new FilterNonlandPermanent("nonland permanent that player controls"); + public OKagachiVengefulKami(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{U}{B}{R}{G}"); @@ -42,7 +48,11 @@ public final class OKagachiVengefulKami extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // Whenever O-Kagachi, Vengeful Kami deals combat damage to a player, if that player attacked you during their last turn, exile target nonland permanent that player controls - this.addAbility(new OKagachiVengefulKamiTriggeredAbility()); + TriggeredAbility ability = new DealsCombatDamageToAPlayerTriggeredAbility(new ExileTargetEffect(), false, true); + ability.addTarget(new TargetPermanent(filter)); + ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster()); + ability.withInterveningIf(KagachiVengefulKamiCondition.instance); + this.addAbility(ability); } private OKagachiVengefulKami(final OKagachiVengefulKami card) { @@ -55,66 +65,25 @@ public final class OKagachiVengefulKami extends CardImpl { } } -class OKagachiVengefulKamiTriggeredAbility extends TriggeredAbilityImpl { - - OKagachiVengefulKamiTriggeredAbility() { - super(Zone.BATTLEFIELD, new ExileTargetEffect(), false); - this.addWatcher(new OKagachiVengefulKamiWatcher()); - } - - private OKagachiVengefulKamiTriggeredAbility(final OKagachiVengefulKamiTriggeredAbility ability) { - super(ability); - } +enum KagachiVengefulKamiCondition implements Condition { + instance; @Override - public OKagachiVengefulKamiTriggeredAbility copy() { - return new OKagachiVengefulKamiTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - Player player = game.getPlayer(event.getTargetId()); - if (player == null - || !((DamagedPlayerEvent) event).isCombatDamage() - || !event.getSourceId().equals(getSourceId())) { - return false; - } - this.getEffects().setValue("damagedPlayer", event.getTargetId()); - FilterPermanent filter = new FilterNonlandPermanent("nonland permanent controlled by " + player.getName()); - filter.add(new ControllerIdPredicate(event.getTargetId())); - this.getTargets().clear(); - this.addTarget(new TargetPermanent(filter)); - return true; - } - - @Override - public boolean checkInterveningIfClause(Game game) { + public boolean apply(Game game, Ability source) { OKagachiVengefulKamiWatcher watcher = game.getState().getWatcher(OKagachiVengefulKamiWatcher.class); if (watcher == null) { return false; } - UUID playerId = null; - for (Effect effect : this.getEffects()) { - Object obj = effect.getValue("damagedPlayer"); - if (obj instanceof UUID) { - playerId = (UUID) obj; - break; - } - } - return watcher.checkPlayer(getControllerId(), playerId); + return CardUtil.getEffectValueFromAbility(source, "damagedPlayer", UUID.class) + .filter(uuid -> watcher.checkPlayer(source.getControllerId(), uuid)) + .isPresent(); } @Override - public String getRule() { - return "Whenever {this} deals combat damage to a player, " + - "if that player attacked you during their last turn, " + - "exile target nonland permanent that player controls."; + public String toString() { + return "if that player attacked you during their last turn"; } + } class OKagachiVengefulKamiWatcher extends Watcher { diff --git a/Mage.Sets/src/mage/cards/o/ONaginata.java b/Mage.Sets/src/mage/cards/o/ONaginata.java index c34f02b7fd9..104488f9627 100644 --- a/Mage.Sets/src/mage/cards/o/ONaginata.java +++ b/Mage.Sets/src/mage/cards/o/ONaginata.java @@ -1,12 +1,8 @@ - package mage.cards.o; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.AttachableToRestrictedAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.keyword.EquipAbility; @@ -15,17 +11,15 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AttachmentType; 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.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; -import mage.target.Target; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class ONaginata extends CardImpl { @@ -37,24 +31,21 @@ public final class ONaginata extends CardImpl { } public ONaginata(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{1}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); this.subtype.add(SubType.EQUIPMENT); - Target target = new TargetControlledCreaturePermanent(1, 1, filter, false); // O-Naginata can be attached only to a creature with 3 or more power. - this.addAbility(new AttachableToRestrictedAbility(target)); + this.addAbility(new AttachableToRestrictedAbility(new TargetPermanent(filter))); // Equipped creature gets +3/+0 and has trample. - Effect effect = new BoostEquippedEffect(3, 0); - effect.setText("Equipped creature gets +3/+0"); - Ability ability = new SimpleStaticAbility(effect); - effect = new GainAbilityAttachedEffect(TrampleAbility.getInstance(), AttachmentType.EQUIPMENT); - effect.setText("and has trample"); - ability.addEffect(effect); + Ability ability = new SimpleStaticAbility(new BoostEquippedEffect(3, 0)); + ability.addEffect(new GainAbilityAttachedEffect( + TrampleAbility.getInstance(), AttachmentType.EQUIPMENT + ).setText("and has trample")); this.addAbility(ability); // Equip {2} - this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2), target)); + this.addAbility(new EquipAbility(2)); } private ONaginata(final ONaginata card) { diff --git a/Mage.Sets/src/mage/cards/o/OathOfChandra.java b/Mage.Sets/src/mage/cards/o/OathOfChandra.java index d4c77f71cef..d3cb3b769d9 100644 --- a/Mage.Sets/src/mage/cards/o/OathOfChandra.java +++ b/Mage.Sets/src/mage/cards/o/OathOfChandra.java @@ -1,18 +1,12 @@ - package mage.cards.o; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.StaticValue; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DamagePlayersEffect; import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -20,31 +14,36 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.watchers.Watcher; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** - * * @author LevelX2 */ public final class OathOfChandra extends CardImpl { public OathOfChandra(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}"); this.supertype.add(SuperType.LEGENDARY); // When Oath of Chandra enters the battlefield, it deals 3 damage to target creature an opponent controls. - Effect effect = new DamageTargetEffect(3); - effect.setText("it deals 3 damage to target creature an opponent controls"); - Ability ability = new EntersBattlefieldTriggeredAbility(effect, false); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(3, "it")); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); // At the beginning of each end step, if a planeswalker entered the battlefield under your control this turn, Oath of Chandra deals 2 damage to each opponent. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfEndStepTriggeredAbility( - TargetController.ANY, new DamagePlayersEffect(Outcome.Damage, StaticValue.get(2), TargetController.OPPONENT), - false), OathOfChandraCondition.instance, - "At the beginning of each end step, if a planeswalker entered the battlefield under your control this turn, {this} deals 2 damage to each opponent."), new OathOfChandraWatcher()); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.ANY, + new DamagePlayersEffect(Outcome.Damage, StaticValue.get(2), TargetController.OPPONENT), + false, OathOfChandraCondition.instance + ), new OathOfChandraWatcher()); } private OathOfChandra(final OathOfChandra card) { @@ -58,7 +57,6 @@ public final class OathOfChandra extends CardImpl { } enum OathOfChandraCondition implements Condition { - instance; @Override @@ -69,7 +67,7 @@ enum OathOfChandraCondition implements Condition { @Override public String toString() { - return "if a planeswalker entered the battlefield under your control this turn"; + return "a planeswalker entered the battlefield under your control this turn"; } } @@ -101,5 +99,4 @@ class OathOfChandraWatcher extends Watcher { public boolean enteredPlaneswalkerForPlayer(UUID playerId) { return players.contains(playerId); } - } diff --git a/Mage.Sets/src/mage/cards/o/OathOfLiliana.java b/Mage.Sets/src/mage/cards/o/OathOfLiliana.java index b47cf7e38c5..ceff40926e3 100644 --- a/Mage.Sets/src/mage/cards/o/OathOfLiliana.java +++ b/Mage.Sets/src/mage/cards/o/OathOfLiliana.java @@ -1,16 +1,11 @@ - package mage.cards.o; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.SacrificeOpponentsEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -21,6 +16,10 @@ import mage.game.events.ZoneChangeEvent; import mage.game.permanent.token.ZombieToken; import mage.watchers.Watcher; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + /** * @author fireshoes */ @@ -31,14 +30,15 @@ public final class OathOfLiliana extends CardImpl { this.supertype.add(SuperType.LEGENDARY); // When Oath of Liliana enters the battlefield, each opponent sacrifices a creature. - this.addAbility(new EntersBattlefieldTriggeredAbility(new SacrificeOpponentsEffect(StaticFilters.FILTER_PERMANENT_CREATURE), false)); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new SacrificeOpponentsEffect(StaticFilters.FILTER_PERMANENT_CREATURE) + )); // At the beginning of each end step, if a planeswalker entered the battlefield under your control this turn, create a 2/2 black Zombie creature token. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfEndStepTriggeredAbility( + this.addAbility(new BeginningOfEndStepTriggeredAbility( TargetController.ANY, new CreateTokenEffect(new ZombieToken()), - false), OathOfLilianaCondition.instance, - "At the beginning of each end step, if a planeswalker entered the battlefield under your control this turn, " - + "create a 2/2 black Zombie creature token."), new OathOfLilianaWatcher()); + false, OathOfLilianaCondition.instance + ), new OathOfLilianaWatcher()); } private OathOfLiliana(final OathOfLiliana card) { @@ -63,7 +63,7 @@ enum OathOfLilianaCondition implements Condition { @Override public String toString() { - return "if a planeswalker entered the battlefield under your control this turn"; + return "a planeswalker entered the battlefield under your control this turn"; } } @@ -95,6 +95,4 @@ class OathOfLilianaWatcher extends Watcher { public boolean enteredPlaneswalkerForPlayer(UUID playerId) { return players.contains(playerId); } - - } diff --git a/Mage.Sets/src/mage/cards/o/ObscuraAscendancy.java b/Mage.Sets/src/mage/cards/o/ObscuraAscendancy.java index de99ac113b5..5593e56ebc0 100644 --- a/Mage.Sets/src/mage/cards/o/ObscuraAscendancy.java +++ b/Mage.Sets/src/mage/cards/o/ObscuraAscendancy.java @@ -1,15 +1,11 @@ package mage.cards.o; -import java.util.UUID; - import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.Effects; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -24,9 +20,11 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.Spirit22Token; import mage.game.stack.Spell; +import mage.util.CardUtil; + +import java.util.UUID; /** - * * @author weirddan455 */ public final class ObscuraAscendancy extends CardImpl { @@ -37,11 +35,11 @@ public final class ObscuraAscendancy extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}{U}{B}"); // Whenever you cast a spell, if its mana value is equal to the number of soul counters on Obscura Ascendancy plus one, put a soul counter on Obscura Ascendancy, then create a 2/2 white Spirit creature token with flying. - SpellCastControllerTriggeredAbility triggeredAbility = new SpellCastControllerTriggeredAbility(new AddCountersSourceEffect(CounterType.SOUL.createInstance()), false); - triggeredAbility.addEffect(new CreateTokenEffect(new Spirit22Token())); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(triggeredAbility, ObscuraAscendancyCondition.instance, - "Whenever you cast a spell, if its mana value is equal to 1 plus the number of soul counters on {this}, put a soul counter on {this}, then create a 2/2 white Spirit creature token with flying." - )); + Ability ability = new SpellCastControllerTriggeredAbility( + new AddCountersSourceEffect(CounterType.SOUL.createInstance()), false + ).withInterveningIf(ObscuraAscendancyCondition.instance); + ability.addEffect(new CreateTokenEffect(new Spirit22Token()).concatBy(", then")); + this.addAbility(ability); // As long as Obscura Ascendancy has five or more soul counters on it, Spirits you control get +3/+3. this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect( @@ -67,15 +65,16 @@ enum ObscuraAscendancyCondition implements Condition { @Override public boolean apply(Game game, Ability source) { Permanent permanent = source.getSourcePermanentOrLKI(game); - if (permanent != null) { - Effects effects = source.getEffects(); - if (!effects.isEmpty()) { - Object spellCast = effects.get(0).getValue("spellCast"); - if (spellCast instanceof Spell) { - return ((Spell) spellCast).getManaValue() == permanent.getCounters(game).getCount(CounterType.SOUL) + 1; - } - } - } - return false; + return permanent != null + && CardUtil + .getEffectValueFromAbility(source, "spellCast", Spell.class) + .map(Spell::getManaValue) + .filter(x -> x == permanent.getCounters(game).getCount(CounterType.SOUL) + 1) + .isPresent(); + } + + @Override + public String toString() { + return "its mana value is equal to 1 plus the number of soul counters on {this}"; } } diff --git a/Mage.Sets/src/mage/cards/o/ObsessiveSkinner.java b/Mage.Sets/src/mage/cards/o/ObsessiveSkinner.java index 5d61c63a5d8..d469f876823 100644 --- a/Mage.Sets/src/mage/cards/o/ObsessiveSkinner.java +++ b/Mage.Sets/src/mage/cards/o/ObsessiveSkinner.java @@ -1,23 +1,23 @@ package mage.cards.o; -import java.util.UUID; - import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.DeliriumCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.TargetController; import mage.counters.CounterType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * @author fireshoes */ @@ -37,14 +37,11 @@ public final class ObsessiveSkinner extends CardImpl { // Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard, // put a +1/+1 counter on target creature. - ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(TargetController.OPPONENT, new AddCountersTargetEffect(CounterType.P1P1.createInstance()), false), - DeliriumCondition.instance, - "Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard, " - + "put a +1/+1 counter on target creature."); + ability = new BeginningOfUpkeepTriggeredAbility( + TargetController.OPPONENT, new AddCountersTargetEffect(CounterType.P1P1.createInstance()), false + ).withInterveningIf(DeliriumCondition.instance); ability.addTarget(new TargetCreaturePermanent()); - ability.addHint(CardTypesInGraveyardCount.YOU.getHint()); - this.addAbility(ability); + this.addAbility(ability.setAbilityWord(AbilityWord.DELIRIUM).addHint(CardTypesInGraveyardCount.YOU.getHint())); } private ObsessiveSkinner(final ObsessiveSkinner card) { diff --git a/Mage.Sets/src/mage/cards/o/OchreJelly.java b/Mage.Sets/src/mage/cards/o/OchreJelly.java index 36dd3fc0234..c14906a72d4 100644 --- a/Mage.Sets/src/mage/cards/o/OchreJelly.java +++ b/Mage.Sets/src/mage/cards/o/OchreJelly.java @@ -6,7 +6,6 @@ import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.CreateTokenCopyTargetEffect; @@ -43,14 +42,11 @@ public final class OchreJelly extends CardImpl { this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.P1P1.createInstance()))); // Split — When Ochre Jelly dies, if it had two or more +1/+1 counters on it, create a token that's a copy of it at the beginning of the next end step. That token enters the battlefield with half that many +1/+1 counters on it, rounded down. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new DiesSourceTriggeredAbility(new CreateDelayedTriggeredAbilityEffect( - new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new OchreJellyEffect()) - )), OchreJellyCondition.instance, CardUtil.italicizeWithEmDash("Split") - + "When {this} dies, if it had two or more +1/+1 counters on it, " - + "create a token that's a copy of it at the beginning of the next end step. " - + "The token enters the battlefield with half that many +1/+1 counters on it, rounded down." - )); + this.addAbility(new DiesSourceTriggeredAbility(new CreateDelayedTriggeredAbilityEffect( + new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new OchreJellyEffect()) + ).setText("create a token that's a copy of it at the beginning of the next end step. " + + "The token enters with half that many +1/+1 counters on it, rounded down")) + .withInterveningIf(OchreJellyCondition.instance).withFlavorWord("Split")); } private OchreJelly(final OchreJelly card) { @@ -68,8 +64,15 @@ enum OchreJellyCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = (Permanent) source.getEffects().get(0).getValue("permanentLeftBattlefield"); - return permanent != null && permanent.getCounters(game).getCount(CounterType.P1P1) >= 2; + return CardUtil + .getEffectValueFromAbility(source, "permanentLeftBattlefield", Permanent.class) + .filter(permanent -> permanent.getCounters(game).getCount(CounterType.P1P1) >= 2) + .isPresent(); + } + + @Override + public String toString() { + return "it had two or more +1/+1 counters on it"; } } @@ -95,10 +98,8 @@ class OchreJellyEffect extends OneShotEffect { if (permanent == null) { return false; } - final int counters = permanent.getCounters(game).getCount(CounterType.P1P1) / 2; - CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(CounterType.P1P1, counters); - effect.setSavedPermanent(permanent); - effect.apply(game, source); - return true; + return new CreateTokenCopyTargetEffect( + CounterType.P1P1, permanent.getCounters(game).getCount(CounterType.P1P1) / 2 + ).setSavedPermanent(permanent).apply(game, source); } } diff --git a/Mage.Sets/src/mage/cards/o/OctopusUmbra.java b/Mage.Sets/src/mage/cards/o/OctopusUmbra.java index 14dbf1bc87f..34b48a0d632 100644 --- a/Mage.Sets/src/mage/cards/o/OctopusUmbra.java +++ b/Mage.Sets/src/mage/cards/o/OctopusUmbra.java @@ -48,7 +48,7 @@ public final class OctopusUmbra extends CardImpl { // Enchanted creature has base power and toughness 8/8 and has "Whenever this creature attacks, you may tap target creature with power 8 or less." Ability abilityToAdd = new AttacksTriggeredAbility(new TapTargetEffect(), true); - abilityToAdd.addTarget(new TargetCreaturePermanent(filter)); + abilityToAdd.addTarget(new TargetPermanent(filter)); ability = new SimpleStaticAbility( new SetBasePowerToughnessAttachedEffect(8, 8, AttachmentType.AURA) ); diff --git a/Mage.Sets/src/mage/cards/o/OgreGatecrasher.java b/Mage.Sets/src/mage/cards/o/OgreGatecrasher.java index f9eeaafab69..326830ce6ce 100644 --- a/Mage.Sets/src/mage/cards/o/OgreGatecrasher.java +++ b/Mage.Sets/src/mage/cards/o/OgreGatecrasher.java @@ -13,6 +13,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -36,7 +37,7 @@ public final class OgreGatecrasher extends CardImpl { // When Ogre Gatecrasher enters the battlefield, destroy target creature with defender. Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), false); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/o/OgreSavant.java b/Mage.Sets/src/mage/cards/o/OgreSavant.java index c75a9a291c3..9ae30f39e26 100644 --- a/Mage.Sets/src/mage/cards/o/OgreSavant.java +++ b/Mage.Sets/src/mage/cards/o/OgreSavant.java @@ -1,38 +1,35 @@ - package mage.cards.o; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.ManaWasSpentCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.ColoredManaSymbol; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author FenrisulfrX */ public final class OgreSavant extends CardImpl { public OgreSavant(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}"); this.subtype.add(SubType.OGRE); this.subtype.add(SubType.WIZARD); this.power = new MageInt(3); this.toughness = new MageInt(2); //When Ogre Savant enters the battlefield, if {U} was spent to cast Ogre Savant, return target creature to its owner’s hand. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(),false); + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()) + .withInterveningIf(ManaWasSpentCondition.BLUE); ability.addTarget(new TargetCreaturePermanent()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, ManaWasSpentCondition.BLUE, - "When {this} enters, if {U} was spent to cast it, return target creature to its owner's hand.")); + this.addAbility(ability); } private OgreSavant(final OgreSavant card) { diff --git a/Mage.Sets/src/mage/cards/o/OhranYeti.java b/Mage.Sets/src/mage/cards/o/OhranYeti.java index 092a8f5f895..0155af89ca0 100644 --- a/Mage.Sets/src/mage/cards/o/OhranYeti.java +++ b/Mage.Sets/src/mage/cards/o/OhranYeti.java @@ -16,6 +16,7 @@ import mage.constants.Duration; import mage.constants.SuperType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class OhranYeti extends CardImpl { // {2}{S}: Target snow creature gains first strike until end of turn. Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect( FirstStrikeAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{2}{S}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/o/OkinaNightwatch.java b/Mage.Sets/src/mage/cards/o/OkinaNightwatch.java index 1657a2ac65b..b912963b205 100644 --- a/Mage.Sets/src/mage/cards/o/OkinaNightwatch.java +++ b/Mage.Sets/src/mage/cards/o/OkinaNightwatch.java @@ -33,7 +33,7 @@ public final class OkinaNightwatch extends CardImpl { Ability ability = new SimpleStaticAbility(new ConditionalContinuousEffect( new BoostSourceEffect(3,3, Duration.WhileOnBattlefield), MoreCardsInHandThanOpponentsCondition.instance, - "As long as you have more cards in hand than each opponent, Okina Nightwatch gets +3/+3")); + "As long as you have more cards in hand than each opponent, {this} gets +3/+3")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/o/OldGrowthTroll.java b/Mage.Sets/src/mage/cards/o/OldGrowthTroll.java index acf6b65c22b..b619622e09e 100644 --- a/Mage.Sets/src/mage/cards/o/OldGrowthTroll.java +++ b/Mage.Sets/src/mage/cards/o/OldGrowthTroll.java @@ -12,7 +12,6 @@ import mage.abilities.costs.Cost; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; @@ -53,13 +52,8 @@ public final class OldGrowthTroll extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // When Old-Growth Troll dies, if it was a creature, return it to the battlefield. It's an Aura enchantment with enchant Forest you control and "Enchanted Forest has '{T}: Add {G}{G}' and '{1}, {T}, Sacrifice this land: Create a 4/4 green Troll Warrior creature token with trample.'" - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new DiesSourceTriggeredAbility(new OldGrowthTrollReturnEffect()), - OldGrowthTrollCondition.instance, "When {this} dies, if it was a creature, " + - "return it to the battlefield. It's an Aura enchantment with enchant Forest you control " + - "and \"Enchanted Forest has '{T}: Add {G}{G}' and '{1}, {T}, Sacrifice this land: " + - "Create a tapped 4/4 green Troll Warrior creature token with trample.'\"" - )); + this.addAbility(new DiesSourceTriggeredAbility(new OldGrowthTrollReturnEffect()) + .withInterveningIf(OldGrowthTrollCondition.instance)); } private OldGrowthTroll(final OldGrowthTroll card) { @@ -77,8 +71,15 @@ enum OldGrowthTrollCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = (Permanent) source.getEffects().get(0).getValue("permanentLeftBattlefield"); - return permanent != null && permanent.isCreature(game); + return CardUtil + .getEffectValueFromAbility(source, "permanentLeftBattlefield", Permanent.class) + .filter(permanent -> permanent.isCreature(game)) + .isPresent(); + } + + @Override + public String toString() { + return "it was a creature"; } } @@ -88,6 +89,9 @@ class OldGrowthTrollReturnEffect extends OneShotEffect { OldGrowthTrollReturnEffect() { super(Outcome.PutCardInPlay); + staticText = "return it to the battlefield. It's an Aura enchantment with enchant Forest you control " + + "and \"Enchanted Forest has '{T}: Add {G}{G}' and '{1}, {T}, Sacrifice this land: " + + "Create a tapped 4/4 green Troll Warrior creature token with trample.'\""; } private OldGrowthTrollReturnEffect(final OldGrowthTrollReturnEffect effect) { diff --git a/Mage.Sets/src/mage/cards/o/OliviaVoldaren.java b/Mage.Sets/src/mage/cards/o/OliviaVoldaren.java index 2c7bda1aa80..4f357294898 100644 --- a/Mage.Sets/src/mage/cards/o/OliviaVoldaren.java +++ b/Mage.Sets/src/mage/cards/o/OliviaVoldaren.java @@ -19,6 +19,7 @@ import mage.constants.SuperType; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -52,7 +53,7 @@ public final class OliviaVoldaren extends CardImpl { .setText("{this} deals 1 damage to another target creature"), new ManaCostsImpl<>("{1}{R}") ); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); Effect effect = new AddCardSubTypeTargetEffect(SubType.VAMPIRE, Duration.WhileOnBattlefield); effect.setText("That creature becomes a Vampire in addition to its other types"); ability.addEffect(effect); @@ -63,7 +64,7 @@ public final class OliviaVoldaren extends CardImpl { Ability ability2 = new SimpleActivatedAbility( new GainControlTargetEffect(Duration.WhileControlled), new ManaCostsImpl<>("{3}{B}{B}") ); - ability2.addTarget(new TargetCreaturePermanent(vampireFilter)); + ability2.addTarget(new TargetPermanent(vampireFilter)); this.addAbility(ability2); } diff --git a/Mage.Sets/src/mage/cards/o/OliviasBloodsworn.java b/Mage.Sets/src/mage/cards/o/OliviasBloodsworn.java index a277949ac54..40dedcfb3fd 100644 --- a/Mage.Sets/src/mage/cards/o/OliviasBloodsworn.java +++ b/Mage.Sets/src/mage/cards/o/OliviasBloodsworn.java @@ -17,6 +17,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -46,7 +47,7 @@ public final class OliviasBloodsworn extends CardImpl { // {R}: Target Vampire gains haste until end of turn. Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{R}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/o/OlorinsSearingLight.java b/Mage.Sets/src/mage/cards/o/OlorinsSearingLight.java index a1b9cecdeba..e865251f5a0 100644 --- a/Mage.Sets/src/mage/cards/o/OlorinsSearingLight.java +++ b/Mage.Sets/src/mage/cards/o/OlorinsSearingLight.java @@ -14,12 +14,11 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.*; /** - * * @author notgreat */ public final class OlorinsSearingLight extends CardImpl { @@ -41,17 +40,20 @@ public final class OlorinsSearingLight extends CardImpl { return new OlorinsSearingLight(this); } } + //See Crackling Doom class OlorinsSearingLightEffect extends OneShotEffect { static FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature with the greatest power among creatures you control"); + static { filter.add(GreatestPowerControlledPredicate.instance); } + public OlorinsSearingLightEffect() { super(Outcome.Sacrifice); this.staticText = "Each opponent exiles a creature with the greatest power among creatures that player controls.
" - +"Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, {this} deals damage to each opponent equal to the power of the creature they exiled."; + + "Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, {this} deals damage to each opponent equal to the power of the creature they exiled."; } private OlorinsSearingLightEffect(final OlorinsSearingLightEffect effect) { @@ -72,7 +74,7 @@ class OlorinsSearingLightEffect extends OneShotEffect { if (controller.hasOpponent(playerId, game)) { Player opponent = game.getPlayer(playerId); if (opponent != null) { - Target target = new TargetControlledCreaturePermanent(filter); + Target target = new TargetPermanent(filter); target.withNotTarget(true); if (opponent.choose(outcome, target, source, game)) { Permanent permanentChosen = game.getPermanent(target.getFirstTarget()); @@ -91,7 +93,7 @@ class OlorinsSearingLightEffect extends OneShotEffect { opponent.moveCards(permanent, Zone.EXILED, source, game); } } - if (SpellMasteryCondition.instance.apply(game, source)){ + if (SpellMasteryCondition.instance.apply(game, source)) { game.processAction(); for (Map.Entry entry : damageList) { entry.getKey().damage(entry.getValue(), source, game); diff --git a/Mage.Sets/src/mage/cards/o/OminousSphinx.java b/Mage.Sets/src/mage/cards/o/OminousSphinx.java index 0ca9748423c..523392f371c 100644 --- a/Mage.Sets/src/mage/cards/o/OminousSphinx.java +++ b/Mage.Sets/src/mage/cards/o/OminousSphinx.java @@ -12,8 +12,11 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Duration; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author spjspj @@ -32,7 +35,7 @@ public final class OminousSphinx extends CardImpl { // Whenever you cycle or discard a card,target creature an opponent controls gets -2/-0 until end of turn. CycleOrDiscardControllerTriggeredAbility ability = new CycleOrDiscardControllerTriggeredAbility(new BoostTargetEffect(-2, -0, Duration.EndOfTurn)); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/o/OnceMoreWithFeeling.java b/Mage.Sets/src/mage/cards/o/OnceMoreWithFeeling.java index ace067e1f21..5543200d25f 100644 --- a/Mage.Sets/src/mage/cards/o/OnceMoreWithFeeling.java +++ b/Mage.Sets/src/mage/cards/o/OnceMoreWithFeeling.java @@ -1,7 +1,6 @@ package mage.cards.o; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; @@ -19,8 +18,9 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import java.util.UUID; + /** - * * @author L_J */ public final class OnceMoreWithFeeling extends CardImpl { @@ -38,7 +38,7 @@ public final class OnceMoreWithFeeling extends CardImpl { // DCI ruling — A deck can have only one card named Once More with Feeling. // (according to rule 112.6m, this shouldn't do anything) - this.getSpellAbility().addEffect(new InfoEffect("
DCI ruling — A deck can have only one card named {this}")); + this.getSpellAbility().addEffect(new InfoEffect("
DCI ruling — A deck can have only one card named Once More with Feeling")); } private OnceMoreWithFeeling(final OnceMoreWithFeeling card) { diff --git a/Mage.Sets/src/mage/cards/o/OpalAcrolith.java b/Mage.Sets/src/mage/cards/o/OpalAcrolith.java index 3faf035927a..7f52f026c94 100644 --- a/Mage.Sets/src/mage/cards/o/OpalAcrolith.java +++ b/Mage.Sets/src/mage/cards/o/OpalAcrolith.java @@ -1,13 +1,9 @@ package mage.cards.o; -import java.util.UUID; -import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; -import mage.abilities.condition.common.SourceMatchesFilterCondition; +import mage.abilities.condition.common.SourceIsEnchantmentCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.effects.common.continuous.BecomesEnchantmentSourceEffect; import mage.cards.CardImpl; @@ -15,35 +11,28 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; -import mage.filter.FilterSpell; import mage.filter.StaticFilters; -import mage.game.permanent.token.TokenImpl; +import mage.game.permanent.token.custom.CreatureToken; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class OpalAcrolith extends CardImpl { - private static final FilterSpell filter = new FilterSpell("creature spell"); - - static { - filter.add(CardType.CREATURE.getPredicate()); - } - public OpalAcrolith(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}"); // Whenever an opponent casts a creature spell, if Opal Acrolith is an enchantment, Opal Acrolith becomes a 2/4 Soldier creature. - TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new OpalAcrolithToken(), null, Duration.WhileOnBattlefield), - filter, false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_PERMANENT_ENCHANTMENT), - "Whenever an opponent casts a creature spell, if Opal Acrolith is an enchantment, Opal Acrolith becomes a 2/4 Soldier creature.")); + this.addAbility(new SpellCastOpponentTriggeredAbility( + new BecomesCreatureSourceEffect(new CreatureToken( + 2, 4, "2/4 Soldier creature", SubType.SOLDIER + ), null, Duration.WhileOnBattlefield), StaticFilters.FILTER_SPELL_A_CREATURE, false + ).withInterveningIf(SourceIsEnchantmentCondition.instance).withRuleTextReplacement(true)); // {0}: Opal Acrolith becomes an enchantment. - this.addAbility(new SimpleActivatedAbility(new BecomesEnchantmentSourceEffect(), new ManaCostsImpl<>("{0}"))); - + this.addAbility(new SimpleActivatedAbility(new BecomesEnchantmentSourceEffect().setText("this permanent becomes an enchantment"), new ManaCostsImpl<>("{0}"))); } private OpalAcrolith(final OpalAcrolith card) { @@ -55,22 +44,3 @@ public final class OpalAcrolith extends CardImpl { return new OpalAcrolith(this); } } - -class OpalAcrolithToken extends TokenImpl { - - public OpalAcrolithToken() { - super("Soldier", "2/4 Soldier creature"); - cardType.add(CardType.CREATURE); - subtype.add(SubType.SOLDIER); - power = new MageInt(2); - toughness = new MageInt(4); - } - - private OpalAcrolithToken(final OpalAcrolithToken token) { - super(token); - } - - public OpalAcrolithToken copy() { - return new OpalAcrolithToken(this); - } -} diff --git a/Mage.Sets/src/mage/cards/o/OpalArchangel.java b/Mage.Sets/src/mage/cards/o/OpalArchangel.java index 45a44a90a0b..7e82d75e61b 100644 --- a/Mage.Sets/src/mage/cards/o/OpalArchangel.java +++ b/Mage.Sets/src/mage/cards/o/OpalArchangel.java @@ -1,40 +1,38 @@ - package mage.cards.o; -import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; -import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.SourceIsEnchantmentCondition; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; 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.SubType; import mage.constants.Duration; +import mage.constants.SubType; import mage.filter.StaticFilters; -import mage.filter.common.FilterCreatureSpell; -import mage.game.permanent.token.TokenImpl; +import mage.game.permanent.token.custom.CreatureToken; import java.util.UUID; /** - * * @author LoneFox - * */ public final class OpalArchangel extends CardImpl { public OpalArchangel(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{4}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{W}"); // When an opponent casts a creature spell, if Opal Archangel is an enchantment, Opal Archangel becomes a 5/5 Angel creature with flying and vigilance. - TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new OpalArchangelToken(), null, Duration.WhileOnBattlefield), - new FilterCreatureSpell(), false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_PERMANENT_ENCHANTMENT), - "When an opponent casts a creature spell, if {this} is an enchantment, {this} becomes a 5/5 Angel creature with flying and vigilance.")); + this.addAbility(new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect( + new CreatureToken( + 5, 5, "5/5 Angel creature with flying and vigilance", SubType.ANGEL + ).withAbility(FlyingAbility.getInstance()).withAbility(VigilanceAbility.getInstance()), + null, Duration.WhileOnBattlefield + ), StaticFilters.FILTER_SPELL_A_CREATURE, false) + .withInterveningIf(SourceIsEnchantmentCondition.instance) + .withRuleTextReplacement(true) + .setTriggerPhrase("When an opponent casts a creature spell, ")); } private OpalArchangel(final OpalArchangel card) { @@ -46,23 +44,3 @@ public final class OpalArchangel extends CardImpl { return new OpalArchangel(this); } } - -class OpalArchangelToken extends TokenImpl { - - public OpalArchangelToken() { - super("Angel", "5/5 Angel creature with flying and vigilance"); - cardType.add(CardType.CREATURE); - subtype.add(SubType.ANGEL); - power = new MageInt(5); - toughness = new MageInt(5); - this.addAbility(FlyingAbility.getInstance()); - this.addAbility(VigilanceAbility.getInstance()); - } - private OpalArchangelToken(final OpalArchangelToken token) { - super(token); - } - - public OpalArchangelToken copy() { - return new OpalArchangelToken(this); - } -} diff --git a/Mage.Sets/src/mage/cards/o/OpalAvenger.java b/Mage.Sets/src/mage/cards/o/OpalAvenger.java index 812059959bf..5f1f3bc6f02 100644 --- a/Mage.Sets/src/mage/cards/o/OpalAvenger.java +++ b/Mage.Sets/src/mage/cards/o/OpalAvenger.java @@ -1,7 +1,7 @@ package mage.cards.o; -import mage.MageInt; import mage.abilities.StateTriggeredAbility; +import mage.abilities.condition.common.SourceIsEnchantmentCondition; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -11,8 +11,10 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.permanent.token.TokenImpl; +import mage.game.permanent.token.custom.CreatureToken; +import mage.players.Player; +import java.util.Optional; import java.util.UUID; /** @@ -40,9 +42,12 @@ public final class OpalAvenger extends CardImpl { class OpalAvengerStateTriggeredAbility extends StateTriggeredAbility { OpalAvengerStateTriggeredAbility() { - super(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new OpalAvengerToken(), null, Duration.Custom)); - this.withRuleTextReplacement(false); - setTriggerPhrase("When you have 10 or less life, if {this} is an enchantment, "); + super(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect( + new CreatureToken(3, 5, "3/5 Soldier creature", SubType.SOLDIER), null, Duration.Custom + )); + this.withInterveningIf(SourceIsEnchantmentCondition.instance); + this.withRuleTextReplacement(true); + this.setTriggerPhrase("When you have 10 or less life, "); } private OpalAvengerStateTriggeredAbility(final OpalAvengerStateTriggeredAbility ability) { @@ -56,38 +61,11 @@ class OpalAvengerStateTriggeredAbility extends StateTriggeredAbility { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (game.getState().getPlayer(getControllerId()) != null) { - return game.getState().getPlayer(getControllerId()).getLife() <= 10; - } - return false; - } - - @Override - public boolean checkInterveningIfClause(Game game) { - if (getSourcePermanentIfItStillExists(game) != null) { - return getSourcePermanentIfItStillExists(game).isEnchantment(game); - } - return false; - } - -} - -class OpalAvengerToken extends TokenImpl { - - public OpalAvengerToken() { - super("Soldier", "3/5 Soldier creature"); - cardType.add(CardType.CREATURE); - subtype.add(SubType.SOLDIER); - power = new MageInt(3); - toughness = new MageInt(5); - } - - private OpalAvengerToken(final OpalAvengerToken token) { - super(token); - } - - @Override - public OpalAvengerToken copy() { - return new OpalAvengerToken(this); + return Optional + .ofNullable(getControllerId()) + .map(game::getPlayer) + .map(Player::getLife) + .filter(x -> x <= 10) + .isPresent(); } } diff --git a/Mage.Sets/src/mage/cards/o/OpalCaryatid.java b/Mage.Sets/src/mage/cards/o/OpalCaryatid.java index 21af43734ae..b0b0c7ca819 100644 --- a/Mage.Sets/src/mage/cards/o/OpalCaryatid.java +++ b/Mage.Sets/src/mage/cards/o/OpalCaryatid.java @@ -1,38 +1,35 @@ - package mage.cards.o; -import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; -import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.SourceIsEnchantmentCondition; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; 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.filter.StaticFilters; -import mage.filter.common.FilterCreatureSpell; -import mage.game.permanent.token.TokenImpl; +import mage.game.permanent.token.custom.CreatureToken; import java.util.UUID; /** - * * @author LoneFox - * */ public final class OpalCaryatid extends CardImpl { public OpalCaryatid(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}"); // When an opponent casts a creature spell, if Opal Caryatid is an enchantment, Opal Caryatid becomes a 2/2 Soldier creature. - TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new OpalCaryatidSoldierToken(), null, Duration.WhileOnBattlefield), - new FilterCreatureSpell(), false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_PERMANENT_ENCHANTMENT), - "When an opponent casts a creature spell, if {this} is an enchantment, {this} becomes a 2/2 Soldier creature.")); + this.addAbility(new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect( + new CreatureToken( + 2, 2, "2/2 Soldier creature", SubType.SOLDIER + ), null, Duration.WhileOnBattlefield + ), StaticFilters.FILTER_SPELL_A_CREATURE, false) + .withInterveningIf(SourceIsEnchantmentCondition.instance) + .withRuleTextReplacement(true) + .setTriggerPhrase("When an opponent casts a creature spell, ")); } private OpalCaryatid(final OpalCaryatid card) { @@ -44,22 +41,3 @@ public final class OpalCaryatid extends CardImpl { return new OpalCaryatid(this); } } - -class OpalCaryatidSoldierToken extends TokenImpl { - - public OpalCaryatidSoldierToken() { - super("Soldier", "2/2 Soldier creature"); - cardType.add(CardType.CREATURE); - subtype.add(SubType.SOLDIER); - power = new MageInt(2); - toughness = new MageInt(2); - } - - private OpalCaryatidSoldierToken(final OpalCaryatidSoldierToken token) { - super(token); - } - - public OpalCaryatidSoldierToken copy() { - return new OpalCaryatidSoldierToken(this); - } -} diff --git a/Mage.Sets/src/mage/cards/o/OpalChampion.java b/Mage.Sets/src/mage/cards/o/OpalChampion.java index f1b24cca13f..24e8386ebf7 100644 --- a/Mage.Sets/src/mage/cards/o/OpalChampion.java +++ b/Mage.Sets/src/mage/cards/o/OpalChampion.java @@ -1,39 +1,36 @@ - package mage.cards.o; -import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; -import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.SourceIsEnchantmentCondition; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.keyword.FirstStrikeAbility; 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.filter.StaticFilters; -import mage.filter.common.FilterCreatureSpell; -import mage.game.permanent.token.TokenImpl; +import mage.game.permanent.token.custom.CreatureToken; import java.util.UUID; /** - * * @author LoneFox - * */ public final class OpalChampion extends CardImpl { public OpalChampion(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}"); // When an opponent casts a creature spell, if Opal Champion is an enchantment, Opal Champion becomes a 3/3 Knight creature with first strike. - TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new OpalChampionKnight(), null, Duration.WhileOnBattlefield), - new FilterCreatureSpell(), false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_PERMANENT_ENCHANTMENT), - "When an opponent casts a creature spell, if {this} is an enchantment, {this} becomes a 3/3 Knight creature with first strike.")); + this.addAbility(new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect( + new CreatureToken( + 3, 3, "3/3 Knight creature with first strike", SubType.KNIGHT + ).withAbility(FirstStrikeAbility.getInstance()), null, Duration.WhileOnBattlefield + ), StaticFilters.FILTER_SPELL_A_CREATURE, false) + .withInterveningIf(SourceIsEnchantmentCondition.instance) + .withRuleTextReplacement(true) + .setTriggerPhrase("When an opponent casts a creature spell, ")); } private OpalChampion(final OpalChampion card) { @@ -45,22 +42,3 @@ public final class OpalChampion extends CardImpl { return new OpalChampion(this); } } - -class OpalChampionKnight extends TokenImpl { - - public OpalChampionKnight() { - super("Knight", "3/3 Knight creature with first strike"); - cardType.add(CardType.CREATURE); - subtype.add(SubType.KNIGHT); - power = new MageInt(3); - toughness = new MageInt(3); - this.addAbility(FirstStrikeAbility.getInstance()); - } - private OpalChampionKnight(final OpalChampionKnight token) { - super(token); - } - - public OpalChampionKnight copy() { - return new OpalChampionKnight(this); - } -} diff --git a/Mage.Sets/src/mage/cards/o/OpalGargoyle.java b/Mage.Sets/src/mage/cards/o/OpalGargoyle.java index 584d69f6141..db6dd091d7d 100644 --- a/Mage.Sets/src/mage/cards/o/OpalGargoyle.java +++ b/Mage.Sets/src/mage/cards/o/OpalGargoyle.java @@ -1,39 +1,36 @@ - package mage.cards.o; -import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; -import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.SourceIsEnchantmentCondition; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; 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.SubType; import mage.filter.StaticFilters; -import mage.filter.common.FilterCreatureSpell; -import mage.game.permanent.token.TokenImpl; +import mage.game.permanent.token.custom.CreatureToken; import java.util.UUID; /** - * * @author LoneFox - * */ public final class OpalGargoyle extends CardImpl { public OpalGargoyle(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}"); // When an opponent casts a creature spell, if Opal Gargoyle is an enchantment, Opal Gargoyle becomes a 2/2 Gargoyle creature with flying. - TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new OpalGargoyleToken(), null, Duration.WhileOnBattlefield), - new FilterCreatureSpell(), false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_PERMANENT_ENCHANTMENT), - "When an opponent casts a creature spell, if {this} is an enchantment, {this} becomes a 2/2 Gargoyle creature with flying.")); + this.addAbility(new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect( + new CreatureToken( + 2, 2, "2/2 Gargoyle creature with flying", SubType.GARGOYLE + ).withAbility(FlyingAbility.getInstance()), null, Duration.WhileOnBattlefield + ), StaticFilters.FILTER_SPELL_A_CREATURE, false) + .withInterveningIf(SourceIsEnchantmentCondition.instance) + .withRuleTextReplacement(true) + .setTriggerPhrase("When an opponent casts a creature spell, ")); } private OpalGargoyle(final OpalGargoyle card) { @@ -45,22 +42,3 @@ public final class OpalGargoyle extends CardImpl { return new OpalGargoyle(this); } } - -class OpalGargoyleToken extends TokenImpl { - - public OpalGargoyleToken() { - super("Gargoyle", "2/2 Gargoyle creature with flying"); - cardType.add(CardType.CREATURE); - subtype.add(SubType.GARGOYLE); - power = new MageInt(2); - toughness = new MageInt(2); - this.addAbility(FlyingAbility.getInstance()); - } - private OpalGargoyleToken(final OpalGargoyleToken token) { - super(token); - } - - public OpalGargoyleToken copy() { - return new OpalGargoyleToken(this); - } -} diff --git a/Mage.Sets/src/mage/cards/o/OpalGuardian.java b/Mage.Sets/src/mage/cards/o/OpalGuardian.java index 40053381d52..8cf25a495c0 100644 --- a/Mage.Sets/src/mage/cards/o/OpalGuardian.java +++ b/Mage.Sets/src/mage/cards/o/OpalGuardian.java @@ -1,41 +1,39 @@ - package mage.cards.o; -import mage.MageInt; import mage.ObjectColor; -import mage.abilities.TriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; -import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.SourceIsEnchantmentCondition; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.ProtectionAbility; 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.filter.StaticFilters; -import mage.filter.common.FilterCreatureSpell; -import mage.game.permanent.token.TokenImpl; +import mage.game.permanent.token.custom.CreatureToken; import java.util.UUID; /** - * * @author LoneFox - * */ public final class OpalGuardian extends CardImpl { public OpalGuardian(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{W}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}{W}{W}"); // When an opponent casts a creature spell, if Opal Guardian is an enchantment, Opal Guardian becomes a 3/4 Gargoyle creature with flying and protection from red. - TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new OpalGuardianGargoyle(), null, Duration.WhileOnBattlefield), - new FilterCreatureSpell(), false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_PERMANENT_ENCHANTMENT), - "When an opponent casts a creature spell, if {this} is an enchantment, {this} becomes a 3/4 Gargoyle creature with flying and protection from red.")); + this.addAbility(new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect( + new CreatureToken( + 3, 4, "3/4 Gargoyle creature with " + + "flying and protection from red", SubType.GARGOYLE + ).withAbility(FlyingAbility.getInstance()).withAbility(ProtectionAbility.from(ObjectColor.RED)), + null, Duration.WhileOnBattlefield + ), StaticFilters.FILTER_SPELL_A_CREATURE, false) + .withInterveningIf(SourceIsEnchantmentCondition.instance) + .setTriggerPhrase("When an opponent casts a creature spell, ")); } private OpalGuardian(final OpalGuardian card) { @@ -47,22 +45,3 @@ public final class OpalGuardian extends CardImpl { return new OpalGuardian(this); } } - -class OpalGuardianGargoyle extends TokenImpl { - public OpalGuardianGargoyle() { - super("Gargoyle", "3/4 Gargoyle creature with flying and protection from red"); - cardType.add(CardType.CREATURE); - subtype.add(SubType.GARGOYLE); - power = new MageInt(3); - toughness = new MageInt(4); - this.addAbility(FlyingAbility.getInstance()); - this.addAbility(ProtectionAbility.from(ObjectColor.RED)); - } - private OpalGuardianGargoyle(final OpalGuardianGargoyle token) { - super(token); - } - - public OpalGuardianGargoyle copy() { - return new OpalGuardianGargoyle(this); - } -} diff --git a/Mage.Sets/src/mage/cards/o/OpalLakeGatekeepers.java b/Mage.Sets/src/mage/cards/o/OpalLakeGatekeepers.java index 9f9084899f1..aa933a62b71 100644 --- a/Mage.Sets/src/mage/cards/o/OpalLakeGatekeepers.java +++ b/Mage.Sets/src/mage/cards/o/OpalLakeGatekeepers.java @@ -2,35 +2,21 @@ package mage.cards.o; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.condition.Condition; -import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.YouControlTwoOrMoreGatesCondition; import mage.abilities.effects.common.DrawCardSourceControllerEffect; -import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.common.GatesYouControlHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.ComparisonType; import mage.constants.SubType; -import mage.filter.common.FilterControlledPermanent; import java.util.UUID; /** * @author LevelX2 */ - - public final class OpalLakeGatekeepers extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent(); - - static { - filter.add(SubType.GATE.getPredicate()); - } - - private static final Condition gatesCondition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1); - public OpalLakeGatekeepers(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); this.subtype.add(SubType.VEDALKEN); @@ -40,11 +26,8 @@ public final class OpalLakeGatekeepers extends CardImpl { this.toughness = new MageInt(4); // When Opal Lake Gatekeepers enters the battlefield, if you control two or more Gates, you may draw a card. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1), true), - gatesCondition, - "When Opal Lake Gatekeepers enters the battlefield, if you control two or more Gates, you may draw a card.") - .addHint(new ConditionHint(gatesCondition, "You control two or more Gates"))); + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1), true) + .withInterveningIf(YouControlTwoOrMoreGatesCondition.instance).addHint(GatesYouControlHint.instance)); } private OpalLakeGatekeepers(final OpalLakeGatekeepers card) { diff --git a/Mage.Sets/src/mage/cards/o/OpalTitan.java b/Mage.Sets/src/mage/cards/o/OpalTitan.java index 2f7e0167e9d..c8f00d4bd72 100644 --- a/Mage.Sets/src/mage/cards/o/OpalTitan.java +++ b/Mage.Sets/src/mage/cards/o/OpalTitan.java @@ -3,10 +3,8 @@ package mage.cards.o; import mage.MageObjectReference; import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.TriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; -import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.SourceIsEnchantmentCondition; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.keyword.ProtectionAbility; import mage.cards.CardImpl; @@ -28,11 +26,11 @@ public final class OpalTitan extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); // When an opponent casts a creature spell, if Opal Titan is an enchantment, Opal Titan becomes a 4/4 Giant creature with protection from each of that spell's colors. - TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(Zone.BATTLEFIELD, new OpalTitanBecomesCreatureEffect(), - StaticFilters.FILTER_SPELL_A_CREATURE, false, SetTargetPointer.SPELL); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_PERMANENT_ENCHANTMENT), - "When an opponent casts a creature spell, if Opal Titan is an enchantment, Opal Titan becomes a 4/4 Giant creature with protection from each of that spell's colors.")); - + this.addAbility(new SpellCastOpponentTriggeredAbility( + Zone.BATTLEFIELD, new OpalTitanBecomesCreatureEffect(), + StaticFilters.FILTER_SPELL_A_CREATURE, false, SetTargetPointer.SPELL + ).withInterveningIf(SourceIsEnchantmentCondition.instance) + .setTriggerPhrase("When an opponent casts a creature spell, ")); } private OpalTitan(final OpalTitan card) { @@ -49,7 +47,7 @@ class OpalTitanBecomesCreatureEffect extends ContinuousEffectImpl { OpalTitanBecomesCreatureEffect() { super(Duration.WhileOnBattlefield, Outcome.BecomeCreature); - staticText = "{this} becomes a 4/4 Giant creature with protection from each of that spell's colors."; + staticText = "it becomes a 4/4 Giant creature with protection from each of that spell's colors."; this.addDependencyType(DependencyType.BecomeCreature); } @@ -117,5 +115,4 @@ class OpalTitanBecomesCreatureEffect extends ContinuousEffectImpl { || layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.TypeChangingEffects_4; } - } diff --git a/Mage.Sets/src/mage/cards/o/Ophiomancer.java b/Mage.Sets/src/mage/cards/o/Ophiomancer.java index 4427d99cd68..ec9e127a3c1 100644 --- a/Mage.Sets/src/mage/cards/o/Ophiomancer.java +++ b/Mage.Sets/src/mage/cards/o/Ophiomancer.java @@ -1,24 +1,30 @@ - package mage.cards.o; -import java.util.UUID; import mage.MageInt; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; import mage.game.permanent.token.OphiomancerSnakeToken; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class Ophiomancer extends CardImpl { + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterCreaturePermanent(SubType.SNAKE, "you control no Snakes"), ComparisonType.EQUAL_TO, 0 + ); + public Ophiomancer(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); this.subtype.add(SubType.HUMAN); @@ -28,10 +34,9 @@ public final class Ophiomancer extends CardImpl { this.toughness = new MageInt(2); // At the beginning of each upkeep, if you control no Snakes, create a 1/1 black Snake creature token with deathtouch. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(TargetController.ANY, new CreateTokenEffect(new OphiomancerSnakeToken()), false), - new PermanentsOnTheBattlefieldCondition(new FilterCreaturePermanent(SubType.SNAKE, "no Snakes"), ComparisonType.EQUAL_TO, 0), - "At the beginning of each upkeep, if you control no Snakes, create a 1/1 black Snake creature token with deathtouch.")); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + TargetController.ANY, new CreateTokenEffect(new OphiomancerSnakeToken()), false + ).withInterveningIf(condition)); } private Ophiomancer(final Ophiomancer card) { diff --git a/Mage.Sets/src/mage/cards/o/OracleEnVec.java b/Mage.Sets/src/mage/cards/o/OracleEnVec.java index 042c879eed7..7a7802eb45d 100644 --- a/Mage.Sets/src/mage/cards/o/OracleEnVec.java +++ b/Mage.Sets/src/mage/cards/o/OracleEnVec.java @@ -13,7 +13,6 @@ import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.RequirementEffect; import mage.abilities.effects.RestrictionEffect; import mage.abilities.effects.common.DestroyTargetEffect; -import mage.abilities.hint.common.MyTurnHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -46,9 +45,10 @@ public final class OracleEnVec extends CardImpl { // {T}: Target opponent chooses any number of creatures they control. During that player’s next turn, the chosen // creatures attack if able, and other creatures can’t attack. At the beginning of that turn’s end step, // destroy each of the chosen creatures that didn’t attack this turn. Activate this ability only during your turn. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new OracleEnVecEffect(), new TapSourceCost(), MyTurnCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new OracleEnVecEffect(), new TapSourceCost(), MyTurnCondition.instance + ); ability.addTarget(new TargetOpponent()); - ability.addHint(MyTurnHint.instance); this.addAbility(ability); } @@ -83,25 +83,27 @@ class OracleEnVecEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player opponent = game.getPlayer(this.getTargetPointer().getFirst(game, source)); - if (opponent != null) { - Target target = new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, new FilterControlledCreaturePermanent(), true); - if (target.choose(Outcome.Neutral, opponent.getId(), source.getSourceId(), source, game)) { - for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), opponent.getId(), source, game)) { - if (target.getTargets().contains(permanent.getId())) { - RequirementEffect effect = new OracleEnVecMustAttackRequirementEffect(); - effect.setTargetPointer(new FixedTarget(permanent, game)); - game.addEffect(effect, source); - } else { - RestrictionEffect effect = new OracleEnVecCantAttackRestrictionEffect(); - effect.setTargetPointer(new FixedTarget(permanent, game)); - game.addEffect(effect, source); - } - } - game.addDelayedTriggeredAbility(new OracleEnVecDelayedTriggeredAbility(game.getTurnNum(), target.getTargets()), source); - return true; + if (opponent == null) { + return false; + } + Target target = new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE); + target.withNotTarget(true); + if (!target.choose(Outcome.Neutral, opponent.getId(), source.getSourceId(), source, game)) { + return false; + } + for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), opponent.getId(), source, game)) { + if (target.getTargets().contains(permanent.getId())) { + RequirementEffect effect = new OracleEnVecMustAttackRequirementEffect(); + effect.setTargetPointer(new FixedTarget(permanent, game)); + game.addEffect(effect, source); + } else { + RestrictionEffect effect = new OracleEnVecCantAttackRestrictionEffect(); + effect.setTargetPointer(new FixedTarget(permanent, game)); + game.addEffect(effect, source); } } - return false; + game.addDelayedTriggeredAbility(new OracleEnVecDelayedTriggeredAbility(game.getTurnNum(), target.getTargets()), source); + return true; } } diff --git a/Mage.Sets/src/mage/cards/o/OracleOfBones.java b/Mage.Sets/src/mage/cards/o/OracleOfBones.java index 67235fda3fb..37e594aae44 100644 --- a/Mage.Sets/src/mage/cards/o/OracleOfBones.java +++ b/Mage.Sets/src/mage/cards/o/OracleOfBones.java @@ -3,7 +3,6 @@ package mage.cards.o; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TributeNotPaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.cost.CastFromHandForFreeEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.TributeAbility; @@ -11,7 +10,8 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.StaticFilters; +import mage.filter.FilterCard; +import mage.filter.common.FilterInstantOrSorceryCard; import java.util.UUID; @@ -20,6 +20,8 @@ import java.util.UUID; */ public final class OracleOfBones extends CardImpl { + private static final FilterCard filter = new FilterInstantOrSorceryCard("an instant or sorcery spell"); + public OracleOfBones(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}"); this.subtype.add(SubType.MINOTAUR); @@ -30,18 +32,14 @@ public final class OracleOfBones extends CardImpl { // Haste this.addAbility(HasteAbility.getInstance()); + // Tribute 2 this.addAbility(new TributeAbility(2)); + // When Oracle of Bones enters the battlefield, if tribute wasn't paid, // you may cast an instant or sorcery card from your hand without paying its mana cost. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new CastFromHandForFreeEffect( - StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY - ), false), - TributeNotPaidCondition.instance, "When {this} enters, " + - "if tribute wasn't paid, you may cast an instant or " + - "sorcery spell from your hand without paying its mana cost." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CastFromHandForFreeEffect(filter)) + .withInterveningIf(TributeNotPaidCondition.instance)); } private OracleOfBones(final OracleOfBones card) { diff --git a/Mage.Sets/src/mage/cards/o/OraclesVault.java b/Mage.Sets/src/mage/cards/o/OraclesVault.java index 9ddbc215f7c..bdaf943dd52 100644 --- a/Mage.Sets/src/mage/cards/o/OraclesVault.java +++ b/Mage.Sets/src/mage/cards/o/OraclesVault.java @@ -6,7 +6,7 @@ import mage.abilities.condition.Condition; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ExileTopXMayPlayUntilEffect; import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect; @@ -42,7 +42,7 @@ public final class OraclesVault extends CardImpl { // {T}: Exile the top card of your library. Until end of turn, you may play that card without paying its mana cost. // Activate this ability only if there are three or more brick counters on Oracle's Vault. - this.addAbility(new ConditionalActivatedAbility(new OraclesVaultFreeEffect(), new TapSourceCost(), condition)); + this.addAbility(new ActivateIfConditionActivatedAbility(new OraclesVaultFreeEffect(), new TapSourceCost(), condition)); } private OraclesVault(final OraclesVault card) { diff --git a/Mage.Sets/src/mage/cards/o/OrahSkyclaveHierophant.java b/Mage.Sets/src/mage/cards/o/OrahSkyclaveHierophant.java index 96a82a5c3e8..4cf1149e302 100644 --- a/Mage.Sets/src/mage/cards/o/OrahSkyclaveHierophant.java +++ b/Mage.Sets/src/mage/cards/o/OrahSkyclaveHierophant.java @@ -1,19 +1,25 @@ package mage.cards.o; import mage.MageInt; -import mage.MageObject; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; +import mage.abilities.common.DiesThisOrAnotherTriggeredAbility; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.keyword.LifelinkAbility; +import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.filter.FilterCard; -import mage.filter.predicate.mageobject.ManaValuePredicate; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; import mage.target.common.TargetCardInYourGraveyard; +import mage.util.CardUtil; import java.util.UUID; @@ -22,6 +28,14 @@ import java.util.UUID; */ public final class OrahSkyclaveHierophant extends CardImpl { + private static final FilterPermanent filterTrigger = new FilterControlledPermanent("Cleric you control"); + private static final FilterCard filterTarget = new FilterCard("Cleric card with lesser mana value"); + static { + filterTrigger.add(SubType.CLERIC.getPredicate()); + filterTarget.add(SubType.CLERIC.getPredicate()); + filterTarget.add(OrahSkyclaveHierophantPredicate.instance); + } + public OrahSkyclaveHierophant(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{B}"); @@ -35,7 +49,9 @@ public final class OrahSkyclaveHierophant extends CardImpl { this.addAbility(LifelinkAbility.getInstance()); // Whenever Orah, Skyclave Hierophant or another Cleric you control dies, return target Cleric card with lesser converted mana cost from your graveyard to the battlefield. - this.addAbility(new OrahSkyclaveHierophantTriggeredAbility()); + Ability ability = new DiesThisOrAnotherTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect(), false, filterTrigger); + ability.addTarget(new TargetCardInYourGraveyard(filterTarget)); + this.addAbility(ability); } private OrahSkyclaveHierophant(final OrahSkyclaveHierophant card) { @@ -48,57 +64,15 @@ public final class OrahSkyclaveHierophant extends CardImpl { } } -class OrahSkyclaveHierophantTriggeredAbility extends TriggeredAbilityImpl { - - OrahSkyclaveHierophantTriggeredAbility() { - super(Zone.BATTLEFIELD, new ReturnFromGraveyardToBattlefieldTargetEffect()); - setLeavesTheBattlefieldTrigger(true); - } - - private OrahSkyclaveHierophantTriggeredAbility(final OrahSkyclaveHierophantTriggeredAbility ability) { - super(ability); - } +enum OrahSkyclaveHierophantPredicate implements ObjectSourcePlayerPredicate { + instance; @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() - || !zEvent.getTarget().isControlledBy(getControllerId()) - || (!zEvent.getTarget().hasSubtype(SubType.CLERIC, game) - && !zEvent.getTarget().getId().equals(getSourceId())) - ) { - return false; - } - FilterCard filterCard = new FilterCard( - "Cleric card with mana value less than " + (zEvent.getTarget().getManaValue()) - ); - filterCard.add(SubType.CLERIC.getPredicate()); - filterCard.add(new ManaValuePredicate( - ComparisonType.FEWER_THAN, zEvent.getTarget().getManaValue() - )); - this.getTargets().clear(); - this.addTarget(new TargetCardInYourGraveyard(filterCard)); - return true; - } - - @Override - public OrahSkyclaveHierophantTriggeredAbility copy() { - return new OrahSkyclaveHierophantTriggeredAbility(this); - } - - @Override - public String getRule() { - return "Whenever {this} or another Cleric you control dies, return target Cleric card " + - "with lesser mana value from your graveyard to the battlefield."; - } - - @Override - public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) { - return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game); + public boolean apply(ObjectSourcePlayer input, Game game) { + return CardUtil.getEffectValueFromAbility( + input.getSource(), "creatureDied", Permanent.class + ) + .filter(permanent -> input.getObject().getManaValue() < permanent.getManaValue()) + .isPresent(); } } diff --git a/Mage.Sets/src/mage/cards/o/OranRiefRecluse.java b/Mage.Sets/src/mage/cards/o/OranRiefRecluse.java index 526f453eafd..4a3bf001199 100644 --- a/Mage.Sets/src/mage/cards/o/OranRiefRecluse.java +++ b/Mage.Sets/src/mage/cards/o/OranRiefRecluse.java @@ -1,11 +1,9 @@ - package mage.cards.o; -import java.util.UUID; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.KickerAbility; @@ -14,24 +12,26 @@ 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.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author North */ public final class OranRiefRecluse extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with flying"); + private static final FilterPermanent filter = new FilterCreaturePermanent("creature with flying"); static { filter.add(new AbilityPredicate(FlyingAbility.class)); } public OranRiefRecluse(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); this.subtype.add(SubType.SPIDER); this.power = new MageInt(1); @@ -44,9 +44,9 @@ public final class OranRiefRecluse extends CardImpl { this.addAbility(ReachAbility.getInstance()); // When Oran-Rief Recluse enters the battlefield, if it was kicked, destroy target creature with flying. - EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), false); - ability.addTarget(new TargetCreaturePermanent(filter)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.ONCE, "When {this} enters, if it was kicked, destroy target creature with flying.")); + Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()).withInterveningIf(KickedCondition.ONCE); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); } private OranRiefRecluse(final OranRiefRecluse card) { diff --git a/Mage.Sets/src/mage/cards/o/OratorOfOjutai.java b/Mage.Sets/src/mage/cards/o/OratorOfOjutai.java index 4b85e8d5274..e142e06615b 100644 --- a/Mage.Sets/src/mage/cards/o/OratorOfOjutai.java +++ b/Mage.Sets/src/mage/cards/o/OratorOfOjutai.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RevealedOrControlledDragonCondition; import mage.abilities.costs.common.RevealDragonFromHandCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.keyword.DefenderAbility; import mage.abilities.keyword.FlyingAbility; @@ -36,11 +35,8 @@ public final class OratorOfOjutai extends CardImpl { this.getSpellAbility().addCost(new RevealDragonFromHandCost()); // When Orator of Ojutai enters the battlefield, if you revealed a Dragon card or controlled a Dragon as you cast Orator of Ojutai, draw a card. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)), - RevealedOrControlledDragonCondition.instance, "When {this} enters, " + - "if you revealed a Dragon card or controlled a Dragon as you cast this spell, draw a card." - ), new DragonOnTheBattlefieldWhileSpellWasCastWatcher()); + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)) + .withInterveningIf(RevealedOrControlledDragonCondition.instance), new DragonOnTheBattlefieldWhileSpellWasCastWatcher()); } private OratorOfOjutai(final OratorOfOjutai card) { diff --git a/Mage.Sets/src/mage/cards/o/OrazcaRelic.java b/Mage.Sets/src/mage/cards/o/OrazcaRelic.java index 693775012da..06573ddbb5e 100644 --- a/Mage.Sets/src/mage/cards/o/OrazcaRelic.java +++ b/Mage.Sets/src/mage/cards/o/OrazcaRelic.java @@ -4,7 +4,7 @@ import mage.abilities.Ability; import mage.abilities.condition.common.CitysBlessingCondition; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.hint.common.CitysBlessingHint; @@ -13,7 +13,6 @@ import mage.abilities.mana.ColorlessManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; import java.util.UUID; @@ -32,14 +31,12 @@ public final class OrazcaRelic extends CardImpl { this.addAbility(new ColorlessManaAbility()); // {T}, Sacrifice Orazca Relic: You gain 3 life and draw a card. Activate this ability only if you have the city's blessing. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, - new GainLifeEffect(3), - new TapSourceCost(), - CitysBlessingCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new GainLifeEffect(3), new TapSourceCost(), CitysBlessingCondition.instance + ); ability.addCost(new SacrificeSourceCost()); ability.addEffect(new DrawCardSourceControllerEffect(1).concatBy("and")); - ability.addHint(CitysBlessingHint.instance); - this.addAbility(ability); + this.addAbility(ability.addHint(CitysBlessingHint.instance)); } private OrazcaRelic(final OrazcaRelic card) { diff --git a/Mage.Sets/src/mage/cards/o/OrcSureshot.java b/Mage.Sets/src/mage/cards/o/OrcSureshot.java index 2775f54e368..a3b18451bac 100644 --- a/Mage.Sets/src/mage/cards/o/OrcSureshot.java +++ b/Mage.Sets/src/mage/cards/o/OrcSureshot.java @@ -10,10 +10,13 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -31,7 +34,7 @@ public final class OrcSureshot extends CardImpl { Ability ability = new EntersBattlefieldControlledTriggeredAbility( new BoostTargetEffect(-1,-1, Duration.EndOfTurn), StaticFilters.FILTER_ANOTHER_CREATURE); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/o/OrcishCaptain.java b/Mage.Sets/src/mage/cards/o/OrcishCaptain.java index 7babdaf7515..5ae5a5337ed 100644 --- a/Mage.Sets/src/mage/cards/o/OrcishCaptain.java +++ b/Mage.Sets/src/mage/cards/o/OrcishCaptain.java @@ -15,6 +15,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,7 +39,7 @@ public final class OrcishCaptain extends CardImpl { // {1}: Flip a coin. If you win the flip, target Orc creature gets +2/+0 until end of turn. If you lose the flip, it gets -0/-2 until end of turn. Ability ability = new SimpleActivatedAbility(new OrcishCaptainEffect(), new GenericManaCost(1)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/o/OrcishHealer.java b/Mage.Sets/src/mage/cards/o/OrcishHealer.java index f3628345b66..330e5e64b03 100644 --- a/Mage.Sets/src/mage/cards/o/OrcishHealer.java +++ b/Mage.Sets/src/mage/cards/o/OrcishHealer.java @@ -19,6 +19,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -51,13 +52,13 @@ public final class OrcishHealer extends CardImpl { // {B}{B}{R}, {tap}: Regenerate target black or green creature. ability = new SimpleActivatedAbility(new RegenerateTargetEffect(), new ManaCostsImpl<>("{B}{B}{R}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // {R}{G}{G}, {tap}: Regenerate target black or green creature. ability = new SimpleActivatedAbility(new RegenerateTargetEffect(), new ManaCostsImpl<>("{R}{G}{G}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/o/OrcishSettlers.java b/Mage.Sets/src/mage/cards/o/OrcishSettlers.java index 2d33e36f563..2570380a90e 100644 --- a/Mage.Sets/src/mage/cards/o/OrcishSettlers.java +++ b/Mage.Sets/src/mage/cards/o/OrcishSettlers.java @@ -7,20 +7,14 @@ 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.abilities.effects.common.DestroyTargetEffect; 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.TargetLandPermanent; -import mage.util.CardUtil; +import mage.target.targetadjustment.XTargetsCountAdjuster; -import java.util.List; import java.util.UUID; /** @@ -38,9 +32,12 @@ public final class OrcishSettlers extends CardImpl { this.toughness = new MageInt(1); // {X}{X}{R}, {tap}, Sacrifice Orcish Settlers: Destroy X target lands. - Ability ability = new SimpleActivatedAbility(new OrcishSettlersEffect(), new ManaCostsImpl<>("{X}{X}{R}")); + Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect().setText("Destroy X target lands"), + new ManaCostsImpl<>("{X}{X}{R}")); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetLandPermanent()); + ability.setTargetAdjuster(new XTargetsCountAdjuster()); this.addAbility(ability); } @@ -53,43 +50,3 @@ public final class OrcishSettlers extends CardImpl { return new OrcishSettlers(this); } } - -class OrcishSettlersEffect extends OneShotEffect { - - OrcishSettlersEffect() { - super(Outcome.DestroyPermanent); - this.staticText = "Destroy X target lands"; - } - - private OrcishSettlersEffect(final OrcishSettlersEffect effect) { - super(effect); - } - - @Override - public OrcishSettlersEffect copy() { - return new OrcishSettlersEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - int amount = CardUtil.getSourceCostsTag(game, source, "X", 0); - if (amount == 0) { - return false; - } - TargetLandPermanent target = new TargetLandPermanent(amount); - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null - && target.canChoose(controller.getId(), source, game) - && controller.choose(Outcome.DestroyPermanent, target, source, game)) { - List targets = target.getTargets(); - targets.forEach((landId) -> { - Permanent land = game.getPermanent(landId); - if (land != null) { - land.destroy(source, game, false); - } - }); - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/o/OrderOfSuccession.java b/Mage.Sets/src/mage/cards/o/OrderOfSuccession.java index 9563f5df456..13901ce9c57 100644 --- a/Mage.Sets/src/mage/cards/o/OrderOfSuccession.java +++ b/Mage.Sets/src/mage/cards/o/OrderOfSuccession.java @@ -21,6 +21,7 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.players.PlayerList; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; @@ -98,7 +99,7 @@ class OrderOfSuccessionEffect extends OneShotEffect { if (currentPlayer != null && game.getState().getPlayersInRange(controller.getId(), game).contains(currentPlayer.getId())) { FilterCreaturePermanent filter = new FilterCreaturePermanent("creature controlled by " + nextPlayer.getLogName()); filter.add(new ControllerIdPredicate(nextPlayer.getId())); - Target target = new TargetCreaturePermanent(filter); + Target target = new TargetPermanent(filter); target.withNotTarget(true); if (target.canChoose(currentPlayer.getId(), source, game)) { if (currentPlayer.chooseTarget(outcome, target, source, game)) { diff --git a/Mage.Sets/src/mage/cards/o/OrdruunMentor.java b/Mage.Sets/src/mage/cards/o/OrdruunMentor.java index a42c25b507a..6e6a8b680bd 100644 --- a/Mage.Sets/src/mage/cards/o/OrdruunMentor.java +++ b/Mage.Sets/src/mage/cards/o/OrdruunMentor.java @@ -1,21 +1,21 @@ package mage.cards.o; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; +import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.MentorAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +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.ObjectSourcePlayer; import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; -import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.util.CardUtil; @@ -27,6 +27,12 @@ import java.util.UUID; */ public final class OrdruunMentor extends CardImpl { + private static final FilterPermanent filter = new FilterCreaturePermanent("creature that's attacking that player"); + + static { + filter.add(OrdruunMentorPredicate.instance); + } + public OrdruunMentor(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R/W}"); @@ -39,7 +45,10 @@ public final class OrdruunMentor extends CardImpl { this.addAbility(new MentorAbility()); // Whenever you attack a player, target creature that's attacking that player gains first strike until end of turn. - this.addAbility(new OrdruunMentorTriggeredAbility()); + Ability ability = new AttacksPlayerWithCreaturesTriggeredAbility( + new GainAbilityTargetEffect(FirstStrikeAbility.getInstance()), SetTargetPointer.NONE); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); } private OrdruunMentor(final OrdruunMentor card) { @@ -51,54 +60,13 @@ public final class OrdruunMentor extends CardImpl { return new OrdruunMentor(this); } } - -class OrdruunMentorTriggeredAbility extends TriggeredAbilityImpl { - - private enum OrdruunMentorPredicate implements ObjectSourcePlayerPredicate { - instance; - - @Override - public boolean apply(ObjectSourcePlayer input, Game game) { - return CardUtil.getEffectValueFromAbility( - input.getSource(), "playerAttacked", UUID.class - ) - .filter(uuid -> uuid.equals(game.getCombat().getDefenderId(input.getObject().getId()))) - .isPresent(); - } - } - - private static final FilterPermanent filter = new FilterCreaturePermanent("creature that's attacking that player"); - - static { - filter.add(OrdruunMentorPredicate.instance); - } - - OrdruunMentorTriggeredAbility() { - super(Zone.BATTLEFIELD, new GainAbilityTargetEffect(FirstStrikeAbility.getInstance()).setText("")); - this.setTriggerPhrase("Whenever you attack a player, "); - this.addTarget(new TargetPermanent(filter)); - } - - private OrdruunMentorTriggeredAbility(final OrdruunMentorTriggeredAbility ability) { - super(ability); - } +enum OrdruunMentorPredicate implements ObjectSourcePlayerPredicate { + instance; @Override - public OrdruunMentorTriggeredAbility copy() { - return new OrdruunMentorTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DEFENDER_ATTACKED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (!isControlledBy(event.getPlayerId()) || game.getPlayer(event.getTargetId()) == null) { - return false; - } - this.getEffects().setValue("playerAttacked", event.getTargetId()); - return true; + public boolean apply(ObjectSourcePlayer input, Game game) { + return CardUtil.getEffectValueFromAbility(input.getSource(), "playerAttacked", UUID.class) + .filter(uuid -> uuid.equals(game.getCombat().getDefenderId(input.getObject().getId()))) + .isPresent(); } } diff --git a/Mage.Sets/src/mage/cards/o/OrneryDilophosaur.java b/Mage.Sets/src/mage/cards/o/OrneryDilophosaur.java index fce5c2b72cf..f56f5f3f092 100644 --- a/Mage.Sets/src/mage/cards/o/OrneryDilophosaur.java +++ b/Mage.Sets/src/mage/cards/o/OrneryDilophosaur.java @@ -3,7 +3,6 @@ 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; @@ -31,12 +30,8 @@ public final class OrneryDilophosaur extends CardImpl { 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)); + this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect(2, 2, Duration.EndOfTurn)) + .withInterveningIf(FerociousCondition.instance).addHint(FerociousHint.instance)); } private OrneryDilophosaur(final OrneryDilophosaur card) { diff --git a/Mage.Sets/src/mage/cards/o/Ornitharch.java b/Mage.Sets/src/mage/cards/o/Ornitharch.java index b23b8a2f31a..f620a3def22 100644 --- a/Mage.Sets/src/mage/cards/o/Ornitharch.java +++ b/Mage.Sets/src/mage/cards/o/Ornitharch.java @@ -1,12 +1,8 @@ - package mage.cards.o; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TributeNotPaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.TributeAbility; @@ -16,14 +12,15 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.game.permanent.token.BirdToken; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class Ornitharch extends CardImpl { public Ornitharch(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); this.subtype.add(SubType.ARCHON); this.power = new MageInt(3); @@ -31,12 +28,13 @@ public final class Ornitharch extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); + // Tribute 2 this.addAbility(new TributeAbility(2)); + // When Ornitharch enters the battlefield, if tribute wasn't paid, create two 1/1 white Bird creature tokens with flying. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new BirdToken(), 2), false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TributeNotPaidCondition.instance, - "When {this} enters, if tribute wasn't paid, create two 1/1 white Bird creature tokens with flying.")); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new BirdToken(), 2)) + .withInterveningIf(TributeNotPaidCondition.instance)); } private Ornitharch(final Ornitharch card) { diff --git a/Mage.Sets/src/mage/cards/o/OrvarTheAllForm.java b/Mage.Sets/src/mage/cards/o/OrvarTheAllForm.java index 607d71b74cc..160f051cb85 100644 --- a/Mage.Sets/src/mage/cards/o/OrvarTheAllForm.java +++ b/Mage.Sets/src/mage/cards/o/OrvarTheAllForm.java @@ -8,7 +8,6 @@ import mage.abilities.Mode; import mage.abilities.common.DiscardedByOpponentTriggeredAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenCopyTargetEffect; import mage.abilities.keyword.ChangelingAbility; @@ -54,17 +53,11 @@ public final class OrvarTheAllForm extends CardImpl { this.addAbility(new ChangelingAbility()); // Whenever you cast an instant or sorcery spell, if it targets one or more other permanents you control, create a token that's a copy of one of those permanents. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new SpellCastControllerTriggeredAbility( - new OrvarTheAllFormEffect(), - StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY, - false, SetTargetPointer.SPELL - ), - OrvarTheAllFormCondition.instance, - "Whenever you cast an instant or sorcery spell, " - + "if it targets one or more other permanents you control, " - + "create a token that's a copy of one of those permanents." - )); + this.addAbility(new SpellCastControllerTriggeredAbility( + new OrvarTheAllFormEffect(), + StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, + false, SetTargetPointer.SPELL + ).withInterveningIf(OrvarTheAllFormCondition.instance)); // When a spell or ability an opponent controls causes you to discard this card, create a token that's a copy of target permanent. Ability ability = new DiscardedByOpponentTriggeredAbility(new CreateTokenCopyTargetEffect()); @@ -109,12 +102,18 @@ enum OrvarTheAllFormCondition implements Condition { .map(Controllable::getControllerId) .anyMatch(source::isControlledBy); } + + @Override + public String toString() { + return "it targets one or more other permanents you control"; + } } class OrvarTheAllFormEffect extends OneShotEffect { OrvarTheAllFormEffect() { super(Outcome.Benefit); + staticText = "create a token that's a copy of one of those permanents."; } private OrvarTheAllFormEffect(final OrvarTheAllFormEffect effect) { diff --git a/Mage.Sets/src/mage/cards/o/OrzhovAdvokist.java b/Mage.Sets/src/mage/cards/o/OrzhovAdvokist.java index 378703e74f0..b971ad23eed 100644 --- a/Mage.Sets/src/mage/cards/o/OrzhovAdvokist.java +++ b/Mage.Sets/src/mage/cards/o/OrzhovAdvokist.java @@ -3,17 +3,16 @@ package mage.cards.o; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.combat.CantAttackYouAllEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.counters.CounterType; -import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; @@ -24,11 +23,10 @@ import mage.target.common.TargetControlledCreaturePermanent; import java.util.ArrayList; import java.util.List; -import java.util.Objects; +import java.util.Optional; import java.util.UUID; /** - * * @author LevelX2 */ public final class OrzhovAdvokist extends CardImpl { @@ -75,37 +73,42 @@ class OrzhovAdvokistEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - List players = new ArrayList<>(); - List creatures = new ArrayList<>(); - for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { - Player player = game.getPlayer(playerId); - if (player != null) { - if (player.chooseUse(outcome, "Put two +1/+1 counters on a creature you control?", source, game)) { - Target target = new TargetControlledCreaturePermanent(new FilterControlledCreaturePermanent("a creature you control (to add two +1/+1 counters on it)")); - if (player.choose(outcome, target, source, game)) { - creatures.add(target.getFirstTarget()); - players.add(player.getId()); - } - - } - } - } - for (UUID creatureId : creatures) { - Permanent creature = game.getPermanent(creatureId); - if (creature != null) { - creature.addCounters(CounterType.P1P1.createInstance(2), creature.getControllerId(), source, game); - } - } - for (UUID playerId : players) { - if (!Objects.equals(playerId, source.getControllerId())) { - FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(new ControllerIdPredicate(playerId)); - game.addEffect(new CantAttackYouAllEffect(Duration.UntilYourNextTurn, filter, true), source); - } - } - return true; + if (controller == null) { + return false; } - return false; + List players = new ArrayList<>(); + List creatures = new ArrayList<>(); + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player == null || !player.chooseUse(outcome, "Put two +1/+1 counters on a creature you control?", source, game)) { + continue; + } + Target target = new TargetControlledCreaturePermanent(0, 1); + target.withNotTarget(true); + target.withChooseHint("to add counters to"); + player.choose(outcome, target, source, game); + Optional.ofNullable(target) + .map(Target::getFirstTarget) + .map(game::getPermanent) + .ifPresent(permanent -> { + creatures.add(permanent.getId()); + players.add(player.getId()); + }); + } + for (UUID creatureId : creatures) { + Permanent creature = game.getPermanent(creatureId); + if (creature != null) { + creature.addCounters(CounterType.P1P1.createInstance(2), creature.getControllerId(), source, game); + } + } + for (UUID playerId : players) { + if (source.isControlledBy(playerId)) { + continue; + } + FilterCreaturePermanent filter = new FilterCreaturePermanent(); + filter.add(new ControllerIdPredicate(playerId)); + game.addEffect(new CantAttackYouAllEffect(Duration.UntilYourNextTurn, filter, true), source); + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/o/OsaiVultures.java b/Mage.Sets/src/mage/cards/o/OsaiVultures.java index 878f35c85c8..4a43fe7f757 100644 --- a/Mage.Sets/src/mage/cards/o/OsaiVultures.java +++ b/Mage.Sets/src/mage/cards/o/OsaiVultures.java @@ -1,47 +1,48 @@ - package mage.cards.o; -import java.util.UUID; import mage.MageInt; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.MorbidCondition; import mage.abilities.costs.common.RemoveCountersSourceCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.hint.common.MorbidHint; import mage.abilities.keyword.FlyingAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; 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.TargetController; -import mage.constants.Zone; import mage.counters.CounterType; +import java.util.UUID; + /** - * * @author LoneFox */ public final class OsaiVultures extends CardImpl { public OsaiVultures(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.BIRD); this.power = new MageInt(1); this.toughness = new MageInt(1); // Flying this.addAbility(FlyingAbility.getInstance()); + // At the beginning of each end step, if a creature died this turn, put a carrion counter on Osai Vultures. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfEndStepTriggeredAbility( - TargetController.ANY, new AddCountersSourceEffect(CounterType.CARRION.createInstance()), false), MorbidCondition.instance, - "At the beginning of each end step, if a creature died this turn, put a carrion counter on {this}.").addHint(MorbidHint.instance)); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.ANY, new AddCountersSourceEffect(CounterType.CARRION.createInstance()), false + ).withInterveningIf(MorbidCondition.instance).addHint(MorbidHint.instance)); + // Remove two carrion counters from Osai Vultures: Osai Vultures gets +1/+1 until end of turn. - this.addAbility(new SimpleActivatedAbility(new BoostSourceEffect(1, 1, Duration.EndOfTurn), - new RemoveCountersSourceCost(CounterType.CARRION.createInstance(2)))); + this.addAbility(new SimpleActivatedAbility( + new BoostSourceEffect(1, 1, Duration.EndOfTurn), + new RemoveCountersSourceCost(CounterType.CARRION.createInstance(2)) + )); } private OsaiVultures(final OsaiVultures card) { diff --git a/Mage.Sets/src/mage/cards/o/OtepecHuntmaster.java b/Mage.Sets/src/mage/cards/o/OtepecHuntmaster.java index 88824db9976..ce862ee9d13 100644 --- a/Mage.Sets/src/mage/cards/o/OtepecHuntmaster.java +++ b/Mage.Sets/src/mage/cards/o/OtepecHuntmaster.java @@ -18,6 +18,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -47,7 +48,7 @@ public final class OtepecHuntmaster extends CardImpl { // {T}: Target Dinosaur gains haste until end of turn. Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter2)); + ability.addTarget(new TargetPermanent(filter2)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/o/OutcasterTrailblazer.java b/Mage.Sets/src/mage/cards/o/OutcasterTrailblazer.java index a845a601fdb..8aadce60736 100644 --- a/Mage.Sets/src/mage/cards/o/OutcasterTrailblazer.java +++ b/Mage.Sets/src/mage/cards/o/OutcasterTrailblazer.java @@ -1,7 +1,7 @@ package mage.cards.o; import mage.MageInt; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.mana.AddManaOfAnyColorEffect; @@ -24,7 +24,7 @@ import java.util.UUID; public final class OutcasterTrailblazer extends CardImpl { private static final FilterPermanent filter - = new FilterControlledCreaturePermanent("another creature with power 4 or greater"); + = new FilterControlledCreaturePermanent("another creature you control with power 4 or greater"); static { filter.add(AnotherPredicate.instance); @@ -43,7 +43,7 @@ public final class OutcasterTrailblazer extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new AddManaOfAnyColorEffect())); // Whenever another creature with power 4 or greater you control enters, draw a card. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility(new DrawCardSourceControllerEffect(1), filter)); + this.addAbility(new EntersBattlefieldAllTriggeredAbility(new DrawCardSourceControllerEffect(1), filter)); // Plot {2}{G} this.addAbility(new PlotAbility("{2}{G}")); diff --git a/Mage.Sets/src/mage/cards/o/OuterRimSlaver.java b/Mage.Sets/src/mage/cards/o/OuterRimSlaver.java index 9e71e43fb55..167b552eac6 100644 --- a/Mage.Sets/src/mage/cards/o/OuterRimSlaver.java +++ b/Mage.Sets/src/mage/cards/o/OuterRimSlaver.java @@ -1,6 +1,5 @@ package mage.cards.o; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -13,10 +12,11 @@ import mage.constants.SubType; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.other.AnotherTargetPredicate; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author Styxo */ public final class OuterRimSlaver extends CardImpl { @@ -32,14 +32,10 @@ public final class OuterRimSlaver extends CardImpl { Ability ability = new EntersBattlefieldTriggeredAbility(new AddCountersTargetEffect(CounterType.BOUNTY.createInstance()) .setText("you may put a bounty counter on target creature"), true); ability.addEffect(new FightTargetsEffect().setText("If you do, another target creature fights that creature")); - TargetCreaturePermanent target = new TargetCreaturePermanent(new FilterCreaturePermanent("creature to put a bounty counter on it")); - target.setTargetTag(1); - ability.addTarget(target); + ability.addTarget(new TargetPermanent(new FilterCreaturePermanent("creature to put a bounty counter on it")).setTargetTag(1)); FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature to fight that creature that gets the bounty counter"); filter.add(new AnotherTargetPredicate(2)); - TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter); - target2.setTargetTag(2); - ability.addTarget(target2); + ability.addTarget(new TargetPermanent(filter).setTargetTag(2)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/o/Outmaneuver.java b/Mage.Sets/src/mage/cards/o/Outmaneuver.java index d08a604e652..8278746a83b 100644 --- a/Mage.Sets/src/mage/cards/o/Outmaneuver.java +++ b/Mage.Sets/src/mage/cards/o/Outmaneuver.java @@ -11,6 +11,7 @@ import mage.constants.Outcome; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.BlockedPredicate; import mage.game.Game; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetadjustment.XTargetsCountAdjuster; @@ -31,7 +32,7 @@ public final class Outmaneuver extends CardImpl { // X target blocked creatures assign their combat damage this turn as though they weren't blocked. this.getSpellAbility().addEffect(new OutmaneuverEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().setTargetAdjuster(new XTargetsCountAdjuster()); } diff --git a/Mage.Sets/src/mage/cards/o/OversoldCemetery.java b/Mage.Sets/src/mage/cards/o/OversoldCemetery.java index e913ac234ab..b3af14b9f83 100644 --- a/Mage.Sets/src/mage/cards/o/OversoldCemetery.java +++ b/Mage.Sets/src/mage/cards/o/OversoldCemetery.java @@ -1,31 +1,34 @@ package mage.cards.o; -import java.util.UUID; -import mage.abilities.TriggeredAbility; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.Ability; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInControllerGraveyardCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; import mage.target.common.TargetCardInGraveyard; +import java.util.UUID; + /** - * * @author fireshoes */ public final class OversoldCemetery extends CardImpl { + private static final Condition condition = new CardsInControllerGraveyardCondition(4, StaticFilters.FILTER_CARD_CREATURES); + public OversoldCemetery(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}"); // At the beginning of your upkeep, if you have four or more creature cards in your graveyard, you may return target creature card from your graveyard to your hand. - TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect(), true); + Ability ability = new BeginningOfUpkeepTriggeredAbility( + new ReturnFromGraveyardToHandTargetEffect(), true + ).withInterveningIf(condition); ability.addTarget(new TargetCardInGraveyard(StaticFilters.FILTER_CARD_CREATURE)); - CardsInControllerGraveyardCondition condition = new CardsInControllerGraveyardCondition(4, StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, condition, "At the beginning of your upkeep, if you have four or more creature cards in your graveyard, you may return target creature card from your graveyard to your hand.")); + this.addAbility(ability); } private OversoldCemetery(final OversoldCemetery card) { diff --git a/Mage.Sets/src/mage/cards/p/PackHunt.java b/Mage.Sets/src/mage/cards/p/PackHunt.java index f4622fc58ee..020e8a3ad73 100644 --- a/Mage.Sets/src/mage/cards/p/PackHunt.java +++ b/Mage.Sets/src/mage/cards/p/PackHunt.java @@ -45,7 +45,8 @@ class PackHuntEffect extends OneShotEffect { PackHuntEffect() { super(Outcome.Benefit); - this.staticText = "Search your library for up to three cards with the same name as target creature, reveal them, and put them into your hand. Then shuffle"; + this.staticText = "Search your library for up to three cards with the same name as target creature, " + + "reveal them, put them into your hand, then shuffle"; } private PackHuntEffect(final PackHuntEffect effect) { @@ -60,6 +61,9 @@ class PackHuntEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent == null) { + return false; + } FilterCard filter = new FilterPermanentCard(); filter.add(new NamePredicate(permanent.getName())); return new SearchLibraryPutInHandEffect(new TargetCardInLibrary(0,3, filter), true).apply(game, source); diff --git a/Mage.Sets/src/mage/cards/p/PacksongPup.java b/Mage.Sets/src/mage/cards/p/PacksongPup.java index cdb22dbfbfd..81e5d8ab0db 100644 --- a/Mage.Sets/src/mage/cards/p/PacksongPup.java +++ b/Mage.Sets/src/mage/cards/p/PacksongPup.java @@ -1,16 +1,15 @@ package mage.cards.p; import mage.MageInt; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.SourcePermanentPowerValue; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.hint.ConditionHint; import mage.abilities.hint.Hint; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -28,7 +27,7 @@ import java.util.UUID; */ public final class PacksongPup extends CardImpl { - private static final FilterPermanent filter = new FilterControlledPermanent(); + private static final FilterPermanent filter = new FilterControlledPermanent("you control another Wolf or Werewolf"); static { filter.add(AnotherPredicate.instance); @@ -39,7 +38,7 @@ public final class PacksongPup extends CardImpl { } private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); - private static final Hint hint = new ConditionHint(condition, "You control another Wolf or Werewolf"); + private static final Hint hint = new ConditionHint(condition); public PacksongPup(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); @@ -49,15 +48,14 @@ public final class PacksongPup extends CardImpl { this.toughness = new MageInt(1); // At the beginning of combat on your turn, if you control another Wolf or Werewolf, put a +1/+1 counter on Packsong Pup. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility( - new AddCountersSourceEffect(CounterType.P1P1.createInstance()) - ), condition, "At the beginning of combat on your turn," + - " if you control another Wolf or Werewolf, put a +1/+1 counter on {this}" - ).addHint(hint)); + this.addAbility(new BeginningOfCombatTriggeredAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance()) + ).withInterveningIf(condition).addHint(hint)); // When Packsong Pup dies, you gain life equal to its power. - this.addAbility(new DiesSourceTriggeredAbility(new GainLifeEffect(SourcePermanentPowerValue.NOT_NEGATIVE).setText("you gain life equal to its power"))); + this.addAbility(new DiesSourceTriggeredAbility( + new GainLifeEffect(SourcePermanentPowerValue.NOT_NEGATIVE).setText("you gain life equal to its power") + )); } private PacksongPup(final PacksongPup card) { diff --git a/Mage.Sets/src/mage/cards/p/PalaceJailer.java b/Mage.Sets/src/mage/cards/p/PalaceJailer.java index 22d324f9f2f..541d407572a 100644 --- a/Mage.Sets/src/mage/cards/p/PalaceJailer.java +++ b/Mage.Sets/src/mage/cards/p/PalaceJailer.java @@ -25,9 +25,12 @@ import mage.game.ExileZone; import mage.game.Game; import mage.game.events.GameEvent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.util.CardUtil; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -47,7 +50,7 @@ public final class PalaceJailer extends CardImpl { // When Palace Jailer enters the battlefield, exile target creature an opponent controls until an opponent becomes the monarch. (That creature returns under its owner's control.) Ability ability = new EntersBattlefieldTriggeredAbility(new PalaceJailerExileEffect()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnOpponentBecomesMonarchReturnExiledToBattlefieldAbility())); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/p/PaladinOfAtonement.java b/Mage.Sets/src/mage/cards/p/PaladinOfAtonement.java index c28eb82f0cc..df6715b1f03 100644 --- a/Mage.Sets/src/mage/cards/p/PaladinOfAtonement.java +++ b/Mage.Sets/src/mage/cards/p/PaladinOfAtonement.java @@ -1,15 +1,12 @@ - package mage.cards.p; -import java.util.UUID; import mage.MageInt; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.condition.common.LiveLostLastTurnCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.SourcePermanentToughnessValue; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -17,8 +14,9 @@ import mage.constants.SubType; import mage.constants.TargetController; import mage.counters.CounterType; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class PaladinOfAtonement extends CardImpl { @@ -32,14 +30,14 @@ public final class PaladinOfAtonement extends CardImpl { this.toughness = new MageInt(1); // At the beginning of each upkeep, if you lost life last turn, put a +1/+1 counter on Paladin of Atonement. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(TargetController.ANY, new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false), - LiveLostLastTurnCondition.instance, - "At the beginning of each upkeep, if you lost life last turn, put a +1/+1 counter on {this}")); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + TargetController.ANY, new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false + ).withInterveningIf(LiveLostLastTurnCondition.instance)); // When Paladin of Atonement dies, you gain life equal to it's toughness. - this.addAbility(new DiesSourceTriggeredAbility(new GainLifeEffect(SourcePermanentToughnessValue.instance, - "you gain life equal to its toughness"))); + this.addAbility(new DiesSourceTriggeredAbility(new GainLifeEffect( + SourcePermanentToughnessValue.instance, "you gain life equal to its toughness" + ))); } private PaladinOfAtonement(final PaladinOfAtonement card) { diff --git a/Mage.Sets/src/mage/cards/p/PalanisHatcher.java b/Mage.Sets/src/mage/cards/p/PalanisHatcher.java index cd85c033cd5..f454171794c 100644 --- a/Mage.Sets/src/mage/cards/p/PalanisHatcher.java +++ b/Mage.Sets/src/mage/cards/p/PalanisHatcher.java @@ -2,15 +2,15 @@ package mage.cards.p; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.SacrificeControllerEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.keyword.HasteAbility; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -29,7 +29,10 @@ import java.util.UUID; public final class PalanisHatcher extends CardImpl { private static final FilterPermanent filter = new FilterPermanent(SubType.DINOSAUR, "Dinosaurs"); - private static final FilterControlledPermanent filterEgg = new FilterControlledPermanent(SubType.EGG, "egg"); + private static final FilterPermanent filterEgg = new FilterControlledPermanent(SubType.EGG, "an Egg"); + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPermanent(SubType.EGG, "you control one or more Eggs") + ); public PalanisHatcher(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{G}"); @@ -39,26 +42,18 @@ public final class PalanisHatcher extends CardImpl { this.toughness = new MageInt(3); // Other Dinosaurs you control have haste. - this.addAbility(new SimpleStaticAbility( - new GainAbilityControlledEffect( - HasteAbility.getInstance(), - Duration.WhileOnBattlefield, - filter, true - ) - )); + this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect( + HasteAbility.getInstance(), Duration.WhileOnBattlefield, filter, true + ))); // When Palani's Hatcher enters the battlefield, create two 0/1 green Dinosaur Egg creature tokens. this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new DinosaurEggToken(), 2))); // At the beginning of combat on your turn, if you control one or more Eggs, sacrifice an Egg, then create a 3/3 green Dinosaur creature token. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility( - new SacrificeControllerEffect(filterEgg, 1, "") - ), new PermanentsOnTheBattlefieldCondition(filterEgg), - "At the beginning of combat on your turn, if you control one or more Eggs, " - + "sacrifice an Egg, then create a 3/3 green Dinosaur creature token." - ); - ability.addEffect(new CreateTokenEffect(new DinosaurVanillaToken())); + Ability ability = new BeginningOfCombatTriggeredAbility( + new SacrificeControllerEffect(filterEgg, 1, "") + ).withInterveningIf(condition); + ability.addEffect(new CreateTokenEffect(new DinosaurVanillaToken()).concatBy(", then")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/p/Paleoloth.java b/Mage.Sets/src/mage/cards/p/Paleoloth.java index e184868b234..891fbd05b65 100644 --- a/Mage.Sets/src/mage/cards/p/Paleoloth.java +++ b/Mage.Sets/src/mage/cards/p/Paleoloth.java @@ -1,37 +1,35 @@ package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; 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.StaticFilters; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.PowerPredicate; +import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.predicate.mageobject.PowerPredicate; import mage.target.common.TargetCardInYourGraveyard; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class Paleoloth extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature with power 5 or greater"); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("another creature you control with power 5 or greater"); static { filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 4)); filter.add(AnotherPredicate.instance); } - private static final String rule = "Whenever another creature with power 5 or greater you control enters, you may return target creature card from your graveyard to your hand."; - public Paleoloth(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}{G}"); this.subtype.add(SubType.BEAST); @@ -40,10 +38,11 @@ public final class Paleoloth extends CardImpl { this.toughness = new MageInt(5); // Whenever another creature with power 5 or greater you control enters, you may return target creature card from your graveyard to your hand. - Ability ability = new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new ReturnFromGraveyardToHandTargetEffect(), filter, true); + Ability ability = new EntersBattlefieldAllTriggeredAbility( + new ReturnFromGraveyardToHandTargetEffect(), filter, true + ); ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE)); this.addAbility(ability); - } private Paleoloth(final Paleoloth card) { diff --git a/Mage.Sets/src/mage/cards/p/PangTongYoungPhoenix.java b/Mage.Sets/src/mage/cards/p/PangTongYoungPhoenix.java index 608693b2ec4..4fa4d5274ee 100644 --- a/Mage.Sets/src/mage/cards/p/PangTongYoungPhoenix.java +++ b/Mage.Sets/src/mage/cards/p/PangTongYoungPhoenix.java @@ -1,7 +1,5 @@ - package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; @@ -12,19 +10,18 @@ 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.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class PangTongYoungPhoenix extends CardImpl { public PangTongYoungPhoenix(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{W}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.ADVISOR); @@ -32,8 +29,10 @@ public final class PangTongYoungPhoenix extends CardImpl { this.toughness = new MageInt(2); // {tap}: Target creature gets +0/+2 until end of turn. Activate this ability only during your turn, before attackers are declared. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new BoostTargetEffect(0, 2, Duration.EndOfTurn), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new BoostTargetEffect(0, 2), new TapSourceCost(), + MyTurnBeforeAttackersDeclaredCondition.instance + ); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/p/ParagonOfEternalWilds.java b/Mage.Sets/src/mage/cards/p/ParagonOfEternalWilds.java index f7f6694dad8..a049ed9bf0d 100644 --- a/Mage.Sets/src/mage/cards/p/ParagonOfEternalWilds.java +++ b/Mage.Sets/src/mage/cards/p/ParagonOfEternalWilds.java @@ -1,7 +1,5 @@ - package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; import mage.abilities.Ability; @@ -15,34 +13,34 @@ 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.TargetController; -import mage.constants.Zone; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.mageobject.AnotherPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class ParagonOfEternalWilds extends CardImpl { - + private static final FilterCreaturePermanent filterGreen = new FilterCreaturePermanent("green creatures you control"); private static final FilterControlledCreaturePermanent filterGreen2 = new FilterControlledCreaturePermanent("another target green creature you control"); static { filterGreen.add(new ColorPredicate(ObjectColor.GREEN)); filterGreen.add(TargetController.YOU.getControllerPredicate()); - filterGreen2.add(new ColorPredicate(ObjectColor.GREEN)); + filterGreen2.add(new ColorPredicate(ObjectColor.GREEN)); filterGreen2.add(AnotherPredicate.instance); } - + public ParagonOfEternalWilds(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.HUMAN); this.subtype.add(SubType.DRUID); @@ -51,10 +49,11 @@ public final class ParagonOfEternalWilds extends CardImpl { // Other green creatures you control get +1/+1. this.addAbility(new SimpleStaticAbility(new BoostAllEffect(1, 1, Duration.WhileOnBattlefield, filterGreen, true))); + // {G}, {t}: Another target green creature you control gains trample until end of turn. - Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(TrampleAbility.getInstance(),Duration.EndOfTurn), new ManaCostsImpl<>("{G}")); + Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{G}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetControlledCreaturePermanent(filterGreen2)); + ability.addTarget(new TargetPermanent(filterGreen2)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/p/ParagonOfFierceDefiance.java b/Mage.Sets/src/mage/cards/p/ParagonOfFierceDefiance.java index cae821f9fbc..51adc82758a 100644 --- a/Mage.Sets/src/mage/cards/p/ParagonOfFierceDefiance.java +++ b/Mage.Sets/src/mage/cards/p/ParagonOfFierceDefiance.java @@ -1,7 +1,5 @@ - package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; import mage.abilities.Ability; @@ -15,32 +13,32 @@ import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.mageobject.AnotherPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author Quercitron */ public final class ParagonOfFierceDefiance extends CardImpl { private static final FilterCreaturePermanent filterCreatures = new FilterCreaturePermanent("red creatures"); private static final FilterControlledCreaturePermanent filterCreature = new FilterControlledCreaturePermanent("another target red creature you control"); - + static { filterCreatures.add(new ColorPredicate(ObjectColor.RED)); filterCreature.add(AnotherPredicate.instance); filterCreature.add(new ColorPredicate(ObjectColor.RED)); } - + public ParagonOfFierceDefiance(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.HUMAN); this.subtype.add(SubType.WARRIOR); @@ -49,11 +47,11 @@ public final class ParagonOfFierceDefiance extends CardImpl { // Other red creatures you control get +1/+1. this.addAbility(new SimpleStaticAbility(new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield, filterCreatures, true))); - + // {R}, {T}: Another target red creature you control gains haste until end of turn. Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{R}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetControlledCreaturePermanent(filterCreature)); + ability.addTarget(new TargetPermanent(filterCreature)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/p/ParagonOfGatheringMists.java b/Mage.Sets/src/mage/cards/p/ParagonOfGatheringMists.java index 24f337a3faa..1a45a3ca9ac 100644 --- a/Mage.Sets/src/mage/cards/p/ParagonOfGatheringMists.java +++ b/Mage.Sets/src/mage/cards/p/ParagonOfGatheringMists.java @@ -1,7 +1,5 @@ - package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; import mage.abilities.Ability; @@ -9,40 +7,39 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; 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.SubType; import mage.constants.Duration; -import mage.constants.TargetController; -import mage.constants.Zone; +import mage.constants.SubType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.mageobject.AnotherPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class ParagonOfGatheringMists extends CardImpl { - private static final FilterCreaturePermanent filterBlue = new FilterCreaturePermanent("blue creatures you control"); + private static final FilterPermanent filterBlue = new FilterCreaturePermanent("blue creatures"); private static final FilterControlledCreaturePermanent filterBlue2 = new FilterControlledCreaturePermanent("another target blue creature you control"); static { filterBlue.add(new ColorPredicate(ObjectColor.BLUE)); - filterBlue.add(TargetController.YOU.getControllerPredicate()); filterBlue2.add(new ColorPredicate(ObjectColor.BLUE)); filterBlue2.add(AnotherPredicate.instance); } public ParagonOfGatheringMists(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WIZARD); @@ -50,12 +47,16 @@ public final class ParagonOfGatheringMists extends CardImpl { this.toughness = new MageInt(2); // Other blue creatures you control get +1/+1. - this.addAbility(new SimpleStaticAbility(new BoostAllEffect(1, 1, Duration.WhileOnBattlefield, filterBlue, true))); + this.addAbility(new SimpleStaticAbility(new BoostControlledEffect( + 1, 1, Duration.WhileOnBattlefield, filterBlue, true + ))); // {U}, {T}: Another target blue creature you control gains flying until end of turn. - Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(FlyingAbility.getInstance(),Duration.EndOfTurn), new ManaCostsImpl<>("{U}")); + Ability ability = new SimpleActivatedAbility( + new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{U}") + ); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetControlledCreaturePermanent(filterBlue2)); + ability.addTarget(new TargetPermanent(filterBlue2)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/p/ParagonOfNewDawns.java b/Mage.Sets/src/mage/cards/p/ParagonOfNewDawns.java index 388b30f9e13..06fac2cd3a1 100644 --- a/Mage.Sets/src/mage/cards/p/ParagonOfNewDawns.java +++ b/Mage.Sets/src/mage/cards/p/ParagonOfNewDawns.java @@ -22,6 +22,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -54,7 +55,7 @@ public final class ParagonOfNewDawns extends CardImpl { // {W}, {T}: Another target white creature you control gains vigilance until end of turn. Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(VigilanceAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{W}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter2)); + ability.addTarget(new TargetPermanent(filter2)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/p/ParagonOfOpenGraves.java b/Mage.Sets/src/mage/cards/p/ParagonOfOpenGraves.java index 6be69435b21..1be1d60379b 100644 --- a/Mage.Sets/src/mage/cards/p/ParagonOfOpenGraves.java +++ b/Mage.Sets/src/mage/cards/p/ParagonOfOpenGraves.java @@ -1,7 +1,5 @@ - package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; import mage.abilities.Ability; @@ -15,22 +13,23 @@ import mage.abilities.keyword.DeathtouchAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.mageobject.AnotherPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class ParagonOfOpenGraves extends CardImpl { - private static final FilterCreaturePermanent filterCreatures = new FilterCreaturePermanent("black creatures"); + private static final FilterPermanent filterCreatures = new FilterCreaturePermanent("black creatures"); private static final FilterControlledCreaturePermanent filterCreature = new FilterControlledCreaturePermanent("another target black creature you control"); static { @@ -40,7 +39,7 @@ public final class ParagonOfOpenGraves extends CardImpl { } public ParagonOfOpenGraves(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.SKELETON); this.subtype.add(SubType.WARRIOR); @@ -48,12 +47,16 @@ public final class ParagonOfOpenGraves extends CardImpl { this.toughness = new MageInt(2); // Other black creatures you control get +1/+1. - this.addAbility(new SimpleStaticAbility(new BoostControlledEffect(1, 1, Duration.WhileOnBattlefield, filterCreatures, true))); + this.addAbility(new SimpleStaticAbility(new BoostControlledEffect( + 1, 1, Duration.WhileOnBattlefield, filterCreatures, true + ))); // {2}{B}, {T}: Another target black creature you control gains deathtouch until end of turn. - Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(DeathtouchAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{2}{B}")); + Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect( + DeathtouchAbility.getInstance(), Duration.EndOfTurn + ), new ManaCostsImpl<>("{2}{B}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetControlledCreaturePermanent(filterCreature)); + ability.addTarget(new TargetPermanent(filterCreature)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/p/Parch.java b/Mage.Sets/src/mage/cards/p/Parch.java index ce4752cb4e9..5e71aa7ebcb 100644 --- a/Mage.Sets/src/mage/cards/p/Parch.java +++ b/Mage.Sets/src/mage/cards/p/Parch.java @@ -10,6 +10,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetAnyTarget; import mage.target.common.TargetCreaturePermanent; @@ -33,7 +34,7 @@ public final class Parch extends CardImpl { this.getSpellAbility().addEffect(new DamageTargetEffect(2)); this.getSpellAbility().addTarget(new TargetAnyTarget()); Mode mode = new Mode(new DamageTargetEffect(4)); - mode.addTarget(new TargetCreaturePermanent(filter)); + mode.addTarget(new TargetPermanent(filter)); this.getSpellAbility().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/p/PardicDragon.java b/Mage.Sets/src/mage/cards/p/PardicDragon.java index 111136610b6..c8ebc65bd9f 100644 --- a/Mage.Sets/src/mage/cards/p/PardicDragon.java +++ b/Mage.Sets/src/mage/cards/p/PardicDragon.java @@ -65,7 +65,7 @@ class PardicDragonEffect extends OneShotEffect { PardicDragonEffect() { super(Outcome.Benefit); - this.staticText = "that player may put a time counter on {this}"; + this.staticText = "that player may put a time counter on this card"; } private PardicDragonEffect(final PardicDragonEffect effect) { diff --git a/Mage.Sets/src/mage/cards/p/Paroxysm.java b/Mage.Sets/src/mage/cards/p/Paroxysm.java index 970b2ea0334..d646d2186b6 100644 --- a/Mage.Sets/src/mage/cards/p/Paroxysm.java +++ b/Mage.Sets/src/mage/cards/p/Paroxysm.java @@ -55,9 +55,8 @@ class ParoxysmEffect extends OneShotEffect { ParoxysmEffect() { super(Outcome.BoostCreature); - this.staticText = "that player reveals the top card of their library. \n" - + "If that card is a land card, destroy that creature. \n" - + "Otherwise, it gets +3/+3 until end of turn."; + this.staticText = "that player reveals the top card of their library. If that card is a land card, "+ + "destroy that creature. Otherwise, it gets +3/+3 until end of turn."; } private ParoxysmEffect(final ParoxysmEffect effect) { diff --git a/Mage.Sets/src/mage/cards/p/PathmakerInitiate.java b/Mage.Sets/src/mage/cards/p/PathmakerInitiate.java index 83df1f90516..717473702cb 100644 --- a/Mage.Sets/src/mage/cards/p/PathmakerInitiate.java +++ b/Mage.Sets/src/mage/cards/p/PathmakerInitiate.java @@ -16,6 +16,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class PathmakerInitiate extends CardImpl { // {T}: Target creature with power 2 or less can't be blocked this turn. Ability ability = new SimpleActivatedAbility(new CantBeBlockedTargetEffect(Duration.EndOfTurn), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/p/PatronOfTheVein.java b/Mage.Sets/src/mage/cards/p/PatronOfTheVein.java index 7460ec51914..6c7cf6cdf17 100644 --- a/Mage.Sets/src/mage/cards/p/PatronOfTheVein.java +++ b/Mage.Sets/src/mage/cards/p/PatronOfTheVein.java @@ -26,9 +26,12 @@ import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author spjspj @@ -48,7 +51,7 @@ public final class PatronOfTheVein extends CardImpl { // When Patron of the Vein enters the battlefield, destroy target creature an opponent controls. Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), false); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); // Whenever a creature an opponent controls dies, exile it and put a +1/+1 counter on each Vampire you control. diff --git a/Mage.Sets/src/mage/cards/p/PaupersCage.java b/Mage.Sets/src/mage/cards/p/PaupersCage.java index 6995e5364bd..2c976f03dca 100644 --- a/Mage.Sets/src/mage/cards/p/PaupersCage.java +++ b/Mage.Sets/src/mage/cards/p/PaupersCage.java @@ -1,33 +1,31 @@ - package mage.cards.p; -import java.util.UUID; -import mage.abilities.TriggeredAbility; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInHandCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.TargetController; +import java.util.UUID; + /** - * * @author fireshoes */ public final class PaupersCage extends CardImpl { + private static final Condition condition = new CardsInHandCondition(ComparisonType.FEWER_THAN, 3, TargetController.ACTIVE); + public PaupersCage(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); // At the beginning of each opponent's upkeep, if that player has two or fewer cards in hand, Paupers' Cage deals 2 damage to that player. - TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility( - TargetController.OPPONENT, new DamageTargetEffect(2), false); - CardsInHandCondition condition = new CardsInHandCondition(ComparisonType.FEWER_THAN, 3, TargetController.ACTIVE); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, condition, - "At the beginning of each opponent's upkeep, if that player has two or fewer cards in hand, {this} deals 2 damage to that player.")); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + TargetController.OPPONENT, new DamageTargetEffect(2, true, "that player"), false + ).withInterveningIf(condition)); } private PaupersCage(final PaupersCage card) { diff --git a/Mage.Sets/src/mage/cards/p/PawpatchRecruit.java b/Mage.Sets/src/mage/cards/p/PawpatchRecruit.java index 68b1b9ac44e..b2ade10d334 100644 --- a/Mage.Sets/src/mage/cards/p/PawpatchRecruit.java +++ b/Mage.Sets/src/mage/cards/p/PawpatchRecruit.java @@ -1,18 +1,17 @@ package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.abilities.TriggeredAbility; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.common.counter.AddCountersTargetEffect; -import mage.constants.*; import mage.abilities.keyword.OffspringAbility; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; import mage.counters.CounterType; -import mage.filter.FilterPermanent; -import mage.filter.FilterStackObject; import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterControlledPermanent; @@ -23,7 +22,9 @@ import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.stack.StackObject; import mage.target.TargetPermanent; -import mage.util.CardUtil; +import mage.target.targetadjustment.DefineByTriggerTargetAdjuster; + +import java.util.UUID; /** * @@ -63,11 +64,9 @@ public final class PawpatchRecruit extends CardImpl { class PawpatchRecruitTriggeredAbility extends TriggeredAbilityImpl { - private final FilterPermanent filterTarget = StaticFilters.FILTER_CONTROLLED_A_CREATURE; - private final FilterStackObject filterStack = StaticFilters.FILTER_SPELL_OR_ABILITY_OPPONENTS; - public PawpatchRecruitTriggeredAbility() { super(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.P1P1.createInstance()), false); + this.setTargetAdjuster(DefineByTriggerTargetAdjuster.instance); } private PawpatchRecruitTriggeredAbility(final PawpatchRecruitTriggeredAbility ability) { @@ -93,11 +92,11 @@ class PawpatchRecruitTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); - if (permanent == null || !filterTarget.match(permanent, getControllerId(), this, game)) { + if (permanent == null || !StaticFilters.FILTER_CONTROLLED_A_CREATURE.match(permanent, getControllerId(), this, game)) { return false; } - StackObject targetingObject = CardUtil.findTargetingStackObject(this.getId().toString(), event, game); - if (targetingObject == null || !filterStack.match(targetingObject, getControllerId(), this, game)) { + StackObject targetingObject = game.findTargetingStackObject(this.getId().toString(), event); + if (targetingObject == null || !StaticFilters.FILTER_SPELL_OR_ABILITY_OPPONENTS.match(targetingObject, getControllerId(), this, game)) { return false; } this.getTargets().clear(); diff --git a/Mage.Sets/src/mage/cards/p/PearlspearCourier.java b/Mage.Sets/src/mage/cards/p/PearlspearCourier.java index 5936dee1d0f..b8a75b41b3e 100644 --- a/Mage.Sets/src/mage/cards/p/PearlspearCourier.java +++ b/Mage.Sets/src/mage/cards/p/PearlspearCourier.java @@ -20,6 +20,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -50,7 +51,7 @@ public final class PearlspearCourier extends CardImpl { ability.addEffect(new ConditionalContinuousEffect(new GainAbilityTargetEffect(VigilanceAbility.getInstance(), Duration.Custom), SourceTappedCondition.TAPPED,"and has vigilance for as long as {this} remains tapped")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/p/PeelFromReality.java b/Mage.Sets/src/mage/cards/p/PeelFromReality.java index 7d66b23ba79..075dab4e7f6 100644 --- a/Mage.Sets/src/mage/cards/p/PeelFromReality.java +++ b/Mage.Sets/src/mage/cards/p/PeelFromReality.java @@ -5,12 +5,15 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.EachTargetPointer; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author North */ @@ -22,7 +25,7 @@ public final class PeelFromReality extends CardImpl { // Return target creature you control and target creature you don't control to their owners' hands. this.getSpellAbility().addEffect(new ReturnToHandTargetEffect().setTargetPointer(new EachTargetPointer())); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); } private PeelFromReality(final PeelFromReality card) { diff --git a/Mage.Sets/src/mage/cards/p/Pendelhaven.java b/Mage.Sets/src/mage/cards/p/Pendelhaven.java index cd9b63cdcbe..0975b511791 100644 --- a/Mage.Sets/src/mage/cards/p/Pendelhaven.java +++ b/Mage.Sets/src/mage/cards/p/Pendelhaven.java @@ -17,6 +17,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; import mage.filter.predicate.mageobject.ToughnessPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,7 +39,7 @@ public final class Pendelhaven extends CardImpl { this.addAbility(new GreenManaAbility()); // {tap}: Target 1/1 creature gets +1/+2 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(1, 2, Duration.EndOfTurn), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/p/Pestilence.java b/Mage.Sets/src/mage/cards/p/Pestilence.java index 4ebedff43af..90adfe9ea6a 100644 --- a/Mage.Sets/src/mage/cards/p/Pestilence.java +++ b/Mage.Sets/src/mage/cards/p/Pestilence.java @@ -1,36 +1,37 @@ - package mage.cards.p; -import java.util.UUID; -import mage.abilities.TriggeredAbility; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.condition.common.CreatureCountCondition; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageEverythingEffect; import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.ComparisonType; import mage.constants.TargetController; -import mage.constants.Zone; -import mage.game.events.GameEvent; +import mage.filter.common.FilterCreaturePermanent; + +import java.util.UUID; /** - * * @author Backfir3 */ public final class Pestilence extends CardImpl { - private static final String ruleText = "At the beginning of the end step, if no creatures are on the battlefield, sacrifice {this}."; + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterCreaturePermanent("no creatures are on the battlefield"), ComparisonType.EQUAL_TO, 0 + ); public Pestilence(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 the end step, if no creatures are on the battlefield, sacrifice Pestilence. - TriggeredAbility triggered = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new SacrificeSourceEffect()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(triggered, new CreatureCountCondition(0, TargetController.ANY), ruleText)); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.NEXT, new SacrificeSourceEffect(), false, condition + )); // {B}: Pestilence deals 1 damage to each creature and each player. this.addAbility(new SimpleActivatedAbility(new DamageEverythingEffect(1), new ManaCostsImpl<>("{B}"))); diff --git a/Mage.Sets/src/mage/cards/p/PestilentCauldron.java b/Mage.Sets/src/mage/cards/p/PestilentCauldron.java index f5b6b65462b..1df624ed426 100644 --- a/Mage.Sets/src/mage/cards/p/PestilentCauldron.java +++ b/Mage.Sets/src/mage/cards/p/PestilentCauldron.java @@ -6,20 +6,16 @@ import mage.abilities.costs.common.DiscardCardCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.dynamicvalue.common.ControllerGainedLifeCount; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.*; import mage.cards.CardSetInfo; import mage.cards.ModalDoubleFacedCard; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.TargetController; import mage.filter.FilterCard; import mage.filter.StaticFilters; import mage.filter.predicate.Predicates; -import mage.game.Game; import mage.game.permanent.token.Pest11GainLifeToken; -import mage.players.Player; import mage.target.common.TargetCardInASingleGraveyard; import mage.target.common.TargetCardInYourGraveyard; import mage.watchers.common.PlayerGainedLifeWatcher; @@ -82,7 +78,7 @@ public final class PestilentCauldron extends ModalDoubleFacedCard { // Sorcery // Return up to two target creature, land, and/or planeswalker cards from your graveyard to your hand. Each player gains 4 life. Exile Restorative Burst. this.getRightHalfCard().getSpellAbility().addEffect(new ReturnFromGraveyardToHandTargetEffect()); - this.getRightHalfCard().getSpellAbility().addEffect(new RestorativeBurstEffect()); + this.getRightHalfCard().getSpellAbility().addEffect(new GainLifeAllEffect(4)); this.getRightHalfCard().getSpellAbility().addEffect(new ExileSpellEffect()); this.getRightHalfCard().getSpellAbility().addTarget(new TargetCardInYourGraveyard(0, 2, filter)); } @@ -96,31 +92,3 @@ public final class PestilentCauldron extends ModalDoubleFacedCard { return new PestilentCauldron(this); } } - -class RestorativeBurstEffect extends OneShotEffect { - - RestorativeBurstEffect() { - super(Outcome.GainLife); - staticText = "Each player gains 4 life."; - } - - private RestorativeBurstEffect(final RestorativeBurstEffect effect) { - super(effect); - } - - @Override - public RestorativeBurstEffect copy() { - return new RestorativeBurstEffect(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) { - player.gainLife(4, game, source); - } - } - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/p/PestsOfHonor.java b/Mage.Sets/src/mage/cards/p/PestsOfHonor.java index 9bc6f9bf106..f92da8d3c0c 100644 --- a/Mage.Sets/src/mage/cards/p/PestsOfHonor.java +++ b/Mage.Sets/src/mage/cards/p/PestsOfHonor.java @@ -1,10 +1,9 @@ package mage.cards.p; import mage.MageInt; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.condition.common.CelebrationCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AbilityWord; @@ -28,12 +27,11 @@ public final class PestsOfHonor extends CardImpl { this.toughness = new MageInt(2); // Celebration - At the beginning of combat on your turn, if two or more nonland permanents entered the battlefield under your control this turn, put a +1/+1 counter on Pests of Honor. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility( - new AddCountersSourceEffect(CounterType.P1P1.createInstance()) - ), CelebrationCondition.instance, "At the beginning of combat on your turn, if two or more " + - "nonland permanents entered the battlefield under your control this turn, put a +1/+1 counter on {this}." - ).addHint(CelebrationCondition.getHint()).setAbilityWord(AbilityWord.CELEBRATION), new PermanentsEnteredBattlefieldWatcher()); + this.addAbility(new BeginningOfCombatTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance())) + .withInterveningIf(CelebrationCondition.instance) + .addHint(CelebrationCondition.getHint()) + .setAbilityWord(AbilityWord.CELEBRATION), new PermanentsEnteredBattlefieldWatcher() + ); } private PestsOfHonor(final PestsOfHonor card) { diff --git a/Mage.Sets/src/mage/cards/p/PhageTheUntouchable.java b/Mage.Sets/src/mage/cards/p/PhageTheUntouchable.java index 25d3b5b1889..fe6bc438e97 100644 --- a/Mage.Sets/src/mage/cards/p/PhageTheUntouchable.java +++ b/Mage.Sets/src/mage/cards/p/PhageTheUntouchable.java @@ -1,14 +1,13 @@ package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.CastFromHandSourcePermanentCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.LoseGameSourceControllerEffect; import mage.abilities.effects.common.LoseGameTargetPlayerEffect; @@ -19,14 +18,17 @@ import mage.constants.SubType; import mage.constants.SuperType; import mage.watchers.common.CastFromHandWatcher; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class PhageTheUntouchable extends CardImpl { + private static final Condition condition = new InvertCondition(CastFromHandSourcePermanentCondition.instance, "you didn't cast it from your hand"); + public PhageTheUntouchable(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{B}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}{B}{B}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.AVATAR); this.subtype.add(SubType.MINION); @@ -35,11 +37,8 @@ public final class PhageTheUntouchable extends CardImpl { this.toughness = new MageInt(4); // 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(CastFromHandSourcePermanentCondition.instance), - "When {this} enters, if you didn't cast it from your hand, you lose the game" - ), new CastFromHandWatcher()); + this.addAbility(new EntersBattlefieldTriggeredAbility(new LoseGameSourceControllerEffect()) + .withInterveningIf(condition), new CastFromHandWatcher()); // Whenever Phage deals combat damage to a creature, destroy that creature. It can't be regenerated. this.addAbility(new DealsCombatDamageToACreatureTriggeredAbility(new DestroyTargetEffect(true), false, true)); diff --git a/Mage.Sets/src/mage/cards/p/PhantasmalMount.java b/Mage.Sets/src/mage/cards/p/PhantasmalMount.java index 886bc73d5f7..b09f34d1df7 100644 --- a/Mage.Sets/src/mage/cards/p/PhantasmalMount.java +++ b/Mage.Sets/src/mage/cards/p/PhantasmalMount.java @@ -1,6 +1,5 @@ package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; @@ -12,25 +11,21 @@ import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.SacrificeTargetEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; -import mage.constants.SubType; import mage.abilities.keyword.FlyingAbility; 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.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.ToughnessPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class PhantasmalMount extends CardImpl { @@ -54,9 +49,8 @@ public final class PhantasmalMount extends CardImpl { // {tap}: Target creature you control with toughness 2 or less gets +1/+1 and gains flying until end of turn. When Phantasmal Mount leaves the battlefield this turn, sacrifice that creature. When the creature leaves the battlefield this turn, sacrifice Phantasmal Mount. Ability activatedAbility = new SimpleActivatedAbility(new PhantasmalMountEffect(), new TapSourceCost()); - activatedAbility.addTarget(new TargetControlledCreaturePermanent(filter)); + activatedAbility.addTarget(new TargetPermanent(filter)); this.addAbility(activatedAbility); - } private PhantasmalMount(final PhantasmalMount card) { diff --git a/Mage.Sets/src/mage/cards/p/PhantomBlade.java b/Mage.Sets/src/mage/cards/p/PhantomBlade.java index 55f91727caa..1f79ccec1b5 100644 --- a/Mage.Sets/src/mage/cards/p/PhantomBlade.java +++ b/Mage.Sets/src/mage/cards/p/PhantomBlade.java @@ -16,8 +16,8 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.SecondTargetPointer; import java.util.UUID; @@ -37,7 +37,7 @@ public final class PhantomBlade extends CardImpl { ability.addTarget(new TargetControlledCreaturePermanent(0, 1).setTargetTag(1)); ability.addEffect(new DestroyTargetEffect().setTargetPointer(new SecondTargetPointer())); - ability.addTarget(new TargetCreaturePermanent(0, 1, StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2, false).setTargetTag(2)); + ability.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2).setTargetTag(2)); this.addAbility(ability); // Equipped creature gets +1/+1 and has menace. diff --git a/Mage.Sets/src/mage/cards/p/PharagaxGiant.java b/Mage.Sets/src/mage/cards/p/PharagaxGiant.java index 44f29cb312f..e92555a4cf1 100644 --- a/Mage.Sets/src/mage/cards/p/PharagaxGiant.java +++ b/Mage.Sets/src/mage/cards/p/PharagaxGiant.java @@ -1,12 +1,8 @@ - package mage.cards.p; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TributeNotPaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamagePlayersEffect; import mage.abilities.keyword.TributeAbility; import mage.cards.CardImpl; @@ -15,14 +11,15 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.TargetController; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class PharagaxGiant extends CardImpl { public PharagaxGiant(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}"); this.subtype.add(SubType.GIANT); this.power = new MageInt(3); @@ -30,10 +27,11 @@ public final class PharagaxGiant extends CardImpl { // Tribute 2 (As this creature enters the battlefield, an opponent of your choice may place two +1/+1 counters on it.) this.addAbility(new TributeAbility(2)); + // When Pharagax Giant enters the battlefield, if tribute wasn't paid, Pharagax Giant deals 5 damage to each opponent. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DamagePlayersEffect(5, TargetController.OPPONENT), false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TributeNotPaidCondition.instance, - "When {this} enters, if tribute wasn't paid, {this} deals 5 damage to each opponent.")); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new DamagePlayersEffect(5, TargetController.OPPONENT) + ).withInterveningIf(TributeNotPaidCondition.instance)); } private PharagaxGiant(final PharagaxGiant card) { diff --git a/Mage.Sets/src/mage/cards/p/PhyrexianBloodstock.java b/Mage.Sets/src/mage/cards/p/PhyrexianBloodstock.java index 5b9fe000e32..60bcea585e6 100644 --- a/Mage.Sets/src/mage/cards/p/PhyrexianBloodstock.java +++ b/Mage.Sets/src/mage/cards/p/PhyrexianBloodstock.java @@ -13,6 +13,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -36,7 +37,7 @@ public final class PhyrexianBloodstock extends CardImpl { // When Phyrexian Bloodstock leaves the battlefield, destroy target white creature. It can't be regenerated. Ability ability = new LeavesBattlefieldTriggeredAbility(new DestroyTargetEffect(true), false); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/p/PhyrexianDreadnought.java b/Mage.Sets/src/mage/cards/p/PhyrexianDreadnought.java index e82404b0646..e08c351495b 100644 --- a/Mage.Sets/src/mage/cards/p/PhyrexianDreadnought.java +++ b/Mage.Sets/src/mage/cards/p/PhyrexianDreadnought.java @@ -1,7 +1,6 @@ package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -12,16 +11,17 @@ 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.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class PhyrexianDreadnought extends CardImpl { @@ -36,6 +36,7 @@ public final class PhyrexianDreadnought extends CardImpl { // Trample this.addAbility(TrampleAbility.getInstance()); + // When Phyrexian Dreadnought enters the battlefield, sacrifice it unless you sacrifice any number of creatures with total power 12 or greater. this.addAbility(new EntersBattlefieldTriggeredAbility(new SacrificeSourceUnlessPaysEffect(new PhyrexianDreadnoughtSacrificeCost()))); @@ -56,7 +57,7 @@ class PhyrexianDreadnoughtSacrificeCost extends CostImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("any number of creatures with total power 12 or greater"); public PhyrexianDreadnoughtSacrificeCost() { - this.addTarget(new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, filter, true)); + this.addTarget(new TargetPermanent(0, Integer.MAX_VALUE, filter, true)); this.text = "sacrifice any number of creatures with total power 12 or greater"; } diff --git a/Mage.Sets/src/mage/cards/p/PhyrexianMissionary.java b/Mage.Sets/src/mage/cards/p/PhyrexianMissionary.java index 158258ae21b..2a44de0a472 100644 --- a/Mage.Sets/src/mage/cards/p/PhyrexianMissionary.java +++ b/Mage.Sets/src/mage/cards/p/PhyrexianMissionary.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; import mage.abilities.keyword.KickerAbility; import mage.abilities.keyword.LifelinkAbility; @@ -38,11 +37,7 @@ public final class PhyrexianMissionary extends CardImpl { this.addAbility(LifelinkAbility.getInstance()); // When Phyrexian Missionary enters the battlefield, if it was kicked, return target creature card from your graveyard to your hand. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect()), - KickedCondition.ONCE, "When {this} enters, if it was kicked, " + - "return target creature card from your graveyard to your hand." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect()).withInterveningIf(KickedCondition.ONCE); ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/p/PhyrexianSwarmlord.java b/Mage.Sets/src/mage/cards/p/PhyrexianSwarmlord.java index 81cf6a32190..93c72f8c086 100644 --- a/Mage.Sets/src/mage/cards/p/PhyrexianSwarmlord.java +++ b/Mage.Sets/src/mage/cards/p/PhyrexianSwarmlord.java @@ -1,27 +1,25 @@ - package mage.cards.p; -import java.util.UUID; import mage.MageInt; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.dynamicvalue.common.OpponentsPoisonCountersCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.InfectAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.game.events.GameEvent.EventType; import mage.game.permanent.token.InsectInfectToken; +import java.util.UUID; + /** - * * @author North */ public final class PhyrexianSwarmlord extends CardImpl { public PhyrexianSwarmlord(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}{G}"); this.subtype.add(SubType.PHYREXIAN); this.subtype.add(SubType.INSECT); this.subtype.add(SubType.HORROR); @@ -30,8 +28,9 @@ public final class PhyrexianSwarmlord extends CardImpl { this.toughness = new MageInt(4); this.addAbility(InfectAbility.getInstance()); - this.addAbility(new OnEventTriggeredAbility(EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", - new CreateTokenEffect(new InsectInfectToken(), OpponentsPoisonCountersCount.instance))); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new CreateTokenEffect(new InsectInfectToken(), OpponentsPoisonCountersCount.instance) + )); } private PhyrexianSwarmlord(final PhyrexianSwarmlord card) { @@ -43,4 +42,3 @@ public final class PhyrexianSwarmlord extends CardImpl { return new PhyrexianSwarmlord(this); } } - diff --git a/Mage.Sets/src/mage/cards/p/PhyrexianTotem.java b/Mage.Sets/src/mage/cards/p/PhyrexianTotem.java index f03f6d65846..381635784cb 100644 --- a/Mage.Sets/src/mage/cards/p/PhyrexianTotem.java +++ b/Mage.Sets/src/mage/cards/p/PhyrexianTotem.java @@ -41,7 +41,7 @@ public final class PhyrexianTotem extends CardImpl { // Whenever {this} is dealt damage, if it's a creature, sacrifice that many permanents. this.addAbility(new DealtDamageToSourceTriggeredAbility( new SacrificeControllerEffect(StaticFilters.FILTER_PERMANENTS, SavedDamageValue.MANY, ""), false - ).withInterveningIf(PhyrexianTotemCondition.instance)); + ).withInterveningIf(PhyrexianTotemCondition.instance).setTriggerPhrase("Whenever this permanent is dealt damage, ")); } private PhyrexianTotem(final PhyrexianTotem card) { diff --git a/Mage.Sets/src/mage/cards/p/PhyrexianWarhorse.java b/Mage.Sets/src/mage/cards/p/PhyrexianWarhorse.java index 9f9ef0e0be4..d393a074bd8 100644 --- a/Mage.Sets/src/mage/cards/p/PhyrexianWarhorse.java +++ b/Mage.Sets/src/mage/cards/p/PhyrexianWarhorse.java @@ -1,6 +1,5 @@ package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -8,20 +7,20 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.KickedCondition; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; -import mage.constants.Duration; -import mage.constants.SubType; import mage.abilities.keyword.KickerAbility; 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 mage.game.permanent.token.SoldierToken; +import java.util.UUID; + /** - * * @author weirddan455 */ public final class PhyrexianWarhorse extends CardImpl { @@ -38,16 +37,12 @@ public final class PhyrexianWarhorse extends CardImpl { this.addAbility(new KickerAbility("{W}")); // When Phyrexian Warhorse enters the battlefield, if it was kicked, create a 1/1 white Soldier creature token. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new SoldierToken())), - KickedCondition.ONCE, - "When {this} enters, if it was kicked, create a 1/1 white Soldier creature token." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new SoldierToken())) + .withInterveningIf(KickedCondition.ONCE)); // {1}, Sacrifice another creature: Phyrexian Warhorse gets +2/+1 until end of turn. Ability ability = new SimpleActivatedAbility( - new BoostSourceEffect(2, 1, Duration.EndOfTurn), - new GenericManaCost(1) + new BoostSourceEffect(2, 1, Duration.EndOfTurn), new GenericManaCost(1) ); ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/p/PiaNalaar.java b/Mage.Sets/src/mage/cards/p/PiaNalaar.java index 80fcf8fee88..89fc86b0178 100644 --- a/Mage.Sets/src/mage/cards/p/PiaNalaar.java +++ b/Mage.Sets/src/mage/cards/p/PiaNalaar.java @@ -22,9 +22,12 @@ import mage.constants.Zone; import mage.filter.StaticFilters; import mage.filter.common.FilterControlledArtifactPermanent; import mage.game.permanent.token.ThopterColorlessToken; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_ARTIFACT_CREATURE; + /** * * @author LevelX2 @@ -44,7 +47,7 @@ public final class PiaNalaar extends CardImpl { // {1}{R}: Target artifact creature gets +1/+0 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl<>("{1}{R}")); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_PERMANENT_ARTIFACT_CREATURE)); this.addAbility(ability); // {1}, Sacrifice an artifact: Target creature can't block this turn. diff --git a/Mage.Sets/src/mage/cards/p/PierceTheSky.java b/Mage.Sets/src/mage/cards/p/PierceTheSky.java index acb6c5ab383..d2d3a4d0273 100644 --- a/Mage.Sets/src/mage/cards/p/PierceTheSky.java +++ b/Mage.Sets/src/mage/cards/p/PierceTheSky.java @@ -9,6 +9,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -28,7 +29,7 @@ public final class PierceTheSky extends CardImpl { // Pierce the Sky deals 7 damage to target creature with flying. this.getSpellAbility().addEffect(new DamageTargetEffect(7)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private PierceTheSky(final PierceTheSky card) { diff --git a/Mage.Sets/src/mage/cards/p/PietyCharm.java b/Mage.Sets/src/mage/cards/p/PietyCharm.java index 83478fd8b6a..9c7b36ebc2c 100644 --- a/Mage.Sets/src/mage/cards/p/PietyCharm.java +++ b/Mage.Sets/src/mage/cards/p/PietyCharm.java @@ -42,7 +42,7 @@ public final class PietyCharm extends CardImpl { this.getSpellAbility().addTarget(new TargetPermanent(filter1)); // or target Soldier creature gets +2/+2 until end of turn Mode mode = new Mode(new BoostTargetEffect(2, 2, Duration.EndOfTurn)); - mode.addTarget(new TargetCreaturePermanent(filter2)); + mode.addTarget(new TargetPermanent(filter2)); this.getSpellAbility().addMode(mode); // or creatures you control gain vigilance until end of turn. mode = new Mode(new GainAbilityAllEffect(VigilanceAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURES)); diff --git a/Mage.Sets/src/mage/cards/p/PillarOfLight.java b/Mage.Sets/src/mage/cards/p/PillarOfLight.java index 343a9f80bb8..93cc7682274 100644 --- a/Mage.Sets/src/mage/cards/p/PillarOfLight.java +++ b/Mage.Sets/src/mage/cards/p/PillarOfLight.java @@ -9,6 +9,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ToughnessPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -29,7 +30,7 @@ public final class PillarOfLight extends CardImpl { // Exile target creature with toughness 4 or greater. this.getSpellAbility().addEffect(new ExileTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private PillarOfLight(final PillarOfLight card) { diff --git a/Mage.Sets/src/mage/cards/p/PinionFeast.java b/Mage.Sets/src/mage/cards/p/PinionFeast.java index 599e8d5104c..42080cdd626 100644 --- a/Mage.Sets/src/mage/cards/p/PinionFeast.java +++ b/Mage.Sets/src/mage/cards/p/PinionFeast.java @@ -10,6 +10,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -29,7 +30,7 @@ public final class PinionFeast extends CardImpl { // Destroy target creature with flying. Bolster 2. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new BolsterEffect(2)); } diff --git a/Mage.Sets/src/mage/cards/p/PistusStrike.java b/Mage.Sets/src/mage/cards/p/PistusStrike.java index 9e931a42e69..e446b0b2fc8 100644 --- a/Mage.Sets/src/mage/cards/p/PistusStrike.java +++ b/Mage.Sets/src/mage/cards/p/PistusStrike.java @@ -16,6 +16,7 @@ import mage.filter.predicate.mageobject.AbilityPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -33,7 +34,7 @@ public final class PistusStrike extends CardImpl { public PistusStrike(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{G}"); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); this.getSpellAbility().addEffect(new PoisonControllerTargetCreatureEffect()); } diff --git a/Mage.Sets/src/mage/cards/p/PitFight.java b/Mage.Sets/src/mage/cards/p/PitFight.java index a34dbd719f5..09dda5563fd 100644 --- a/Mage.Sets/src/mage/cards/p/PitFight.java +++ b/Mage.Sets/src/mage/cards/p/PitFight.java @@ -4,12 +4,13 @@ import mage.abilities.effects.common.FightTargetsEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2; + /** * @author LevelX2 */ @@ -20,13 +21,8 @@ public final class PitFight extends CardImpl { // Target creature you control fights another target creature. this.getSpellAbility().addEffect(new FightTargetsEffect()); - TargetControlledCreaturePermanent target = new TargetControlledCreaturePermanent(); - target.setTargetTag(1); - this.getSpellAbility().addTarget(target); - - TargetCreaturePermanent target2 = new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2); - target2.setTargetTag(2); - this.getSpellAbility().addTarget(target2); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent().setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_ANOTHER_CREATURE_TARGET_2).setTargetTag(2)); } private PitFight(final PitFight card) { diff --git a/Mage.Sets/src/mage/cards/p/PitKeeper.java b/Mage.Sets/src/mage/cards/p/PitKeeper.java index 8d31e68c894..d261db5bc13 100644 --- a/Mage.Sets/src/mage/cards/p/PitKeeper.java +++ b/Mage.Sets/src/mage/cards/p/PitKeeper.java @@ -1,28 +1,27 @@ package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.CardsInControllerGraveyardCondition; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; -import mage.game.Game; -import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; +import java.util.UUID; + /** - * * @author fireshoes */ public final class PitKeeper extends CardImpl { + private static final Condition condition = new CardsInControllerGraveyardCondition(4, StaticFilters.FILTER_CARD_CREATURES); + public PitKeeper(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); this.subtype.add(SubType.HUMAN); @@ -31,12 +30,9 @@ public final class PitKeeper extends CardImpl { this.toughness = new MageInt(1); // When Pit Keeper enters the battlefield, if you have four or more creature cards in your graveyard, you may return target creature card from your graveyard to your hand. - TriggeredAbility triggeredAbility = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true); - triggeredAbility.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - triggeredAbility, - new CreatureCardsInControllerGraveyardCondition(4), - "When {this} enters, if you have four or more creature cards in your graveyard, you may return target creature card from your graveyard to your hand.")); + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true).withInterveningIf(condition); + ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); + this.addAbility(ability); } private PitKeeper(final PitKeeper card) { @@ -48,21 +44,3 @@ public final class PitKeeper extends CardImpl { return new PitKeeper(this); } } - -class CreatureCardsInControllerGraveyardCondition implements Condition { - - private int value; - - public CreatureCardsInControllerGraveyardCondition(int value) { - this.value = value; - } - - @Override - public boolean apply(Game game, Ability source) { - Player p = game.getPlayer(source.getControllerId()); - if (p != null && p.getGraveyard().count(StaticFilters.FILTER_CARD_CREATURE, game) >= value) { - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/p/PlagueSpores.java b/Mage.Sets/src/mage/cards/p/PlagueSpores.java index 9e3162505ca..5b08bce7de3 100644 --- a/Mage.Sets/src/mage/cards/p/PlagueSpores.java +++ b/Mage.Sets/src/mage/cards/p/PlagueSpores.java @@ -6,10 +6,13 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetLandPermanent; import mage.target.targetpointer.EachTargetPointer; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author LoneFox @@ -22,7 +25,7 @@ public final class PlagueSpores extends CardImpl { // Destroy target nonblack creature and target land. They can't be regenerated. this.getSpellAbility().addEffect(new DestroyTargetEffect(true).setTargetPointer(new EachTargetPointer())); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.getSpellAbility().addTarget(new TargetLandPermanent()); } diff --git a/Mage.Sets/src/mage/cards/p/PlanarCollapse.java b/Mage.Sets/src/mage/cards/p/PlanarCollapse.java index 96bfb43e1fc..4228f56e032 100644 --- a/Mage.Sets/src/mage/cards/p/PlanarCollapse.java +++ b/Mage.Sets/src/mage/cards/p/PlanarCollapse.java @@ -1,34 +1,37 @@ - package mage.cards.p; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.TriggeredAbility; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.effects.common.DestroyAllEffect; import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.ComparisonType; import mage.filter.StaticFilters; -import mage.game.Game; +import mage.filter.common.FilterCreaturePermanent; + +import java.util.UUID; /** - * * @author Plopman */ public final class PlanarCollapse extends CardImpl { + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterCreaturePermanent("there are four or more creatures on the battlefield"), + ComparisonType.MORE_THAN, 3, false + ); + public PlanarCollapse(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}"); // At the beginning of your upkeep, if there are four or more creatures on the battlefield, sacrifice Planar Collapse and destroy all creatures. They can't be regenerated. - TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceEffect()); - ability.addEffect(new DestroyAllEffect(StaticFilters.FILTER_PERMANENT_CREATURE, true)); - PlanarCollapseCondition contition = new PlanarCollapseCondition(); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, contition, "At the beginning of your upkeep, if there are four or more creatures on the battlefield, sacrifice {this} and destroy all creatures. They can't be regenerated")); - + Ability ability = new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceEffect()).withInterveningIf(condition); + ability.addEffect(new DestroyAllEffect(StaticFilters.FILTER_PERMANENT_CREATURES, true).concatBy("and")); + this.addAbility(ability); } private PlanarCollapse(final PlanarCollapse card) { @@ -39,12 +42,4 @@ public final class PlanarCollapse extends CardImpl { public PlanarCollapse copy() { return new PlanarCollapse(this); } - - static class PlanarCollapseCondition implements mage.abilities.condition.Condition { - - @Override - public boolean apply(Game game, Ability source) { - return game.getBattlefield().count(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source, game) >= 4; - } - } } diff --git a/Mage.Sets/src/mage/cards/p/PlarggDeanOfChaos.java b/Mage.Sets/src/mage/cards/p/PlarggDeanOfChaos.java index 7d417ad9d62..2bd180fbff7 100644 --- a/Mage.Sets/src/mage/cards/p/PlarggDeanOfChaos.java +++ b/Mage.Sets/src/mage/cards/p/PlarggDeanOfChaos.java @@ -22,11 +22,12 @@ import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Controllable; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; +import java.util.Optional; import java.util.UUID; /** @@ -167,13 +168,16 @@ class AugustaDeanOfOrderEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - TargetControlledCreaturePermanent target = new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, filter, true); - Player controller = game.getPlayer(source.getControllerId()); - controller.chooseTarget(Outcome.Benefit, target, source, game); - target.getTargets().forEach(t -> { - Permanent permanent = game.getPermanent(t); - permanent.tap(source, game); - }); + TargetPermanent target = new TargetPermanent(0, Integer.MAX_VALUE, filter, true); + Optional.ofNullable(source) + .map(Controllable::getControllerId) + .map(game::getPlayer) + .ifPresent(player -> player.chooseTarget(Outcome.Benefit, target, source, game)); + for (UUID targetId : target.getTargets()) { + Optional.ofNullable(targetId) + .map(game::getPermanent) + .ifPresent(permanent -> permanent.tap(source, game)); + } return true; } diff --git a/Mage.Sets/src/mage/cards/p/PlasmaCaster.java b/Mage.Sets/src/mage/cards/p/PlasmaCaster.java index 994081709d2..897be0f883e 100644 --- a/Mage.Sets/src/mage/cards/p/PlasmaCaster.java +++ b/Mage.Sets/src/mage/cards/p/PlasmaCaster.java @@ -22,6 +22,7 @@ import mage.filter.predicate.ObjectSourcePlayer; import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.watchers.common.BlockingOrBlockedWatcher; @@ -60,7 +61,7 @@ public final class PlasmaCaster extends CardImpl { + "Otherwise, {this} deals 1 damage to it"), new PayEnergyCost(2) ); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // Equip {2} diff --git a/Mage.Sets/src/mage/cards/p/PlaxcasterFrogling.java b/Mage.Sets/src/mage/cards/p/PlaxcasterFrogling.java index a217ad0388f..6d224464a0d 100644 --- a/Mage.Sets/src/mage/cards/p/PlaxcasterFrogling.java +++ b/Mage.Sets/src/mage/cards/p/PlaxcasterFrogling.java @@ -16,8 +16,11 @@ import mage.constants.SubType; import mage.constants.Duration; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_CREATURE_P1P1; + /** * * @author JotaPeRL @@ -36,7 +39,7 @@ public final class PlaxcasterFrogling extends CardImpl { // {2}: Target creature with a +1/+1 counter on it gains shroud until end of turn. Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(ShroudAbility.getInstance(), Duration.EndOfTurn), new GenericManaCost(2)); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_P1P1)); + ability.addTarget(new TargetPermanent(FILTER_CREATURE_P1P1)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/p/PlazaOfHarmony.java b/Mage.Sets/src/mage/cards/p/PlazaOfHarmony.java index 71d652b53b7..2bc0057e502 100644 --- a/Mage.Sets/src/mage/cards/p/PlazaOfHarmony.java +++ b/Mage.Sets/src/mage/cards/p/PlazaOfHarmony.java @@ -1,21 +1,17 @@ package mage.cards.p; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.condition.Condition; -import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.YouControlTwoOrMoreGatesCondition; import mage.abilities.effects.common.GainLifeEffect; -import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.common.GatesYouControlHint; import mage.abilities.mana.AnyColorLandsProduceManaAbility; import mage.abilities.mana.ColorlessManaAbility; 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.filter.FilterPermanent; -import mage.filter.common.FilterControlledPermanent; import java.util.UUID; @@ -24,25 +20,14 @@ import java.util.UUID; */ public final class PlazaOfHarmony extends CardImpl { - private static final FilterPermanent filter = new FilterControlledPermanent(); private static final FilterPermanent filter2 = new FilterPermanent(SubType.GATE, "Gate"); - static { - filter.add(SubType.GATE.getPredicate()); - } - - private static final Condition condition - = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1); - public PlazaOfHarmony(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); // When Plaza of Harmony enters the battlefield, if you control two or more Gates, you gain 3 life. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3)), - condition, "When {this} enters, " + - "if you control two or more Gates, you gain 3 life." - ).addHint(new ConditionHint(condition, "You control two or more Gates"))); + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3)) + .withInterveningIf(YouControlTwoOrMoreGatesCondition.instance).addHint(GatesYouControlHint.instance)); // {T}: Add {C}. this.addAbility(new ColorlessManaAbility()); diff --git a/Mage.Sets/src/mage/cards/p/Plummet.java b/Mage.Sets/src/mage/cards/p/Plummet.java index fb539c22cb2..559acade3ba 100644 --- a/Mage.Sets/src/mage/cards/p/Plummet.java +++ b/Mage.Sets/src/mage/cards/p/Plummet.java @@ -11,6 +11,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -28,7 +29,7 @@ public final class Plummet extends CardImpl { public Plummet(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{G}"); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); } diff --git a/Mage.Sets/src/mage/cards/p/PoisonArrow.java b/Mage.Sets/src/mage/cards/p/PoisonArrow.java index ce1bad3cf7f..fb2d330b92d 100644 --- a/Mage.Sets/src/mage/cards/p/PoisonArrow.java +++ b/Mage.Sets/src/mage/cards/p/PoisonArrow.java @@ -7,8 +7,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author LoneFox @@ -21,7 +24,7 @@ public final class PoisonArrow extends CardImpl { // Destroy target nonblack creature. You gain 3 life. this.getSpellAbility().addEffect(new DestroyTargetEffect()); this.getSpellAbility().addEffect(new GainLifeEffect(3)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); } private PoisonArrow(final PoisonArrow card) { diff --git a/Mage.Sets/src/mage/cards/p/PolisCrusher.java b/Mage.Sets/src/mage/cards/p/PolisCrusher.java index 1b615461828..83422c7208a 100644 --- a/Mage.Sets/src/mage/cards/p/PolisCrusher.java +++ b/Mage.Sets/src/mage/cards/p/PolisCrusher.java @@ -1,10 +1,9 @@ package mage.cards.p; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.condition.common.MonstrousCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.MonstrosityAbility; import mage.abilities.keyword.ProtectionAbility; @@ -14,6 +13,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.FilterCard; +import mage.filter.FilterPermanent; import mage.filter.common.FilterEnchantmentCard; import mage.filter.common.FilterEnchantmentPermanent; import mage.target.TargetPermanent; @@ -27,11 +27,7 @@ import java.util.UUID; public final class PolisCrusher extends CardImpl { private static final FilterCard filterCard = new FilterEnchantmentCard("enchantments"); - private static final FilterEnchantmentPermanent filterPermanent = new FilterEnchantmentPermanent("enchantment that player controls"); - - static { - filterCard.add(CardType.ENCHANTMENT.getPredicate()); - } + private static final FilterPermanent filterPermanent = new FilterEnchantmentPermanent("enchantment that player controls"); public PolisCrusher(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{G}"); @@ -50,12 +46,11 @@ public final class PolisCrusher extends CardImpl { this.addAbility(new MonstrosityAbility("{4}{R}{G}", 3)); // Whenever Polis Crusher deals combat damage to a player, if Polis Crusher is monstrous, destroy target enchantment that player controls. - TriggeredAbility ability = new DealsCombatDamageToAPlayerTriggeredAbility(new DestroyTargetEffect(), false, true); + Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility( + new DestroyTargetEffect(), false, true + ).withInterveningIf(MonstrousCondition.instance); ability.addTarget(new TargetPermanent(filterPermanent)); - ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster()); - - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, MonstrousCondition.instance, - "Whenever {this} deals combat damage to a player, if {this} is monstrous, destroy target enchantment that player controls.")); + this.addAbility(ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster())); } private PolisCrusher(final PolisCrusher card) { diff --git a/Mage.Sets/src/mage/cards/p/PolymorphousRush.java b/Mage.Sets/src/mage/cards/p/PolymorphousRush.java index 5819a2fc124..92462a17caf 100644 --- a/Mage.Sets/src/mage/cards/p/PolymorphousRush.java +++ b/Mage.Sets/src/mage/cards/p/PolymorphousRush.java @@ -8,12 +8,13 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; -import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; +import mage.target.TargetPermanent; +import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import mage.util.functions.EmptyCopyApplier; @@ -31,9 +32,8 @@ public final class PolymorphousRush extends CardImpl { this.addAbility(new StriveAbility("{1}{U}")); // Choose a creature on the battlefield. Any number of target creatures you control each become a copy of that creature until end of turn. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, Integer.MAX_VALUE, StaticFilters.FILTER_PERMANENT_CREATURE_CONTROLLED, false)); this.getSpellAbility().addEffect(new PolymorphousRushCopyEffect()); - + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE)); } private PolymorphousRush(final PolymorphousRush card) { @@ -66,7 +66,7 @@ class PolymorphousRushCopyEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - Target target = new TargetCreaturePermanent(new FilterCreaturePermanent("")); + Target target = new TargetPermanent(new FilterCreaturePermanent("")); target.withNotTarget(true); target.withTargetName("a creature on the battlefield (creature to copy)"); if (target.canChoose(controller.getId(), source, game) && controller.chooseTarget(outcome, target, source, game)) { diff --git a/Mage.Sets/src/mage/cards/p/PoppetStitcher.java b/Mage.Sets/src/mage/cards/p/PoppetStitcher.java index 018254b646b..00b952d09a7 100644 --- a/Mage.Sets/src/mage/cards/p/PoppetStitcher.java +++ b/Mage.Sets/src/mage/cards/p/PoppetStitcher.java @@ -1,23 +1,25 @@ package mage.cards.p; import mage.MageInt; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.hint.Hint; import mage.abilities.hint.ValueHint; import mage.abilities.keyword.TransformAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.StaticFilters; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.permanent.TokenPredicate; import mage.game.permanent.token.ZombieDecayedToken; import java.util.UUID; @@ -27,11 +29,15 @@ import java.util.UUID; */ public final class PoppetStitcher extends CardImpl { - private static final Condition condition = new PermanentsOnTheBattlefieldCondition( - StaticFilters.FILTER_CREATURE_TOKEN, ComparisonType.MORE_THAN, 2 - ); + private static final FilterPermanent filter = new FilterControlledPermanent("you control three or more creature tokens"); + + static { + filter.add(TokenPredicate.TRUE); + } + + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 2); private static final Hint hint = new ValueHint( - "Creature tokens you control", new PermanentsOnBattlefieldCount(StaticFilters.FILTER_CREATURE_TOKEN) + "Creature tokens you control", new PermanentsOnBattlefieldCount(filter) ); public PoppetStitcher(UUID ownerId, CardSetInfo setInfo) { @@ -52,12 +58,8 @@ public final class PoppetStitcher extends CardImpl { // At the beginning of your upkeep, if you control three or more creature tokens, you may transform Poppet Sticher. this.addAbility(new TransformAbility()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility( - new TransformSourceEffect(), true - ), condition, "At the beginning of your upkeep, " + - "if you control three or more creature tokens, you may transform {this}." - ).addHint(hint)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(), true) + .withInterveningIf(condition).addHint(hint)); } private PoppetStitcher(final PoppetStitcher card) { diff --git a/Mage.Sets/src/mage/cards/p/PortalManipulator.java b/Mage.Sets/src/mage/cards/p/PortalManipulator.java new file mode 100644 index 00000000000..b4f39834bba --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PortalManipulator.java @@ -0,0 +1,134 @@ +package mage.cards.p; + +import mage.MageInt; +import mage.MageItem; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.IsStepCondition; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.FlashAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.PhaseStep; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterAttackingCreature; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.game.Game; +import mage.game.combat.CombatGroup; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; +import mage.target.TargetPlayer; +import mage.target.Targets; +import mage.target.targetpointer.EachTargetPointer; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * @author TheElk801 + */ +public final class PortalManipulator extends CardImpl { + + private static final Condition condition = new IsStepCondition(PhaseStep.DECLARE_ATTACKERS); + private static final FilterPermanent filter = new FilterAttackingCreature("attacking creatures controlled by that player's opponents"); + + static { + filter.add(PortalManipulatorPredicate.instance); + } + + public PortalManipulator(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W/U}{W/U}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // When Portal Manipulator enters the battlefield during the declare attackers step, choose target player and any number of target attacking creatures their opponents control. Those creatures are now attacking that player. + Ability ability = new EntersBattlefieldTriggeredAbility(new PortalManipulatorEffect()).withTriggerCondition(condition); + ability.addTarget(new TargetPlayer()); + ability.addTarget(new TargetPermanent(0, Integer.MAX_VALUE, filter)); + this.addAbility(ability); + } + + private PortalManipulator(final PortalManipulator card) { + super(card); + } + + @Override + public PortalManipulator copy() { + return new PortalManipulator(this); + } +} + +enum PortalManipulatorPredicate implements ObjectSourcePlayerPredicate { + instance; + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + return Optional + .ofNullable(input) + .map(ObjectSourcePlayer::getSource) + .map(Ability::getTargets) + .map(Targets::getFirstTarget) + .map(game::getPlayer) + .filter(player -> player.hasOpponent(input.getObject().getControllerId(), game)) + .isPresent(); + } +} + +class PortalManipulatorEffect extends OneShotEffect { + + PortalManipulatorEffect() { + super(Outcome.Benefit); + staticText = "choose target player and any number of target attacking creatures their opponents control. " + + "Those creatures are now attacking that player"; + this.setTargetPointer(new EachTargetPointer()); + } + + private PortalManipulatorEffect(final PortalManipulatorEffect effect) { + super(effect); + } + + @Override + public PortalManipulatorEffect copy() { + return new PortalManipulatorEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(this.getTargetPointer().getFirst(game, source)); + if (player == null) { + return false; + } + List permanents = this + .getTargetPointer() + .getTargets(game, source) + .stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .map(MageItem::getId) + .collect(Collectors.toList()); + if (permanents.isEmpty()) { + return false; + } + for (CombatGroup combatGroup : game.getCombat().getGroups()) { + if (combatGroup.getAttackers().stream().anyMatch(permanents::contains)) { + combatGroup.changeDefenderPostDeclaration(player.getId(), game); + } + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/p/PortalOfSanctuary.java b/Mage.Sets/src/mage/cards/p/PortalOfSanctuary.java index 4f854479914..d77c411a23c 100644 --- a/Mage.Sets/src/mage/cards/p/PortalOfSanctuary.java +++ b/Mage.Sets/src/mage/cards/p/PortalOfSanctuary.java @@ -6,7 +6,6 @@ import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.OneShotEffect; -import mage.abilities.hint.common.MyTurnHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.cards.Cards; @@ -32,12 +31,10 @@ public final class PortalOfSanctuary extends CardImpl { // {1}, {T}: Return target creature you control and each Aura attached to it to their owners' hands. Activate this ability only during your turn. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new PortalOfSanctuaryEffect(), - new GenericManaCost(1), MyTurnCondition.instance + new PortalOfSanctuaryEffect(), new GenericManaCost(1), MyTurnCondition.instance ); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetControlledCreaturePermanent()); - ability.addHint(MyTurnHint.instance); this.addAbility(ability); } @@ -83,4 +80,4 @@ class PortalOfSanctuaryEffect extends OneShotEffect { .forEach(perm -> cards.add(perm)); return player.moveCards(cards, Zone.HAND, source, game); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/p/Portcullis.java b/Mage.Sets/src/mage/cards/p/Portcullis.java index a85b6c4c20a..2a67517e06c 100644 --- a/Mage.Sets/src/mage/cards/p/Portcullis.java +++ b/Mage.Sets/src/mage/cards/p/Portcullis.java @@ -2,11 +2,9 @@ package mage.cards.p; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; -import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect; @@ -30,17 +28,19 @@ import java.util.UUID; */ public final class Portcullis extends CardImpl { + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterCreaturePermanent("there are two or more other creatures on the battlefield"), + ComparisonType.MORE_THAN, 1, false + ); + public Portcullis(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); // Whenever a creature enters the battlefield, if there are two or more other creatures on the battlefield, exile that creature. Return that card to the battlefield under its owner's control when Portcullis leaves the battlefield. - String rule = "Whenever a creature enters the battlefield, if there are two or more other creatures on the battlefield, exile that creature."; - String rule2 = " Return that card to the battlefield under its owner's control when {this} leaves the battlefield."; - TriggeredAbility ability = new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new PortcullisExileEffect(), - StaticFilters.FILTER_PERMANENT_A_CREATURE, false, SetTargetPointer.PERMANENT); - MoreThanXCreaturesOnBFCondition condition = new MoreThanXCreaturesOnBFCondition(2); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, condition, rule + rule2)); - + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + Zone.BATTLEFIELD, new PortcullisExileEffect(), StaticFilters.FILTER_PERMANENT_A_CREATURE, + false, SetTargetPointer.PERMANENT + ).withInterveningIf(condition)); } private Portcullis(final Portcullis card) { @@ -53,28 +53,12 @@ public final class Portcullis extends CardImpl { } } -class MoreThanXCreaturesOnBFCondition implements Condition { - - protected final int value; - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures on field"); - - public MoreThanXCreaturesOnBFCondition(int value) { - this.value = value; - } - - @Override - public final boolean apply(Game game, Ability source) { - PermanentsOnBattlefieldCount amount = new PermanentsOnBattlefieldCount(filter); - int count = amount.calculate(game, source, null); - return count > value; - } -} - class PortcullisExileEffect extends OneShotEffect { PortcullisExileEffect() { super(Outcome.Exile); - this.staticText = "Whenever a creature enters the battlefield, if there are two or more other creatures on the battlefield, exile that creature"; + this.staticText = "exile that creature. Return that card to the battlefield " + + "under its owner's control when {this} leaves the battlefield"; } private PortcullisExileEffect(final PortcullisExileEffect effect) { @@ -139,6 +123,6 @@ class PortcullisReturnToBattlefieldTriggeredAbility extends DelayedTriggeredAbil @Override public String getRule() { - return "Return this card to the battlefield under its owner's control when Portcullis leaves the battlefield."; + return "Return this card to the battlefield under its owner's control when {this} leaves the battlefield."; } } diff --git a/Mage.Sets/src/mage/cards/p/PossessedAven.java b/Mage.Sets/src/mage/cards/p/PossessedAven.java index 8c85263792a..3e7fce76795 100644 --- a/Mage.Sets/src/mage/cards/p/PossessedAven.java +++ b/Mage.Sets/src/mage/cards/p/PossessedAven.java @@ -22,6 +22,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -59,7 +60,7 @@ public final class PossessedAven extends CardImpl { )); Ability gainedAbility = new SimpleActivatedAbility(new DestroyTargetEffect(), new ManaCostsImpl<>("{2}{B}")); gainedAbility.addCost(new TapSourceCost()); - gainedAbility.addTarget(new TargetCreaturePermanent(filter)); + gainedAbility.addTarget(new TargetPermanent(filter)); ability.addEffect(new ConditionalContinuousEffect( new GainAbilitySourceEffect(gainedAbility), ThresholdCondition.instance, ", and has \"{2}{B}, {T}: Destroy target blue creature.\"" diff --git a/Mage.Sets/src/mage/cards/p/PossessedBarbarian.java b/Mage.Sets/src/mage/cards/p/PossessedBarbarian.java index c19e6aabca8..7b0b9f0c9bb 100644 --- a/Mage.Sets/src/mage/cards/p/PossessedBarbarian.java +++ b/Mage.Sets/src/mage/cards/p/PossessedBarbarian.java @@ -22,6 +22,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -60,7 +61,7 @@ public final class PossessedBarbarian extends CardImpl { )); Ability gainedAbility = new SimpleActivatedAbility(new DestroyTargetEffect(), new ManaCostsImpl<>("{2}{B}")); gainedAbility.addCost(new TapSourceCost()); - gainedAbility.addTarget(new TargetCreaturePermanent(filter)); + gainedAbility.addTarget(new TargetPermanent(filter)); ability.addEffect(new ConditionalContinuousEffect( new GainAbilitySourceEffect(gainedAbility), ThresholdCondition.instance, ", and has \"{2}{B}, {T}: Destroy target red creature.\"" diff --git a/Mage.Sets/src/mage/cards/p/PossessedCentaur.java b/Mage.Sets/src/mage/cards/p/PossessedCentaur.java index f35ad616eca..99da498f184 100644 --- a/Mage.Sets/src/mage/cards/p/PossessedCentaur.java +++ b/Mage.Sets/src/mage/cards/p/PossessedCentaur.java @@ -22,6 +22,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -58,7 +59,7 @@ public final class PossessedCentaur extends CardImpl { )); Ability gainedAbility = new SimpleActivatedAbility(new DestroyTargetEffect(), new ManaCostsImpl<>("{2}{B}")); gainedAbility.addCost(new TapSourceCost()); - gainedAbility.addTarget(new TargetCreaturePermanent(filter)); + gainedAbility.addTarget(new TargetPermanent(filter)); ability.addEffect(new ConditionalContinuousEffect( new GainAbilitySourceEffect(gainedAbility), ThresholdCondition.instance, ", and has \"{2}{B}, {T}: Destroy target green creature.\"" diff --git a/Mage.Sets/src/mage/cards/p/PossessedNomad.java b/Mage.Sets/src/mage/cards/p/PossessedNomad.java index 2d3523f34c5..195170e30cf 100644 --- a/Mage.Sets/src/mage/cards/p/PossessedNomad.java +++ b/Mage.Sets/src/mage/cards/p/PossessedNomad.java @@ -22,6 +22,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -59,7 +60,7 @@ public final class PossessedNomad extends CardImpl { )); Ability gainedAbility = new SimpleActivatedAbility(new DestroyTargetEffect(), new ManaCostsImpl<>("{2}{B}")); gainedAbility.addCost(new TapSourceCost()); - gainedAbility.addTarget(new TargetCreaturePermanent(filter)); + gainedAbility.addTarget(new TargetPermanent(filter)); ability.addEffect(new ConditionalContinuousEffect( new GainAbilitySourceEffect(gainedAbility), ThresholdCondition.instance, ", and has \"{2}{B}, {T}: Destroy target white creature.\"" diff --git a/Mage.Sets/src/mage/cards/p/PouncingWurm.java b/Mage.Sets/src/mage/cards/p/PouncingWurm.java index 03932a55579..eaa2a553e4c 100644 --- a/Mage.Sets/src/mage/cards/p/PouncingWurm.java +++ b/Mage.Sets/src/mage/cards/p/PouncingWurm.java @@ -1,12 +1,9 @@ - package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.HasteAbility; @@ -14,18 +11,19 @@ import mage.abilities.keyword.KickerAbility; 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.counters.CounterType; +import java.util.UUID; + /** - * * @author Backfir3 */ public final class PouncingWurm extends CardImpl { public PouncingWurm(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.WURM); this.power = new MageInt(3); @@ -33,12 +31,14 @@ public final class PouncingWurm extends CardImpl { // Kicker {2}{G} this.addAbility(new KickerAbility("{2}{G}")); + // If Pouncing Wurm was kicked, it enters with three +1/+1 counters on it and with haste. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(3))), - KickedCondition.ONCE,"If Pouncing Wurm was kicked, it enters with three +1/+1 counters on it and with haste."); - ability.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield)); - this.addAbility(ability); + Ability ability = new EntersBattlefieldAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance(3)), KickedCondition.ONCE, + "If {this} was kicked, it enters with three +1/+1 counters on it and with haste.", "" + ); + ability.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield)); + this.addAbility(ability); } private PouncingWurm(final PouncingWurm card) { diff --git a/Mage.Sets/src/mage/cards/p/PredatorFlagship.java b/Mage.Sets/src/mage/cards/p/PredatorFlagship.java index 3ad925e2fb1..e7a586da48a 100644 --- a/Mage.Sets/src/mage/cards/p/PredatorFlagship.java +++ b/Mage.Sets/src/mage/cards/p/PredatorFlagship.java @@ -17,6 +17,7 @@ import mage.constants.SuperType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -43,7 +44,7 @@ public final class PredatorFlagship extends CardImpl { // {5}, {T}: Destroy target creature with flying. ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new ManaCostsImpl<>("{5}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/p/PrematureBurial.java b/Mage.Sets/src/mage/cards/p/PrematureBurial.java index c74ba2fe51e..23e5b7ac879 100644 --- a/Mage.Sets/src/mage/cards/p/PrematureBurial.java +++ b/Mage.Sets/src/mage/cards/p/PrematureBurial.java @@ -15,6 +15,7 @@ import mage.filter.predicate.mageobject.ColorPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.watchers.Watcher; @@ -38,7 +39,7 @@ public final class PrematureBurial extends CardImpl { // Destroy target nonblack creature that entered the battlefield since your last turn ended. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addWatcher(new PrematureBurialWatcher()); } diff --git a/Mage.Sets/src/mage/cards/p/PreyUpon.java b/Mage.Sets/src/mage/cards/p/PreyUpon.java index ebe83d2e98b..9320387fcbc 100644 --- a/Mage.Sets/src/mage/cards/p/PreyUpon.java +++ b/Mage.Sets/src/mage/cards/p/PreyUpon.java @@ -5,11 +5,14 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author BetaSteward */ @@ -21,7 +24,7 @@ public final class PreyUpon extends CardImpl { // Target creature you control fights target creature you don't control. this.getSpellAbility().addEffect(new FightTargetsEffect()); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); } private PreyUpon(final PreyUpon card) { diff --git a/Mage.Sets/src/mage/cards/p/PrickleFaeries.java b/Mage.Sets/src/mage/cards/p/PrickleFaeries.java index a25a5ac2c23..525b6089461 100644 --- a/Mage.Sets/src/mage/cards/p/PrickleFaeries.java +++ b/Mage.Sets/src/mage/cards/p/PrickleFaeries.java @@ -1,24 +1,15 @@ package mage.cards.p; import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.CardsInHandCondition; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.keyword.FlyingAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.game.Game; -import mage.players.Player; +import mage.constants.*; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; import java.util.UUID; /** @@ -26,6 +17,8 @@ import java.util.UUID; */ public final class PrickleFaeries extends CardImpl { + private static final Condition condition = new CardsInHandCondition(ComparisonType.FEWER_THAN, 3, TargetController.ACTIVE); + public PrickleFaeries(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); @@ -39,13 +32,10 @@ public final class PrickleFaeries extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // At the beginning of each opponent's upkeep, if that player has two or fewer cards in hand, Prickle Faeries deals 2 damage to them. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility( - Zone.BATTLEFIELD, TargetController.OPPONENT, new DamageTargetEffect(2), - false - ), PrickleFaeriesCondition.instance, "At the beginning of each opponent's upkeep, " + - "if that player has two or fewer cards in hand, {this} deals 2 damage to them." - )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + Zone.BATTLEFIELD, TargetController.OPPONENT, + new DamageTargetEffect(2, true, "them"), false + ).withInterveningIf(condition)); } private PrickleFaeries(final PrickleFaeries card) { @@ -57,18 +47,3 @@ public final class PrickleFaeries extends CardImpl { return new PrickleFaeries(this); } } - -enum PrickleFaeriesCondition implements Condition { - instance; - - @Override - public boolean apply(Game game, Ability source) { - return Optional - .ofNullable(game.getActivePlayerId()) - .map(game::getPlayer) - .filter(Objects::nonNull) - .map(Player::getHand) - .map(Set::size) - .orElse(0) <= 2; - } -} diff --git a/Mage.Sets/src/mage/cards/p/PrismaticStrands.java b/Mage.Sets/src/mage/cards/p/PrismaticStrands.java index b61bb5a328d..4c320f5e31c 100644 --- a/Mage.Sets/src/mage/cards/p/PrismaticStrands.java +++ b/Mage.Sets/src/mage/cards/p/PrismaticStrands.java @@ -1,7 +1,5 @@ - package mage.cards.p; -import java.util.UUID; import mage.MageObject; import mage.ObjectColor; import mage.abilities.Ability; @@ -15,22 +13,22 @@ import mage.choices.ChoiceColor; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; -import mage.constants.TimingRule; import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.players.Player; -import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; /** - * * @author escplan9 (Derek Monturo - dmontur1 at gmail dot com) */ public final class PrismaticStrands extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped white creature you control"); + private static final FilterControlledPermanent filter = new FilterControlledCreaturePermanent("untapped white creature you control"); static { filter.add(TappedPredicate.UNTAPPED); @@ -44,7 +42,7 @@ public final class PrismaticStrands extends CardImpl { this.getSpellAbility().addEffect(new PrismaticStrandsEffect()); // Flashback-Tap an untapped white creature you control. - this.addAbility(new FlashbackAbility(this, new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, false)))); + this.addAbility(new FlashbackAbility(this, new TapTargetCost(filter))); } private PrismaticStrands(final PrismaticStrands card) { @@ -77,18 +75,17 @@ class PrismaticStrandsEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = game.getObject(source); - if (controller != null && sourceObject != null) { - ChoiceColor choice = new ChoiceColor(); - controller.choose(Outcome.PreventDamage, choice, game); - if (choice.isChosen()) { - if (!game.isSimulation()) { - game.informPlayers(sourceObject.getLogName() + ": " + controller.getLogName() + " has chosen sources of the color " + choice.getChoice()); - } - game.addEffect(new PrismaticStrandsPreventionEffect(choice.getColor()), source); - return true; - } + if (controller == null || sourceObject == null) { + return false; } - return false; + ChoiceColor choice = new ChoiceColor(); + controller.choose(Outcome.PreventDamage, choice, game); + if (!choice.isChosen()) { + return false; + } + game.informPlayers(sourceObject.getLogName() + ": " + controller.getLogName() + " has chosen sources of the color " + choice.getChoice()); + game.addEffect(new PrismaticStrandsPreventionEffect(choice.getColor()), source); + return true; } } @@ -108,16 +105,13 @@ class PrismaticStrandsPreventionEffect extends PreventionEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (super.applies(event, source, game)) { - if (event.getType() == GameEvent.EventType.DAMAGE_PLAYER - || event.getType() == GameEvent.EventType.DAMAGE_PERMANENT) { - MageObject sourceObject = game.getObject(event.getSourceId()); - if (sourceObject != null && sourceObject.getColor(game).shares(this.color)) { - return true; - } - } + if (!super.applies(event, source, game) + || event.getType() != GameEvent.EventType.DAMAGE_PLAYER + && event.getType() != GameEvent.EventType.DAMAGE_PERMANENT) { + return false; } - return false; + MageObject sourceObject = game.getObject(event.getSourceId()); + return sourceObject != null && sourceObject.getColor(game).shares(this.color); } @Override diff --git a/Mage.Sets/src/mage/cards/p/ProfaneCommand.java b/Mage.Sets/src/mage/cards/p/ProfaneCommand.java index ebe372bff1c..984bba44788 100644 --- a/Mage.Sets/src/mage/cards/p/ProfaneCommand.java +++ b/Mage.Sets/src/mage/cards/p/ProfaneCommand.java @@ -21,6 +21,7 @@ import mage.filter.common.FilterCreatureCard; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.game.Game; +import mage.target.TargetPermanent; import mage.target.TargetPlayer; import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetCreaturePermanent; @@ -37,13 +38,12 @@ public final class ProfaneCommand extends CardImpl { public ProfaneCommand(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{B}{B}"); - - DynamicValue xValue = GetXValue.instance; // Choose two - this.getSpellAbility().getModes().setMinModes(2); this.getSpellAbility().getModes().setMaxModes(2); + // * Target player loses X life. - this.getSpellAbility().addEffect(new LoseLifeTargetEffect(xValue)); + this.getSpellAbility().addEffect(new LoseLifeTargetEffect(GetXValue.instance)); this.getSpellAbility().addTarget(new TargetPlayer()); // * Return target creature card with converted mana cost X or less from your graveyard to the battlefield. @@ -52,15 +52,13 @@ public final class ProfaneCommand extends CardImpl { this.getSpellAbility().addMode(mode); // * Target creature gets -X/-X until end of turn. - DynamicValue minusValue = new SignInversionDynamicValue(xValue); + DynamicValue minusValue = new SignInversionDynamicValue(GetXValue.instance); mode = new Mode(new BoostTargetEffect(minusValue, minusValue, Duration.EndOfTurn)); mode.addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addMode(mode); // * Up to X target creatures gain fear until end of turn. - Effect effect = new GainAbilityTargetEffect(FearAbility.getInstance(), Duration.EndOfTurn); - effect.setText("Up to X target creatures gain fear until end of turn"); - mode = new Mode(effect); + mode = new Mode(new GainAbilityTargetEffect(FearAbility.getInstance(), Duration.EndOfTurn).setText("Up to X target creatures gain fear until end of turn")); mode.addTarget(new TargetCreaturePermanent(0, 1)); this.getSpellAbility().addMode(mode); @@ -95,8 +93,8 @@ enum ProfaneCommandAdjuster implements TargetAdjuster { if (effect instanceof GainAbilityTargetEffect) { mode.getTargets().clear(); FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures gain fear until end of turn"); - mode.addTarget(new TargetCreaturePermanent(0, xValue, filter, false)); + mode.addTarget(new TargetPermanent(0, xValue, filter)); } } } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/p/ProftsEideticMemory.java b/Mage.Sets/src/mage/cards/p/ProftsEideticMemory.java index 8797f7c4fa1..60e17d1518a 100644 --- a/Mage.Sets/src/mage/cards/p/ProftsEideticMemory.java +++ b/Mage.Sets/src/mage/cards/p/ProftsEideticMemory.java @@ -1,32 +1,33 @@ package mage.cards.p; -import java.util.UUID; - import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.DrewTwoOrMoreCardsCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.IntPlusDynamicValue; import mage.abilities.dynamicvalue.common.CardsDrawnThisTurnDynamicValue; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.continuous.MaximumHandSizeControllerEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; -import mage.constants.Duration; -import mage.constants.SuperType; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SuperType; import mage.counters.CounterType; import mage.target.common.TargetControlledCreaturePermanent; +import java.util.UUID; + /** - * * @author DominionSpy */ public final class ProftsEideticMemory extends CardImpl { + private static final DynamicValue xValue = new IntPlusDynamicValue(-1, CardsDrawnThisTurnDynamicValue.instance); + public ProftsEideticMemory(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); @@ -38,21 +39,17 @@ public final class ProftsEideticMemory extends CardImpl { // You have no maximum hand size. this.addAbility(new SimpleStaticAbility(new MaximumHandSizeControllerEffect( Integer.MAX_VALUE, Duration.WhileOnBattlefield, - MaximumHandSizeControllerEffect.HandSizeModification.SET))); + MaximumHandSizeControllerEffect.HandSizeModification.SET + ))); // At the beginning of combat on your turn, if you've drawn more than one card this turn, // put X +1/+1 counters on target creature you control, // where X is the number of cards you've drawn this turn minus one. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility( - new AddCountersTargetEffect( - CounterType.P1P1.createInstance(), - new IntPlusDynamicValue(-1, CardsDrawnThisTurnDynamicValue.instance)) - ), - DrewTwoOrMoreCardsCondition.instance, - "At the beginning of combat on your turn, if you've drawn more than one card this turn, " + - "put X +1/+1 counters on target creature you control, " + - "where X is the number of cards you've drawn this turn minus one"); + Ability ability = new BeginningOfCombatTriggeredAbility( + new AddCountersTargetEffect(CounterType.P1P1.createInstance(), xValue) + .setText("put X +1/+1 counters on target creature you control, " + + "where X is the number of cards you've drawn this turn minus one") + ).withInterveningIf(DrewTwoOrMoreCardsCondition.instance); ability.addTarget(new TargetControlledCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/p/ProgenitorMimic.java b/Mage.Sets/src/mage/cards/p/ProgenitorMimic.java index e671856f85f..fd24facb62b 100644 --- a/Mage.Sets/src/mage/cards/p/ProgenitorMimic.java +++ b/Mage.Sets/src/mage/cards/p/ProgenitorMimic.java @@ -1,37 +1,38 @@ - package mage.cards.p; -import java.util.UUID; import mage.MageInt; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.CreateTokenCopySourceEffect; import mage.abilities.effects.common.CopyPermanentEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.permanent.TokenPredicate; import mage.util.functions.AbilityCopyApplier; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class ProgenitorMimic extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("no Token"); + private static final FilterPermanent filter = new FilterCreaturePermanent("this creature isn't a token"); static { filter.add(TokenPredicate.FALSE); } + private static final Condition condition = new SourceMatchesFilterCondition(filter); + public ProgenitorMimic(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{G}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}{U}"); this.subtype.add(SubType.SHAPESHIFTER); this.power = new MageInt(0); @@ -40,18 +41,14 @@ public final class ProgenitorMimic extends CardImpl { // You may have Progenitor Mimic enter the battlefield as a copy of any creature on the battlefield // except it has "At the beginning of your upkeep, if this creature isn't a token, // create a token that's a copy of this creature." - Effect effect = new CreateTokenCopySourceEffect(); - effect.setText("create a token that's a copy of this creature"); - - AbilityCopyApplier applier = new AbilityCopyApplier( - new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(effect), - new SourceMatchesFilterCondition(filter), - "At the beginning of your upkeep, if this creature isn't a token, create a token that's a copy of this creature.") - ); - effect = new CopyPermanentEffect(applier); - effect.setText("as a copy of any creature on the battlefield except it has \"At the beginning of your upkeep, if this creature isn't a token, create a token that's a copy of this creature.\""); - this.addAbility(new EntersBattlefieldAbility(effect, true)); + this.addAbility(new EntersBattlefieldAbility(new CopyPermanentEffect(new AbilityCopyApplier( + new BeginningOfUpkeepTriggeredAbility( + new CreateTokenCopySourceEffect().setText("create a token that's a copy of this creature") + ).withInterveningIf(condition) + )).setText("as a copy of any creature on the battlefield, except it has " + + "\"At the beginning of your upkeep, if this creature isn't a token, " + + "create a token that's a copy of this creature.\""), true + )); } private ProgenitorMimic(final ProgenitorMimic card) { diff --git a/Mage.Sets/src/mage/cards/p/PromiseOfTomorrow.java b/Mage.Sets/src/mage/cards/p/PromiseOfTomorrow.java index dea8fdf10dd..6dd75516b53 100644 --- a/Mage.Sets/src/mage/cards/p/PromiseOfTomorrow.java +++ b/Mage.Sets/src/mage/cards/p/PromiseOfTomorrow.java @@ -1,13 +1,13 @@ package mage.cards.p; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.DiesCreatureTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ExileTargetForSourceEffect; import mage.abilities.effects.common.ReturnFromExileForSourceEffect; import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -15,6 +15,7 @@ import mage.constants.ComparisonType; import mage.constants.TargetController; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledCreaturePermanent; import java.util.UUID; @@ -24,7 +25,7 @@ import java.util.UUID; public final class PromiseOfTomorrow extends CardImpl { private static final Condition condition = new PermanentsOnTheBattlefieldCondition( - StaticFilters.FILTER_CONTROLLED_CREATURE, + new FilterControlledCreaturePermanent("you control no creatures"), ComparisonType.EQUAL_TO, 0, true ); @@ -38,12 +39,12 @@ public final class PromiseOfTomorrow extends CardImpl { )); // At the beginning of each end step, if you control no creatures, sacrifice Promise of Tomorrow and return all cards exiled with it to the battlefield under your control. - BeginningOfEndStepTriggeredAbility returnAbility = new BeginningOfEndStepTriggeredAbility(TargetController.ANY, new SacrificeSourceEffect(), false); - returnAbility.addEffect(new ReturnFromExileForSourceEffect(Zone.BATTLEFIELD)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - returnAbility, condition, "At the beginning of each end step, if you control no creatures, " + - "sacrifice {this} and return all cards exiled with it to the battlefield under your control." - )); + Ability ability = new BeginningOfEndStepTriggeredAbility( + TargetController.ANY, new SacrificeSourceEffect(), false, condition + ); + ability.addEffect(new ReturnFromExileForSourceEffect(Zone.BATTLEFIELD) + .setText("and return all cards exiled with it to the battlefield under your control")); + this.addAbility(ability); } private PromiseOfTomorrow(final PromiseOfTomorrow card) { diff --git a/Mage.Sets/src/mage/cards/p/PromisingDuskmage.java b/Mage.Sets/src/mage/cards/p/PromisingDuskmage.java index 3c4fec64340..6edd71de717 100644 --- a/Mage.Sets/src/mage/cards/p/PromisingDuskmage.java +++ b/Mage.Sets/src/mage/cards/p/PromisingDuskmage.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -13,6 +12,7 @@ import mage.constants.SubType; import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.util.CardUtil; import java.util.UUID; @@ -30,11 +30,8 @@ public final class PromisingDuskmage extends CardImpl { this.toughness = new MageInt(3); // When Promising Duskmage dies, if it had a +1/+1 counter on it, draw a card. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1)), - PromisingDuskmageCondition.instance, "When {this} dies, " + - "if it had a +1/+1 counter on it, draw a card." - )); + this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1)) + .withInterveningIf(PromisingDuskmageCondition.instance)); } private PromisingDuskmage(final PromisingDuskmage card) { @@ -52,7 +49,14 @@ enum PromisingDuskmageCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = (Permanent) source.getEffects().get(0).getValue("permanentLeftBattlefield"); - return permanent != null && permanent.getCounters(game).containsKey(CounterType.P1P1); + return CardUtil + .getEffectValueFromAbility(source, "permanentLeftBattlefield", Permanent.class) + .filter(permanent -> permanent.getCounters(game).containsKey(CounterType.P1P1)) + .isPresent(); + } + + @Override + public String toString() { + return "it had a +1/+1 counter on it"; } } diff --git a/Mage.Sets/src/mage/cards/p/Provoke.java b/Mage.Sets/src/mage/cards/p/Provoke.java index 324c8b8475e..0cf42d67785 100644 --- a/Mage.Sets/src/mage/cards/p/Provoke.java +++ b/Mage.Sets/src/mage/cards/p/Provoke.java @@ -9,10 +9,13 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author LevelX2 */ @@ -26,7 +29,7 @@ public final class Provoke extends CardImpl { Effect effect = new BlocksIfAbleTargetEffect(Duration.EndOfTurn); effect.setText("That creature blocks this turn if able"); this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("
")); diff --git a/Mage.Sets/src/mage/cards/p/PsychoticFury.java b/Mage.Sets/src/mage/cards/p/PsychoticFury.java index 3e051377a96..c3d3ec3634c 100644 --- a/Mage.Sets/src/mage/cards/p/PsychoticFury.java +++ b/Mage.Sets/src/mage/cards/p/PsychoticFury.java @@ -11,6 +11,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.MulticoloredPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -30,7 +31,7 @@ public final class PsychoticFury extends CardImpl { // Target multicolored creature gains double strike until end of turn. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new GainAbilityTargetEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn)); // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("
")); diff --git a/Mage.Sets/src/mage/cards/p/PublicExecution.java b/Mage.Sets/src/mage/cards/p/PublicExecution.java index 7233230dd30..9617a293300 100644 --- a/Mage.Sets/src/mage/cards/p/PublicExecution.java +++ b/Mage.Sets/src/mage/cards/p/PublicExecution.java @@ -15,10 +15,13 @@ import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * @author jeffwadsworth */ @@ -29,7 +32,7 @@ public final class PublicExecution extends CardImpl { // Destroy target creature an opponent controls. Each other creature that player controls gets -2/-0 until end of turn. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.getSpellAbility().addEffect(new PublicExecutionEffect()); } diff --git a/Mage.Sets/src/mage/cards/p/PuncturingLight.java b/Mage.Sets/src/mage/cards/p/PuncturingLight.java index 4e4a2f88670..18faaf075cb 100644 --- a/Mage.Sets/src/mage/cards/p/PuncturingLight.java +++ b/Mage.Sets/src/mage/cards/p/PuncturingLight.java @@ -10,6 +10,7 @@ import mage.constants.ComparisonType; import mage.filter.common.FilterAttackingOrBlockingCreature; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -28,7 +29,7 @@ public final class PuncturingLight extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W}"); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); } diff --git a/Mage.Sets/src/mage/cards/p/Purge.java b/Mage.Sets/src/mage/cards/p/Purge.java index e3d989598ac..232a6c5e5e7 100644 --- a/Mage.Sets/src/mage/cards/p/Purge.java +++ b/Mage.Sets/src/mage/cards/p/Purge.java @@ -10,6 +10,7 @@ import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -29,7 +30,7 @@ public final class Purge extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W}"); // Destroy target artifact creature or black creature. It can't be regenerated. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); } diff --git a/Mage.Sets/src/mage/cards/p/PusKami.java b/Mage.Sets/src/mage/cards/p/PusKami.java index ac715e4c406..02496217b8b 100644 --- a/Mage.Sets/src/mage/cards/p/PusKami.java +++ b/Mage.Sets/src/mage/cards/p/PusKami.java @@ -15,8 +15,11 @@ import mage.constants.SubType; import mage.constants.ColoredManaSymbol; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author Loki @@ -32,7 +35,7 @@ public final class PusKami extends CardImpl { // {B}, Sacrifice Pus Kami: Destroy target nonblack creature. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new ColoredManaCost(ColoredManaSymbol.B)); ability.addCost(new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + ability.addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.addAbility(ability); this.addAbility(new SoulshiftAbility(6)); } diff --git a/Mage.Sets/src/mage/cards/p/PushPull.java b/Mage.Sets/src/mage/cards/p/PushPull.java index e0a55f6c229..956e3f5c8cd 100644 --- a/Mage.Sets/src/mage/cards/p/PushPull.java +++ b/Mage.Sets/src/mage/cards/p/PushPull.java @@ -22,6 +22,7 @@ import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCardInASingleGraveyard; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTargets; @@ -49,7 +50,7 @@ public final class PushPull extends SplitCard { // Push // Destroy target tapped creature. getLeftHalfCard().getSpellAbility().addEffect(new DestroyTargetEffect()); - getLeftHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + getLeftHalfCard().getSpellAbility().addTarget(new TargetPermanent(filter)); // Pull // Put up to two target creature cards from a single graveyard onto the battlefield under your control. They gain haste until end of turn. Sacrifice them at the beginning of the next end step. diff --git a/Mage.Sets/src/mage/cards/p/Putrefax.java b/Mage.Sets/src/mage/cards/p/Putrefax.java index 5f261b98f1a..ffffa137643 100644 --- a/Mage.Sets/src/mage/cards/p/Putrefax.java +++ b/Mage.Sets/src/mage/cards/p/Putrefax.java @@ -1,28 +1,26 @@ - - package mage.cards.p; -import java.util.UUID; import mage.MageInt; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.InfectAbility; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.game.events.GameEvent; +import mage.constants.TargetController; + +import java.util.UUID; /** - * * @author Loki */ public final class Putrefax extends CardImpl { - public Putrefax (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}{G}"); + public Putrefax(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}"); this.subtype.add(SubType.PHYREXIAN); this.subtype.add(SubType.HORROR); @@ -31,7 +29,9 @@ public final class Putrefax extends CardImpl { this.addAbility(TrampleAbility.getInstance()); this.addAbility(HasteAbility.getInstance()); this.addAbility(InfectAbility.getInstance()); - this.addAbility(new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new SacrificeSourceEffect())); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.NEXT, new SacrificeSourceEffect(), false + )); } private Putrefax(final Putrefax card) { diff --git a/Mage.Sets/src/mage/cards/p/PutridWarrior.java b/Mage.Sets/src/mage/cards/p/PutridWarrior.java index f46b567d50d..e68a0d51708 100644 --- a/Mage.Sets/src/mage/cards/p/PutridWarrior.java +++ b/Mage.Sets/src/mage/cards/p/PutridWarrior.java @@ -4,15 +4,12 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.common.DealsDamageSourceTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.GainLifeAllEffect; import mage.abilities.effects.common.LoseLifeAllPlayersEffect; 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.players.Player; import java.util.UUID; @@ -31,7 +28,7 @@ public final class PutridWarrior extends CardImpl { // Whenever Putrid Warrior deals damage, choose one - Each player loses 1 life; or each player gains 1 life. Ability ability = new DealsDamageSourceTriggeredAbility(new LoseLifeAllPlayersEffect(1)); - ability.addMode(new Mode(new PutridWarriorGainLifeEffect())); + ability.addMode(new Mode(new GainLifeAllEffect(1))); this.addAbility(ability); } @@ -44,32 +41,3 @@ public final class PutridWarrior extends CardImpl { return new PutridWarrior(this); } } - -class PutridWarriorGainLifeEffect extends OneShotEffect { - - PutridWarriorGainLifeEffect() { - super(Outcome.GainLife); - staticText = "each player gains 1 life"; - } - - private PutridWarriorGainLifeEffect(final PutridWarriorGainLifeEffect effect) { - super(effect); - } - - @Override - public PutridWarriorGainLifeEffect copy() { - return new PutridWarriorGainLifeEffect(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) { - player.gainLife(1, game, source); - } - } - return true; - } - -} diff --git a/Mage.Sets/src/mage/cards/p/PyreZombie.java b/Mage.Sets/src/mage/cards/p/PyreZombie.java index 9a67214ee97..83fdbc0a4e2 100644 --- a/Mage.Sets/src/mage/cards/p/PyreZombie.java +++ b/Mage.Sets/src/mage/cards/p/PyreZombie.java @@ -34,7 +34,7 @@ public final class PyreZombie extends CardImpl { // At the beginning of your upkeep, if Pyre Zombie is in your graveyard, you may pay {1}{B}{B}. If you do, return Pyre Zombie to your hand. this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.GRAVEYARD, - TargetController.YOU, new DoIfCostPaid(new ReturnToHandSourceEffect().setText("return {this} to your hand"), new ManaCostsImpl<>("{1}{B}{B}")), + TargetController.YOU, new DoIfCostPaid(new ReturnToHandSourceEffect().setText("return it to your hand"), new ManaCostsImpl<>("{1}{B}{B}")), false).withInterveningIf(SourceInGraveyardCondition.instance)); // {1}{R}{R}, Sacrifice Pyre Zombie: Pyre Zombie deals 2 damage to any target. diff --git a/Mage.Sets/src/mage/cards/p/PyrewildShaman.java b/Mage.Sets/src/mage/cards/p/PyrewildShaman.java index 93dc40f06c0..9b8a684b8d3 100644 --- a/Mage.Sets/src/mage/cards/p/PyrewildShaman.java +++ b/Mage.Sets/src/mage/cards/p/PyrewildShaman.java @@ -30,7 +30,7 @@ public final class PyrewildShaman extends CardImpl { // Whenever one or more creatures you control deal combat damage to a player, if Pyrewild Shaman is in your graveyard, you may pay {3}. If you do, return Pyrewild Shaman to your hand. this.addAbility(new OneOrMoreCombatDamagePlayerTriggeredAbility(Zone.GRAVEYARD, new DoIfCostPaid( - new ReturnToHandSourceEffect().setText("return {this} to your hand"), + new ReturnToHandSourceEffect().setText("return this card to your hand"), new ManaCostsImpl<>("{3}") ), StaticFilters.FILTER_PERMANENT_CREATURES, SetTargetPointer.NONE, false) .withInterveningIf(SourceInGraveyardCondition.instance)); diff --git a/Mage.Sets/src/mage/cards/p/Pyrohemia.java b/Mage.Sets/src/mage/cards/p/Pyrohemia.java index 5ebe14c9cdc..c161ce7991f 100644 --- a/Mage.Sets/src/mage/cards/p/Pyrohemia.java +++ b/Mage.Sets/src/mage/cards/p/Pyrohemia.java @@ -1,36 +1,37 @@ - package mage.cards.p; -import java.util.UUID; -import mage.abilities.TriggeredAbility; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.condition.common.CreatureCountCondition; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageEverythingEffect; import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.ComparisonType; import mage.constants.TargetController; -import mage.constants.Zone; -import mage.game.events.GameEvent; +import mage.filter.common.FilterCreaturePermanent; + +import java.util.UUID; /** - * * @author fireshoes */ public final class Pyrohemia extends CardImpl { - private static final String ruleText = "At the beginning of the end step, if no creatures are on the battlefield, sacrifice {this}."; + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterCreaturePermanent("no creatures are on the battlefield"), ComparisonType.EQUAL_TO, 0 + ); public Pyrohemia(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}{R}"); // At the beginning of the end step, if no creatures are on the battlefield, sacrifice Pyrohemia. - TriggeredAbility triggered = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new SacrificeSourceEffect()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(triggered, new CreatureCountCondition(0, TargetController.ANY), ruleText)); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.NEXT, new SacrificeSourceEffect(), false, condition + )); // {R}: Pyrohemia deals 1 damage to each creature and each player. this.addAbility(new SimpleActivatedAbility(new DamageEverythingEffect(1), new ManaCostsImpl<>("{R}"))); diff --git a/Mage.Sets/src/mage/cards/q/QueenMarchesa.java b/Mage.Sets/src/mage/cards/q/QueenMarchesa.java index 1c4d74e037d..79019ed5ac6 100644 --- a/Mage.Sets/src/mage/cards/q/QueenMarchesa.java +++ b/Mage.Sets/src/mage/cards/q/QueenMarchesa.java @@ -1,18 +1,15 @@ - package mage.cards.q; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.BecomesMonarchSourceEffect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.hint.common.MonarchHint; import mage.abilities.keyword.DeathtouchAbility; import mage.abilities.keyword.HasteAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -21,8 +18,9 @@ import mage.constants.SuperType; import mage.game.Game; import mage.game.permanent.token.QueenMarchesaAssassinToken; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class QueenMarchesa extends CardImpl { @@ -38,16 +36,16 @@ public final class QueenMarchesa extends CardImpl { // Deathtouch this.addAbility(DeathtouchAbility.getInstance()); + // Haste + this.addAbility(HasteAbility.getInstance()); // When Queen Marchesa enters the battlefield, you become the monarch. this.addAbility(new EntersBattlefieldTriggeredAbility(new BecomesMonarchSourceEffect()).addHint(MonarchHint.instance)); // At the beginning of your upkeep, if an opponent is the monarch, create a 1/1 black Assassin creature token with deathtouch and haste. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new QueenMarchesaAssassinToken())), - OpponentIsMonarchCondition.instance, - "At the beginning of your upkeep, if an opponent is the monarch, create a 1/1 black Assassin creature token with deathtouch and haste.")); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new QueenMarchesaAssassinToken())) + .withInterveningIf(QueenMarchesaCondition.instance)); } private QueenMarchesa(final QueenMarchesa card) { @@ -60,9 +58,8 @@ public final class QueenMarchesa extends CardImpl { } } -enum OpponentIsMonarchCondition implements Condition { - - instance; +enum QueenMarchesaCondition implements Condition { + instance; @Override public boolean apply(Game game, Ability source) { diff --git a/Mage.Sets/src/mage/cards/q/Quicksand.java b/Mage.Sets/src/mage/cards/q/Quicksand.java index 9229168c64e..434e50ad3a9 100644 --- a/Mage.Sets/src/mage/cards/q/Quicksand.java +++ b/Mage.Sets/src/mage/cards/q/Quicksand.java @@ -16,6 +16,7 @@ import mage.constants.Zone; import mage.filter.common.FilterAttackingCreature; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -37,7 +38,7 @@ public final class Quicksand extends CardImpl { SimpleActivatedAbility ability = new SimpleActivatedAbility( new BoostTargetEffect(-1, -2, Duration.EndOfTurn), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); ability.addCost(new SacrificeSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/q/QuietContemplation.java b/Mage.Sets/src/mage/cards/q/QuietContemplation.java index 5d3358c991c..c19f2be85da 100644 --- a/Mage.Sets/src/mage/cards/q/QuietContemplation.java +++ b/Mage.Sets/src/mage/cards/q/QuietContemplation.java @@ -12,8 +12,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -30,7 +33,7 @@ public final class QuietContemplation extends CardImpl { effect.setText("and it doesn't untap during its controller's next untap step"); doIfCostPaid.addEffect(effect); Ability ability = new SpellCastControllerTriggeredAbility(doIfCostPaid, StaticFilters.FILTER_SPELL_A_NON_CREATURE, false); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/q/QuilledGreatwurm.java b/Mage.Sets/src/mage/cards/q/QuilledGreatwurm.java index 5f5cf52e503..cebc2dd16f8 100644 --- a/Mage.Sets/src/mage/cards/q/QuilledGreatwurm.java +++ b/Mage.Sets/src/mage/cards/q/QuilledGreatwurm.java @@ -24,7 +24,7 @@ import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.permanent.CounterAnyPredicate; import mage.game.Game; import mage.players.Player; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; import java.util.UUID; @@ -102,7 +102,7 @@ class QuilledGreatwurmEffect extends AsThoughEffectImpl { return false; } Costs costs = new CostsImpl<>(); - costs.add(new RemoveCounterCost(new TargetControlledCreaturePermanent(1, 6, filter, true), null, 6)); + costs.add(new RemoveCounterCost(new TargetControlledPermanent(1, 6, filter, true), null, 6)); controller.setCastSourceIdWithAlternateMana( objectId, new ManaCostsImpl<>("{4}{G}{G}"), costs, MageIdentifier.QuilledGreatwurmAlternateCast diff --git a/Mage.Sets/src/mage/cards/q/QuillmaneBaku.java b/Mage.Sets/src/mage/cards/q/QuillmaneBaku.java index ffd15b4f2cf..6466c942f14 100644 --- a/Mage.Sets/src/mage/cards/q/QuillmaneBaku.java +++ b/Mage.Sets/src/mage/cards/q/QuillmaneBaku.java @@ -17,6 +17,7 @@ import mage.constants.SubType; import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetadjustment.XManaValueTargetAdjuster; @@ -43,7 +44,7 @@ public final class QuillmaneBaku extends CardImpl { Ability ability = new SimpleActivatedAbility(new ReturnToHandTargetEffect(), new GenericManaCost(1)); ability.addCost(new TapSourceCost()); ability.addCost(new RemoveVariableCountersSourceCost(CounterType.KI)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); ability.setTargetAdjuster(new XManaValueTargetAdjuster(ComparisonType.OR_LESS)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RabidBite.java b/Mage.Sets/src/mage/cards/r/RabidBite.java index 7344f543dd9..7a9b21225fe 100644 --- a/Mage.Sets/src/mage/cards/r/RabidBite.java +++ b/Mage.Sets/src/mage/cards/r/RabidBite.java @@ -5,11 +5,14 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author fireshoes */ @@ -21,7 +24,7 @@ public final class RabidBite extends CardImpl { // Target creature you control deals damage equal to its power to target creature you don't control. this.getSpellAbility().addEffect(new DamageWithPowerFromOneToAnotherTargetEffect()); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); } private RabidBite(final RabidBite card) { diff --git a/Mage.Sets/src/mage/cards/r/RabidRats.java b/Mage.Sets/src/mage/cards/r/RabidRats.java index 77a86379821..c407e560fff 100644 --- a/Mage.Sets/src/mage/cards/r/RabidRats.java +++ b/Mage.Sets/src/mage/cards/r/RabidRats.java @@ -14,6 +14,7 @@ import mage.constants.SubType; import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterBlockingCreature; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -30,7 +31,7 @@ public final class RabidRats extends CardImpl { // {tap}: Target blocking creature gets -1/-1 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(-1, -1, Duration.EndOfTurn), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(new FilterBlockingCreature())); + ability.addTarget(new TargetPermanent(new FilterBlockingCreature())); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RadiantPerformer.java b/Mage.Sets/src/mage/cards/r/RadiantPerformer.java index baf97129cec..89ed4ec669d 100644 --- a/Mage.Sets/src/mage/cards/r/RadiantPerformer.java +++ b/Mage.Sets/src/mage/cards/r/RadiantPerformer.java @@ -6,7 +6,6 @@ import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromHandSourcePermanentCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CopySpellForEachItCouldTargetEffect; import mage.abilities.keyword.FlashAbility; import mage.cards.CardImpl; @@ -52,13 +51,8 @@ public final class RadiantPerformer extends CardImpl { this.addAbility(FlashAbility.getInstance()); // When Radiant Performer enters the battlefield, if you cast it from your hand, choose target spell or ability that targets only a single permanent or player. Copy that spell or ability for each other permanent or player the spell or ability could target. Each copy targets a different one of those permanents and players. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new RadiantPerformerEffect()), - CastFromHandSourcePermanentCondition.instance, "When {this} enters, " + - "if you cast it from your hand, choose target spell or ability that targets only " + - "a single permanent or player. Copy that spell or ability for each other permanent or player " + - "the spell or ability could target. Each copy targets a different one of those permanents and players." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new RadiantPerformerEffect()) + .withInterveningIf(CastFromHandSourcePermanentCondition.instance); ability.addTarget(new TargetStackObject(filter)); this.addAbility(ability, new CastFromHandWatcher()); } @@ -98,6 +92,7 @@ class RadiantPerformerEffect extends CopySpellForEachItCouldTargetEffect { RadiantPerformerEffect() { super(); + staticText = "choose target spell or ability that targets only a single permanent or player. Copy that spell or ability for each other permanent or player the spell or ability could target. Each copy targets a different one of those permanents and players"; } private RadiantPerformerEffect(final RadiantPerformerEffect effect) { diff --git a/Mage.Sets/src/mage/cards/r/RadiantsJudgment.java b/Mage.Sets/src/mage/cards/r/RadiantsJudgment.java index 8ce18659009..db92762efa3 100644 --- a/Mage.Sets/src/mage/cards/r/RadiantsJudgment.java +++ b/Mage.Sets/src/mage/cards/r/RadiantsJudgment.java @@ -11,6 +11,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -29,7 +30,7 @@ public final class RadiantsJudgment extends CardImpl { // Destroy target creature with power 4 or greater. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // Cycling {2} this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{2}"))); } diff --git a/Mage.Sets/src/mage/cards/r/RafterDemon.java b/Mage.Sets/src/mage/cards/r/RafterDemon.java index 9c966444ab6..9bffe4ebf87 100644 --- a/Mage.Sets/src/mage/cards/r/RafterDemon.java +++ b/Mage.Sets/src/mage/cards/r/RafterDemon.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.SpectacleCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.common.discard.DiscardEachPlayerEffect; import mage.abilities.keyword.SpectacleAbility; @@ -32,14 +31,9 @@ public final class RafterDemon extends CardImpl { this.addAbility(new SpectacleAbility(this, new ManaCostsImpl<>("{3}{B}{R}"))); // When Rafter Demon enters the battlefield, if its spectacle cost was paid, each opponent discards a card. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DiscardEachPlayerEffect( - StaticValue.get(1), false, TargetController.OPPONENT - )), SpectacleCondition.instance, - "When {this} enters, " + - "if its spectacle cost was paid, " + - "each opponent discards a card." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new DiscardEachPlayerEffect( + StaticValue.get(1), false, TargetController.OPPONENT + )).withInterveningIf(SpectacleCondition.instance)); } private RafterDemon(final RafterDemon card) { diff --git a/Mage.Sets/src/mage/cards/r/RagMan.java b/Mage.Sets/src/mage/cards/r/RagMan.java index 7bfdf48b6a2..619f3a68947 100644 --- a/Mage.Sets/src/mage/cards/r/RagMan.java +++ b/Mage.Sets/src/mage/cards/r/RagMan.java @@ -8,12 +8,10 @@ import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.RevealHandTargetEffect; -import mage.abilities.hint.common.MyTurnHint; import mage.cards.*; 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.players.Player; @@ -35,11 +33,12 @@ public final class RagMan extends CardImpl { this.toughness = new MageInt(1); // {B}{B}{B}, {T}: Target opponent reveals their hand and discards a creature card at random. Activate this ability only during your turn. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new RevealHandTargetEffect(), new ManaCostsImpl<>("{B}{B}{B}"), MyTurnCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new RevealHandTargetEffect(), new ManaCostsImpl<>("{B}{B}{B}"), MyTurnCondition.instance + ); ability.addCost(new TapSourceCost()); ability.addEffect(new RagManDiscardEffect()); ability.addTarget(new TargetOpponent()); - ability.addHint(MyTurnHint.instance); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/Ragamuffyn.java b/Mage.Sets/src/mage/cards/r/Ragamuffyn.java index 21f8e3433e9..7e1733d9fc0 100644 --- a/Mage.Sets/src/mage/cards/r/Ragamuffyn.java +++ b/Mage.Sets/src/mage/cards/r/Ragamuffyn.java @@ -1,48 +1,46 @@ - package mage.cards.r; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.condition.common.HellbentCondition; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; 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.common.FilterControlledPermanent; import mage.filter.predicate.Predicates; -import mage.target.common.TargetControlledPermanent; + +import java.util.UUID; /** - * * @author djbrez */ public final class Ragamuffyn extends CardImpl { - + private static final FilterControlledPermanent filter = new FilterControlledPermanent("a creature or land"); - + static { filter.add(Predicates.or(CardType.CREATURE.getPredicate(), CardType.LAND.getPredicate())); } public Ragamuffyn(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.ZOMBIE); this.subtype.add(SubType.CLERIC); this.power = new MageInt(2); this.toughness = new MageInt(2); // Hellbent - {tap}, Sacrifice a creature or land: Draw a card. Activate this ability only if you have no cards in hand. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD,new DrawCardSourceControllerEffect(1),new TapSourceCost(), HellbentCondition.instance); - ability.setAbilityWord(AbilityWord.HELLBENT); + Ability ability = new ActivateIfConditionActivatedAbility( + new DrawCardSourceControllerEffect(1), new TapSourceCost(), HellbentCondition.instance + ); ability.addCost(new SacrificeTargetCost(filter)); - this.addAbility(ability); + this.addAbility(ability.setAbilityWord(AbilityWord.HELLBENT)); } private Ragamuffyn(final Ragamuffyn card) { diff --git a/Mage.Sets/src/mage/cards/r/RageWeaver.java b/Mage.Sets/src/mage/cards/r/RageWeaver.java index 293a3e8f18e..cdcce1908bb 100644 --- a/Mage.Sets/src/mage/cards/r/RageWeaver.java +++ b/Mage.Sets/src/mage/cards/r/RageWeaver.java @@ -18,6 +18,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -42,7 +43,7 @@ public final class RageWeaver extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn), new GenericManaCost(2)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RagingBattleMouse.java b/Mage.Sets/src/mage/cards/r/RagingBattleMouse.java index fbd10b2475b..76a043ed272 100644 --- a/Mage.Sets/src/mage/cards/r/RagingBattleMouse.java +++ b/Mage.Sets/src/mage/cards/r/RagingBattleMouse.java @@ -2,32 +2,33 @@ package mage.cards.r; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.CelebrationCondition; +import mage.abilities.condition.common.YouCastExactOneSpellThisTurnCondition; import mage.abilities.decorator.ConditionalCostModificationEffect; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.AbilityWord; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; import mage.filter.StaticFilters; import mage.target.common.TargetControlledCreaturePermanent; import mage.watchers.common.PermanentsEnteredBattlefieldWatcher; -import mage.abilities.condition.common.YouCastExactOneSpellThisTurnCondition; import java.util.UUID; /** - * * @author Susucr */ public final class RagingBattleMouse extends CardImpl { public RagingBattleMouse(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); - + this.subtype.add(SubType.MOUSE); this.power = new MageInt(2); this.toughness = new MageInt(1); @@ -39,17 +40,11 @@ public final class RagingBattleMouse extends CardImpl { ))); // Celebration -- At the beginning of combat on your turn, if two or more nonland permanents entered the battlefield under your control this turn, target creature you control gets +1/+1 until end of turn. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility( - new BoostTargetEffect(1, 1, Duration.EndOfTurn) - ), CelebrationCondition.instance, "At the beginning of combat on your turn, " - + "if two or more nonland permanents entered the battlefield under your control this turn, " - + "target creature you control gets +1/+1 until end of turn." - ); + Ability ability = new BeginningOfCombatTriggeredAbility( + new BoostTargetEffect(1, 1, Duration.EndOfTurn) + ).withInterveningIf(CelebrationCondition.instance); ability.addTarget(new TargetControlledCreaturePermanent()); - ability.setAbilityWord(AbilityWord.CELEBRATION); - ability.addHint(CelebrationCondition.getHint()); - this.addAbility(ability, new PermanentsEnteredBattlefieldWatcher()); + this.addAbility(ability.setAbilityWord(AbilityWord.CELEBRATION).addHint(CelebrationCondition.getHint()), new PermanentsEnteredBattlefieldWatcher()); } private RagingBattleMouse(final RagingBattleMouse card) { diff --git a/Mage.Sets/src/mage/cards/r/RagingRiver.java b/Mage.Sets/src/mage/cards/r/RagingRiver.java index fffdfdc0d5a..0977d98abd8 100644 --- a/Mage.Sets/src/mage/cards/r/RagingRiver.java +++ b/Mage.Sets/src/mage/cards/r/RagingRiver.java @@ -12,6 +12,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; @@ -22,7 +23,7 @@ import mage.game.combat.CombatGroup; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.targetpointer.FixedTarget; import java.util.ArrayList; @@ -57,6 +58,12 @@ public final class RagingRiver extends CardImpl { class RagingRiverEffect extends OneShotEffect { + private static final FilterPermanent filterBlockers = new FilterControlledCreaturePermanent("creatures without flying you control to assign to the \"left\" pile (creatures not chosen will be assigned to the \"right\" pile)"); + + static { + filterBlockers.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); + } + RagingRiverEffect() { super(Outcome.Detriment); staticText = "each defending player divides all creatures without flying they control into a \"left\" pile and a \"right\" pile. Then, for each attacking creature you control, choose \"left\" or \"right.\" That creature can't be blocked this combat except by creatures with flying and creatures in a pile with the chosen label"; @@ -74,84 +81,87 @@ class RagingRiverEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - List left = new ArrayList<>(); - List right = new ArrayList<>(); - - for (UUID defenderId : game.getCombat().getPlayerDefenders(game)) { - Player defender = game.getPlayer(defenderId); - if (defender != null) { - List leftLog = new ArrayList<>(); - List rightLog = new ArrayList<>(); - FilterControlledCreaturePermanent filterBlockers = new FilterControlledCreaturePermanent("creatures without flying you control to assign to the \"left\" pile (creatures not chosen will be assigned to the \"right\" pile)"); - filterBlockers.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); - Target target = new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, filterBlockers, true); - if (target.canChoose(defenderId, source, game)) { - if (defender.chooseTarget(Outcome.Neutral, target, source, game)) { - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), defenderId, game)) { - if (target.getTargets().contains(permanent.getId())) { - left.add(permanent); - leftLog.add(permanent); - } else if (filterBlockers.match(permanent, defenderId, source, game)) { - right.add(permanent); - rightLog.add(permanent); - } - } - } - - // it could be nice to invoke some graphic indicator of which creature is Left or Right in this spot - StringBuilder sb = new StringBuilder("Left pile of ").append(defender.getLogName()).append(": "); - sb.append(leftLog.stream().map(MageObject::getLogName).collect(Collectors.joining(", "))); - - game.informPlayers(sb.toString()); - - sb = new StringBuilder("Right pile of ").append(defender.getLogName()).append(": "); - sb.append(rightLog.stream().map(MageObject::getLogName).collect(Collectors.joining(", "))); - - game.informPlayers(sb.toString()); - } - } - } - - for (UUID attackers : game.getCombat().getAttackers()) { - Permanent attacker = game.getPermanent(attackers); - if (attacker != null && Objects.equals(attacker.getControllerId(), controller.getId())) { - CombatGroup combatGroup = game.getCombat().findGroup(attacker.getId()); - if (combatGroup != null) { - FilterCreaturePermanent filter = new FilterCreaturePermanent(); - Player defender = game.getPlayer(combatGroup.getDefendingPlayerId()); - if (defender != null) { - if (left.isEmpty() && right.isEmpty()) { - // shortcut in case of no labeled blockers available - filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); - } else { - List leftLog = left.stream() - .filter(permanent -> permanent.getControllerId() != null) - .filter(permanent -> permanent.isControlledBy(defender.getId())) - .collect(Collectors.toList()); - List rightLog = right.stream() - .filter(permanent -> permanent.getControllerId() != null) - .filter(permanent -> permanent.isControlledBy(defender.getId())) - .collect(Collectors.toList()); - - - if (controller.choosePile(outcome, attacker.getName() + ": attacking " + defender.getName(), leftLog, rightLog, game)) { - filter.add(Predicates.not(Predicates.or(new AbilityPredicate(FlyingAbility.class), new PermanentReferenceInCollectionPredicate(left, game)))); - game.informPlayers(attacker.getLogName() + ": attacks left (" + defender.getLogName() + ")"); - } else { - filter.add(Predicates.not(Predicates.or(new AbilityPredicate(FlyingAbility.class), new PermanentReferenceInCollectionPredicate(right, game)))); - game.informPlayers(attacker.getLogName() + ": attacks right (" + defender.getLogName() + ")"); - } - } - RestrictionEffect effect = new CantBeBlockedByAllTargetEffect(filter, Duration.EndOfCombat); - effect.setTargetPointer(new FixedTarget(attacker.getId(), game)); - game.addEffect(effect, source); - } - } - } - } - return true; + if (controller == null) { + return false; } - return false; + List left = new ArrayList<>(); + List right = new ArrayList<>(); + + for (UUID defenderId : game.getCombat().getPlayerDefenders(game)) { + Player defender = game.getPlayer(defenderId); + if (defender == null) { + continue; + } + List leftLog = new ArrayList<>(); + List rightLog = new ArrayList<>(); + Target target = new TargetPermanent(0, Integer.MAX_VALUE, filterBlockers, true); + if (!target.canChoose(defenderId, source, game)) { + continue; + } + if (defender.chooseTarget(Outcome.Neutral, target, source, game)) { + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), defenderId, game)) { + if (target.getTargets().contains(permanent.getId())) { + left.add(permanent); + leftLog.add(permanent); + } else if (filterBlockers.match(permanent, defenderId, source, game)) { + right.add(permanent); + rightLog.add(permanent); + } + } + } + + // it could be nice to invoke some graphic indicator of which creature is Left or Right in this spot + StringBuilder sb = new StringBuilder("Left pile of ").append(defender.getLogName()).append(": "); + sb.append(leftLog.stream().map(MageObject::getLogName).collect(Collectors.joining(", "))); + + game.informPlayers(sb.toString()); + + sb = new StringBuilder("Right pile of ").append(defender.getLogName()).append(": "); + sb.append(rightLog.stream().map(MageObject::getLogName).collect(Collectors.joining(", "))); + + game.informPlayers(sb.toString()); + } + + for (UUID attackers : game.getCombat().getAttackers()) { + Permanent attacker = game.getPermanent(attackers); + if (attacker == null || !Objects.equals(attacker.getControllerId(), controller.getId())) { + continue; + } + CombatGroup combatGroup = game.getCombat().findGroup(attacker.getId()); + if (combatGroup == null) { + continue; + } + FilterCreaturePermanent filter = new FilterCreaturePermanent(); + Player defender = game.getPlayer(combatGroup.getDefendingPlayerId()); + if (defender == null) { + continue; + } + if (left.isEmpty() && right.isEmpty()) { + // shortcut in case of no labeled blockers available + filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); + } else { + List leftLog = left.stream() + .filter(permanent -> permanent.getControllerId() != null) + .filter(permanent -> permanent.isControlledBy(defender.getId())) + .collect(Collectors.toList()); + List rightLog = right.stream() + .filter(permanent -> permanent.getControllerId() != null) + .filter(permanent -> permanent.isControlledBy(defender.getId())) + .collect(Collectors.toList()); + + + if (controller.choosePile(outcome, attacker.getName() + ": attacking " + defender.getName(), leftLog, rightLog, game)) { + filter.add(Predicates.not(Predicates.or(new AbilityPredicate(FlyingAbility.class), new PermanentReferenceInCollectionPredicate(left, game)))); + game.informPlayers(attacker.getLogName() + ": attacks left (" + defender.getLogName() + ")"); + } else { + filter.add(Predicates.not(Predicates.or(new AbilityPredicate(FlyingAbility.class), new PermanentReferenceInCollectionPredicate(right, game)))); + game.informPlayers(attacker.getLogName() + ": attacks right (" + defender.getLogName() + ")"); + } + } + RestrictionEffect effect = new CantBeBlockedByAllTargetEffect(filter, Duration.EndOfCombat); + effect.setTargetPointer(new FixedTarget(attacker.getId(), game)); + game.addEffect(effect, source); + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/r/RaidersWake.java b/Mage.Sets/src/mage/cards/r/RaidersWake.java index d69a9914f2b..0feb1e688ca 100644 --- a/Mage.Sets/src/mage/cards/r/RaidersWake.java +++ b/Mage.Sets/src/mage/cards/r/RaidersWake.java @@ -1,13 +1,12 @@ package mage.cards.r; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.DiscardsACardOpponentTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.LoseLifeTargetEffect; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.abilities.hint.common.RaidHint; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AbilityWord; @@ -27,16 +26,15 @@ public final class RaidersWake extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}"); // Whenever an opponent discards a card, that player loses 2 life. - this.addAbility(new DiscardsACardOpponentTriggeredAbility(new LoseLifeTargetEffect(2), false, SetTargetPointer.PLAYER)); + this.addAbility(new DiscardsACardOpponentTriggeredAbility( + new LoseLifeTargetEffect(2), false, SetTargetPointer.PLAYER + )); // Raid — At the beginning of your end step, if you attacked this turn, target opponent discards a card. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility(new DiscardTargetEffect(1)), RaidCondition.instance, - "At the beginning of your end step, if you attacked this turn, target opponent discards a card."); + Ability ability = new BeginningOfEndStepTriggeredAbility(new DiscardTargetEffect(1)) + .withInterveningIf(RaidCondition.instance); ability.addTarget(new TargetOpponent()); - ability.setAbilityWord(AbilityWord.RAID); - ability.addHint(RaidHint.instance); - this.addAbility(ability, new PlayerAttackedWatcher()); + this.addAbility(ability.setAbilityWord(AbilityWord.RAID).addHint(RaidHint.instance), new PlayerAttackedWatcher()); } private RaidersWake(final RaidersWake card) { diff --git a/Mage.Sets/src/mage/cards/r/RaidingParty.java b/Mage.Sets/src/mage/cards/r/RaidingParty.java index 4284c5b0a1a..21aa94e0f14 100644 --- a/Mage.Sets/src/mage/cards/r/RaidingParty.java +++ b/Mage.Sets/src/mage/cards/r/RaidingParty.java @@ -1,9 +1,6 @@ package mage.cards.r; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -17,9 +14,8 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.SubType; -import mage.constants.Zone; -import mage.filter.FilterStackObject; import mage.filter.FilterPermanent; +import mage.filter.FilterStackObject; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.ColorPredicate; @@ -29,27 +25,29 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; import mage.target.TargetPermanent; -import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; /** - * * @author L_J */ public final class RaidingParty extends CardImpl { - + private static final FilterStackObject filterWhite = new FilterStackObject("white spells or abilities from white sources"); private static final FilterControlledPermanent filterOrc = new FilterControlledPermanent(SubType.ORC, "an Orc"); - + static { filterWhite.add(new ColorPredicate(ObjectColor.WHITE)); } public RaidingParty(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); // Raiding Party can't be the target of white spells or abilities from white sources. this.addAbility(new SimpleStaticAbility(new CantBeTargetedSourceEffect(filterWhite, Duration.WhileOnBattlefield))); - + // Sacrifice an Orc: Each player may tap any number of untapped white creatures they control. For each creature tapped this way, that player chooses up to two Plains. Then destroy all Plains that weren't chosen this way by any player. this.addAbility(new SimpleActivatedAbility(new RaidingPartyEffect(), new SacrificeTargetCost(filterOrc))); } @@ -66,7 +64,7 @@ public final class RaidingParty extends CardImpl { class RaidingPartyEffect extends OneShotEffect { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped white creatures"); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("untapped white creatures"); private static final FilterPermanent filter2 = new FilterPermanent("Plains"); static { @@ -99,7 +97,7 @@ class RaidingPartyEffect extends OneShotEffect { if (player != null) { int countBattlefield = game.getBattlefield().getAllActivePermanents(filter, game.getActivePlayerId(), game).size(); int tappedCount = 0; - Target untappedCreatureTarget = new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, filter, true); + Target untappedCreatureTarget = new TargetPermanent(0, Integer.MAX_VALUE, filter, true); if (player.choose(Outcome.Benefit, untappedCreatureTarget, source, game)) { tappedCount = untappedCreatureTarget.getTargets().size(); for (UUID creatureId : untappedCreatureTarget.getTargets()) { diff --git a/Mage.Sets/src/mage/cards/r/RakaSanctuary.java b/Mage.Sets/src/mage/cards/r/RakaSanctuary.java index 5e06e5d7a2b..ebaa5bf0a34 100644 --- a/Mage.Sets/src/mage/cards/r/RakaSanctuary.java +++ b/Mage.Sets/src/mage/cards/r/RakaSanctuary.java @@ -1,18 +1,17 @@ - package mage.cards.r; -import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.common.SanctuaryInterveningIfTriggeredAbility; +import mage.abilities.common.SanctuaryTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; 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 RakaSanctuary extends CardImpl { @@ -21,10 +20,10 @@ public final class RakaSanctuary extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); // At the beginning of your upkeep, if you control a white or blue permanent, Raka Sanctuary deals 1 damage to target creature. If you control a white permanent and a blue permanent, Raka Sanctuary deals 3 damage to that creature instead. - Ability ability = new SanctuaryInterveningIfTriggeredAbility( - new DamageTargetEffect(1), new DamageTargetEffect(3), ObjectColor.WHITE, ObjectColor.BLUE, - "At the beginning of your upkeep, if you control a white or blue permanent, Raka Sanctuary deals 1 damage to target creature. " - + "If you control a white permanent and a blue permanent, Raka Sanctuary deals 3 damage to that creature instead." + Ability ability = new SanctuaryTriggeredAbility( + new DamageTargetEffect(1), new DamageTargetEffect(3), + ObjectColor.WHITE, ObjectColor.BLUE, "{this} deals 1 damage to target creature. " + + "If you control a white permanent and a blue permanent, {this} deals 3 damage to that creature instead." ); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/r/RakdosFirewheeler.java b/Mage.Sets/src/mage/cards/r/RakdosFirewheeler.java index 025ef05376f..e9db64acfe7 100644 --- a/Mage.Sets/src/mage/cards/r/RakdosFirewheeler.java +++ b/Mage.Sets/src/mage/cards/r/RakdosFirewheeler.java @@ -9,7 +9,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent; import mage.target.common.TargetCreatureOrPlaneswalker; import mage.target.common.TargetOpponent; @@ -34,7 +33,7 @@ public final class RakdosFirewheeler extends CardImpl { effect.setText("it deals 2 damage to target opponent and 2 damage to up to one target creature or planeswalker"); Ability ability = new EntersBattlefieldTriggeredAbility(effect, false); ability.addTarget(new TargetOpponent()); - ability.addTarget(new TargetCreatureOrPlaneswalker(0, 1, new FilterCreatureOrPlaneswalkerPermanent(), false)); + ability.addTarget(new TargetCreatureOrPlaneswalker(0, 1)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RakdosRoustabout.java b/Mage.Sets/src/mage/cards/r/RakdosRoustabout.java index c439fbb8d04..74fc73e2e15 100644 --- a/Mage.Sets/src/mage/cards/r/RakdosRoustabout.java +++ b/Mage.Sets/src/mage/cards/r/RakdosRoustabout.java @@ -74,6 +74,6 @@ class RakdosRoustaboutAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever {this} becomes blocked, it deals 1 damage to the player or planeswalker it's attacking"; + return "Whenever {this} becomes blocked, it deals 1 damage to the player or planeswalker it's attacking."; } } diff --git a/Mage.Sets/src/mage/cards/r/RakeclawGargantuan.java b/Mage.Sets/src/mage/cards/r/RakeclawGargantuan.java index 2d6361b7812..eef9b352c95 100644 --- a/Mage.Sets/src/mage/cards/r/RakeclawGargantuan.java +++ b/Mage.Sets/src/mage/cards/r/RakeclawGargantuan.java @@ -16,6 +16,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class RakeclawGargantuan extends CardImpl { SimpleActivatedAbility ability = new SimpleActivatedAbility( new GainAbilityTargetEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{1}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RallyManeuver.java b/Mage.Sets/src/mage/cards/r/RallyManeuver.java index fc7e7fbe24e..27f46357750 100644 --- a/Mage.Sets/src/mage/cards/r/RallyManeuver.java +++ b/Mage.Sets/src/mage/cards/r/RallyManeuver.java @@ -1,7 +1,5 @@ package mage.cards.r; -import java.util.UUID; - import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.FirstStrikeAbility; @@ -12,11 +10,13 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.other.AnotherTargetPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.SecondTargetPointer; +import java.util.UUID; + /** - * * @author weirddan455 */ public final class RallyManeuver extends CardImpl { @@ -31,25 +31,22 @@ public final class RallyManeuver extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}"); // Target creature gets +2/+0 and gains first strike until end of turn. Up to one other target creature gets +0/+2 and gains lifelink until end of turn. - TargetCreaturePermanent target = new TargetCreaturePermanent(); - target.setTargetTag(1); - this.getSpellAbility().addTarget(target.withChooseHint("+2/+0 and first strike")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(1).withChooseHint("+2/+0 and first strike")); this.getSpellAbility().addEffect(new BoostTargetEffect(2, 0).setText("Target creature gets +2/+0")); this.getSpellAbility().addEffect(new GainAbilityTargetEffect( - FirstStrikeAbility.getInstance(), Duration.EndOfTurn, "and gains first strike until end of turn" + FirstStrikeAbility.getInstance(), Duration.EndOfTurn, + "and gains first strike until end of turn" )); - - target = new TargetCreaturePermanent(0, 1, filter2, false); - target.setTargetTag(2); - this.getSpellAbility().addTarget(target.withChooseHint("+0/+2 and lifelink")); + this.getSpellAbility().addTarget(new TargetPermanent(0, 1, filter2) + .setTargetTag(2).withChooseHint("+0/+2 and lifelink")); this.getSpellAbility().addEffect(new BoostTargetEffect(0, 2) .setText("Up to one other target creature gets +0/+2") .setTargetPointer(new SecondTargetPointer()) ); - this.getSpellAbility().addEffect( - new GainAbilityTargetEffect(LifelinkAbility.getInstance(), Duration.EndOfTurn, "and gains lifelink until end of turn") - .setTargetPointer(new SecondTargetPointer()) - ); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect( + LifelinkAbility.getInstance(), Duration.EndOfTurn, + "and gains lifelink until end of turn" + ).setTargetPointer(new SecondTargetPointer())); } private RallyManeuver(final RallyManeuver card) { diff --git a/Mage.Sets/src/mage/cards/r/RallyTheMonastery.java b/Mage.Sets/src/mage/cards/r/RallyTheMonastery.java index 7867c2c0c48..dae91cbf035 100644 --- a/Mage.Sets/src/mage/cards/r/RallyTheMonastery.java +++ b/Mage.Sets/src/mage/cards/r/RallyTheMonastery.java @@ -1,7 +1,5 @@ package mage.cards.r; -import java.util.UUID; - import mage.abilities.Mode; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.CastAnotherSpellThisTurnCondition; @@ -14,13 +12,14 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.Zone; -import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; import mage.game.permanent.token.MonasteryMentorToken; import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; +import java.util.UUID; + /** * @author balazskristof */ @@ -44,16 +43,16 @@ public final class RallyTheMonastery extends CardImpl { // Choose one — this.getSpellAbility().getModes().setMinModes(1); this.getSpellAbility().getModes().setMaxModes(1); + // • Create two 1/1 white Monk creature tokens with prowess. this.getSpellAbility().addEffect(new CreateTokenEffect(new MonasteryMentorToken(), 2)); + // • Up to two target creatures you control each get +2/+2 until end of turn. - Mode mode = new Mode(new BoostTargetEffect(2, 2)); - mode.addTarget(new TargetControlledCreaturePermanent(0, 2, StaticFilters.FILTER_CONTROLLED_CREATURES, false)); - this.getSpellAbility().getModes().addMode(mode); + this.getSpellAbility().getModes().addMode(new Mode(new BoostTargetEffect(2, 2)) + .addTarget(new TargetControlledCreaturePermanent(0, 2))); + // • Destroy target creature with power 4 or greater. - Mode mode2 = new Mode(new DestroyTargetEffect()); - mode2.addTarget(new TargetPermanent(filter)); - this.getSpellAbility().getModes().addMode(mode2); + this.getSpellAbility().getModes().addMode(new Mode(new DestroyTargetEffect()).addTarget(new TargetPermanent(filter))); } private RallyTheMonastery(final RallyTheMonastery card) { @@ -65,4 +64,3 @@ public final class RallyTheMonastery extends CardImpl { return new RallyTheMonastery(this); } } - diff --git a/Mage.Sets/src/mage/cards/r/RalsStaticaster.java b/Mage.Sets/src/mage/cards/r/RalsStaticaster.java index d05013c785b..3745ab51b15 100644 --- a/Mage.Sets/src/mage/cards/r/RalsStaticaster.java +++ b/Mage.Sets/src/mage/cards/r/RalsStaticaster.java @@ -1,35 +1,30 @@ package mage.cards.r; -import java.util.UUID; 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.dynamicvalue.common.CardsInControllerHandCount; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.common.continuous.BoostSourceEffect; -import mage.constants.SubType; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.TargetController; -import mage.filter.FilterPermanent; +import mage.constants.SubType; +import mage.filter.common.FilterControlledPlaneswalkerPermanent; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class RalsStaticaster extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("a Ral planeswalker"); - - static { - filter.add(TargetController.YOU.getControllerPredicate()); - filter.add(CardType.PLANESWALKER.getPredicate()); - filter.add(SubType.RAL.getPredicate()); - } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPlaneswalkerPermanent(SubType.RAL, "you control a Ral planeswalker") + ); public RalsStaticaster(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{R}"); @@ -43,14 +38,9 @@ public final class RalsStaticaster extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // Whenever Ral's Staticaster attacks, if you control a Ral planeswalker, Ral's Staticaster gets +1/+0 for each card in your hand until end of turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new BoostSourceEffect( - CardsInControllerHandCount.ANY, StaticValue.get(0), - Duration.EndOfTurn), false), - new PermanentsOnTheBattlefieldCondition(filter), - "Whenever {this} attacks, if you control a Ral planeswalker, " - + "{this} gets +1/+0 for each card in your hand until end of turn." - )); + this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect( + CardsInControllerHandCount.ANY, StaticValue.get(0), Duration.EndOfTurn + ).setText("this creature gets +1/+0 for each card in your hand until end of turn")).withInterveningIf(condition)); } private RalsStaticaster(final RalsStaticaster card) { diff --git a/Mage.Sets/src/mage/cards/r/RamThrough.java b/Mage.Sets/src/mage/cards/r/RamThrough.java index 0dbccc0a842..582f0ccb988 100644 --- a/Mage.Sets/src/mage/cards/r/RamThrough.java +++ b/Mage.Sets/src/mage/cards/r/RamThrough.java @@ -11,11 +11,14 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author TheElk801 */ @@ -27,7 +30,7 @@ public final class RamThrough extends CardImpl { // Target creature you control deals damage equal to its power to target creature you don't control. If the creature you control has trample, excess damage is dealt to that creature's controller instead. this.getSpellAbility().addEffect(new RamThroughEffect()); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); } private RamThrough(final RamThrough card) { diff --git a/Mage.Sets/src/mage/cards/r/RampagingRaptor.java b/Mage.Sets/src/mage/cards/r/RampagingRaptor.java index bf4ee11f65b..4f69d51409a 100644 --- a/Mage.Sets/src/mage/cards/r/RampagingRaptor.java +++ b/Mage.Sets/src/mage/cards/r/RampagingRaptor.java @@ -1,7 +1,8 @@ package mage.cards.r; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; +import mage.abilities.common.DealsDamageToOpponentTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.dynamicvalue.common.SavedDamageValue; @@ -14,16 +15,15 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.FilterPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.filter.predicate.permanent.ProtectorIdPredicate; import mage.game.Game; -import mage.game.events.DamagedEvent; -import mage.game.events.GameEvent; import mage.players.Player; import mage.target.TargetPermanent; +import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetpointer.FirstTargetPointer; import java.util.UUID; @@ -51,7 +51,10 @@ public final class RampagingRaptor extends CardImpl { )); // Whenever Rampaging Raptor deals combat damage to an opponent, it deals that much damage to target planeswalker that player controls or battle that player protects. - this.addAbility(new RampagingRaptorTriggeredAbility()); + Ability ability = new DealsDamageToOpponentTriggeredAbility(new DamageTargetEffect(SavedDamageValue.MUCH) + .withTargetDescription("target planeswalker that player controls or battle that player protects"), false, true, true); + ability.setTargetAdjuster(RampagingRaptorTargetAdjuster.instance); + this.addAbility(ability); } private RampagingRaptor(final RampagingRaptor card) { @@ -64,33 +67,17 @@ public final class RampagingRaptor extends CardImpl { } } -class RampagingRaptorTriggeredAbility extends TriggeredAbilityImpl { - - RampagingRaptorTriggeredAbility() { - super(Zone.BATTLEFIELD, new DamageTargetEffect(SavedDamageValue.MUCH), false); - } - - private RampagingRaptorTriggeredAbility(final RampagingRaptorTriggeredAbility ability) { - super(ability); - } +enum RampagingRaptorTargetAdjuster implements TargetAdjuster { + instance; @Override - public RampagingRaptorTriggeredAbility copy() { - return new RampagingRaptorTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - Player opponent = game.getPlayer(event.getPlayerId()); - if (opponent == null - || !event.getSourceId().equals(this.getSourceId()) - || !((DamagedEvent) event).isCombatDamage()) { - return false; + public void adjustTargets(Ability ability, Game game) { + UUID opponentId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability); + Player opponent = game.getPlayer(opponentId); + ability.getTargets().clear(); + ability.getAllEffects().setTargetPointer(new FirstTargetPointer()); + if (opponent == null) { + return; } FilterPermanent filter = new FilterPermanent( "planeswalker " + opponent.getLogName() + " controls " + @@ -106,15 +93,6 @@ class RampagingRaptorTriggeredAbility extends TriggeredAbilityImpl { new ProtectorIdPredicate(opponent.getId()) ) )); - this.getEffects().setValue("damage", event.getAmount()); - this.getTargets().clear(); - this.addTarget(new TargetPermanent(filter)); - return true; - } - - @Override - public String getRule() { - return "Whenever {this} deals combat damage to an opponent, it deals that much damage " + - "to target planeswalker that player controls or battle that player protects."; + ability.addTarget(new TargetPermanent(filter)); } } diff --git a/Mage.Sets/src/mage/cards/r/RampagingWarMammoth.java b/Mage.Sets/src/mage/cards/r/RampagingWarMammoth.java index 36302890eb2..af293b7cbfc 100644 --- a/Mage.Sets/src/mage/cards/r/RampagingWarMammoth.java +++ b/Mage.Sets/src/mage/cards/r/RampagingWarMammoth.java @@ -1,22 +1,21 @@ package mage.cards.r; import mage.MageInt; -import mage.abilities.common.ZoneChangeTriggeredAbility; +import mage.abilities.Ability; +import mage.abilities.common.CycleTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.EffectKeyValue; import mage.abilities.effects.common.DestroyTargetEffect; -import mage.abilities.hint.StaticHint; import mage.abilities.keyword.CyclingAbility; import mage.abilities.keyword.TrampleAbility; 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.stack.StackObject; -import mage.target.common.TargetArtifactPermanent; -import mage.util.CardUtil; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterArtifactPermanent; +import mage.target.TargetPermanent; +import mage.target.targetadjustment.TargetsCountAdjuster; import java.util.UUID; @@ -25,6 +24,8 @@ import java.util.UUID; */ public final class RampagingWarMammoth extends CardImpl { + private static final FilterPermanent filter = new FilterArtifactPermanent("up to X target artifacts"); + public RampagingWarMammoth(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{R}{R}"); @@ -39,7 +40,10 @@ public final class RampagingWarMammoth extends CardImpl { this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{X}{2}{R}"))); // When you cycle Rampaging War Mammoth, destroy up to X target artifacts. - this.addAbility(new RampagingWarMammothTriggeredAbility()); + Ability ability = new CycleTriggeredAbility(new DestroyTargetEffect()); + ability.addTarget(new TargetPermanent(0,1, filter)); + ability.setTargetAdjuster(new TargetsCountAdjuster(new EffectKeyValue("cycleXValue"))); + this.addAbility(ability); } private RampagingWarMammoth(final RampagingWarMammoth card) { @@ -51,56 +55,3 @@ public final class RampagingWarMammoth extends CardImpl { return new RampagingWarMammoth(this); } } - -class RampagingWarMammothTriggeredAbility extends ZoneChangeTriggeredAbility { - - RampagingWarMammothTriggeredAbility() { - super(Zone.ALL, null, "", false); - } - - private RampagingWarMammothTriggeredAbility(RampagingWarMammothTriggeredAbility ability) { - super(ability); - } - - @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.getSourceId().equals(this.getSourceId())) { - return false; - } - StackObject object = game.getStack().getStackObject(event.getSourceId()); - if (object == null || !(object.getStackAbility() instanceof CyclingAbility)) { - return false; - } - - CyclingAbility cyclingAbility = (CyclingAbility) object.getStackAbility(); - // If X is 0, or cycling from another ability that does not have {X} in cost, - // this should trigger (but do nothing). - int xValue = CardUtil.getSourceCostsTag(game, cyclingAbility, "X", 0); - - this.getEffects().clear(); - this.getTargets().clear(); - - this.addEffect(new DestroyTargetEffect()); - // Target up to X artifacts - this.addTarget(new TargetArtifactPermanent(0, xValue)); - this.getHints().clear(); - this.addHint(new StaticHint("X = " + xValue)); - - return true; - } - - @Override - public RampagingWarMammothTriggeredAbility copy() { - return new RampagingWarMammothTriggeredAbility(this); - } - - @Override - public String getRule() { - return "When you cycle {this}, destroy up to X target artifacts."; - } -} diff --git a/Mage.Sets/src/mage/cards/r/RamsesOverdark.java b/Mage.Sets/src/mage/cards/r/RamsesOverdark.java index 93a86234a2a..458b4a8f126 100644 --- a/Mage.Sets/src/mage/cards/r/RamsesOverdark.java +++ b/Mage.Sets/src/mage/cards/r/RamsesOverdark.java @@ -15,6 +15,7 @@ import mage.constants.SuperType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.EnchantedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -39,7 +40,7 @@ public final class RamsesOverdark extends CardImpl { // {tap}: Destroy target enchanted creature. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RasaadYnBashir.java b/Mage.Sets/src/mage/cards/r/RasaadYnBashir.java index 1eb28c1e9d6..1aafde868bd 100644 --- a/Mage.Sets/src/mage/cards/r/RasaadYnBashir.java +++ b/Mage.Sets/src/mage/cards/r/RasaadYnBashir.java @@ -6,7 +6,6 @@ import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.ChooseABackgroundAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.HaveInitiativeCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessControlledEffect; @@ -42,11 +41,8 @@ public final class RasaadYnBashir extends CardImpl { this.addAbility(new SimpleStaticAbility(new CombatDamageByToughnessControlledEffect())); // Whenever Rasaad yn Bashir attacks, if you have the initiative, double the toughness of each creature you control until end of turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new RasaadYnBashirEffect()), - HaveInitiativeCondition.instance, "Whenever {this} attacks, if you have the initiative, " + - "double the toughness of each creature you control until end of turn." - ).addHint(InitiativeHint.instance)); + this.addAbility(new AttacksTriggeredAbility(new RasaadYnBashirEffect()) + .withInterveningIf(HaveInitiativeCondition.instance).addHint(InitiativeHint.instance)); // Choose a Background this.addAbility(ChooseABackgroundAbility.getInstance()); @@ -66,6 +62,7 @@ class RasaadYnBashirEffect extends OneShotEffect { RasaadYnBashirEffect() { super(Outcome.Benefit); + staticText = "double the toughness of each creature you control until end of turn"; } private RasaadYnBashirEffect(final RasaadYnBashirEffect effect) { diff --git a/Mage.Sets/src/mage/cards/r/RashidaScalebane.java b/Mage.Sets/src/mage/cards/r/RashidaScalebane.java index 9e93758cf35..aa4bdce442d 100644 --- a/Mage.Sets/src/mage/cards/r/RashidaScalebane.java +++ b/Mage.Sets/src/mage/cards/r/RashidaScalebane.java @@ -20,6 +20,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.AttackingPredicate; import mage.filter.predicate.permanent.BlockingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -48,7 +49,7 @@ public final class RashidaScalebane extends CardImpl { Effect effect = new GainLifeEffect(TargetPermanentPowerCount.instance); effect.setText("You gain life equal to its power"); ability.addEffect(effect); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RasputinDreamweaver.java b/Mage.Sets/src/mage/cards/r/RasputinDreamweaver.java index ae03012f912..d499b452b17 100644 --- a/Mage.Sets/src/mage/cards/r/RasputinDreamweaver.java +++ b/Mage.Sets/src/mage/cards/r/RasputinDreamweaver.java @@ -1,23 +1,18 @@ - package mage.cards.r; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.MageInt; import mage.Mana; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.CantHaveMoreThanAmountCountersSourceAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.common.RemoveCountersSourceCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.PreventDamageToSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.mana.SimpleManaAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -28,6 +23,10 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.watchers.Watcher; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + /** * @author emerald000 */ @@ -43,23 +42,29 @@ public final class RasputinDreamweaver extends CardImpl { this.toughness = new MageInt(1); // Rasputin Dreamweaver enters the battlefield with seven dream counters on it. - this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.DREAM.createInstance(7)), "with seven dream counters on it")); + this.addAbility(new EntersBattlefieldAbility( + new AddCountersSourceEffect(CounterType.DREAM.createInstance(7)), + "with seven dream counters on it" + )); // Remove a dream counter from Rasputin: Add {C}. - this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, Mana.ColorlessMana(1), + this.addAbility(new SimpleManaAbility( + Zone.BATTLEFIELD, Mana.ColorlessMana(1), new RemoveCountersSourceCost(CounterType.DREAM.createInstance()), - new CountersSourceCount(CounterType.DREAM))); + new CountersSourceCount(CounterType.DREAM) + )); // Remove a dream counter from Rasputin: Prevent the next 1 damage that would be dealt to Rasputin this turn. - this.addAbility(new SimpleActivatedAbility(new PreventDamageToSourceEffect(Duration.EndOfTurn, 1), new RemoveCountersSourceCost(CounterType.DREAM.createInstance()))); + this.addAbility(new SimpleActivatedAbility( + new PreventDamageToSourceEffect(Duration.EndOfTurn, 1), + new RemoveCountersSourceCost(CounterType.DREAM.createInstance()) + )); // At the beginning of your upkeep, if Rasputin started the turn untapped, put a dream counter on it. - this.addAbility( - new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.DREAM.createInstance())), - RasputinDreamweaverStartedUntappedCondition.instance, - "At the beginning of your upkeep, if {this} started the turn untapped, put a dream counter on it."), - new RasputinDreamweaverStartedUntappedWatcher()); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new AddCountersSourceEffect(CounterType.DREAM.createInstance()) + .setText("put a dream counter on it") + ).withInterveningIf(RasputinDreamweaverCondition.instance), new RasputinDreamweaverWatcher()); // Rasputin can't have more than seven dream counters on it. this.addAbility(new CantHaveMoreThanAmountCountersSourceAbility(CounterType.DREAM, 7)); @@ -75,17 +80,12 @@ public final class RasputinDreamweaver extends CardImpl { } } -enum RasputinDreamweaverStartedUntappedCondition implements Condition { - +enum RasputinDreamweaverCondition implements Condition { instance; @Override public boolean apply(Game game, Ability source) { - RasputinDreamweaverStartedUntappedWatcher watcher = game.getState().getWatcher(RasputinDreamweaverStartedUntappedWatcher.class); - if (watcher != null) { - return watcher.startedUntapped(source.getSourceId()); - } - return false; + return game.getState().getWatcher(RasputinDreamweaverWatcher.class).startedUntapped(source.getSourceId()); } @Override @@ -94,9 +94,9 @@ enum RasputinDreamweaverStartedUntappedCondition implements Condition { } } -class RasputinDreamweaverStartedUntappedWatcher extends Watcher { +class RasputinDreamweaverWatcher extends Watcher { - private static final FilterPermanent filter = new FilterPermanent("Untapped permanents"); + private static final FilterPermanent filter = new FilterPermanent(); static { filter.add(TappedPredicate.UNTAPPED); @@ -104,7 +104,7 @@ class RasputinDreamweaverStartedUntappedWatcher extends Watcher { private final Set startedUntapped = new HashSet<>(0); - RasputinDreamweaverStartedUntappedWatcher() { + RasputinDreamweaverWatcher() { super(WatcherScope.GAME); } diff --git a/Mage.Sets/src/mage/cards/r/RathiAssassin.java b/Mage.Sets/src/mage/cards/r/RathiAssassin.java index 7e5ae73b63b..6f70b089eeb 100644 --- a/Mage.Sets/src/mage/cards/r/RathiAssassin.java +++ b/Mage.Sets/src/mage/cards/r/RathiAssassin.java @@ -23,6 +23,7 @@ import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetCreaturePermanent; @@ -55,7 +56,7 @@ public final class RathiAssassin extends CardImpl { // {1}{B}{B}, {T}: Destroy target tapped nonblack creature. Ability destroyAbility = new SimpleActivatedAbility(new DestroyTargetEffect(), new ManaCostsImpl<>("{1}{B}{B}")); destroyAbility.addCost(new TapSourceCost()); - destroyAbility.addTarget(new TargetCreaturePermanent(destroyFilter)); + destroyAbility.addTarget(new TargetPermanent(destroyFilter)); this.addAbility(destroyAbility); // {3}, {T}: Search your library for a Mercenary permanent card with converted mana cost 3 or less and put it onto the battlefield. Then shuffle your library. diff --git a/Mage.Sets/src/mage/cards/r/Rattlechains.java b/Mage.Sets/src/mage/cards/r/Rattlechains.java index d26b1938ae8..5d12df82102 100644 --- a/Mage.Sets/src/mage/cards/r/Rattlechains.java +++ b/Mage.Sets/src/mage/cards/r/Rattlechains.java @@ -19,6 +19,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -49,7 +50,7 @@ public final class Rattlechains extends CardImpl { // When Rattlechains enters the battlefield, target spirit gains hexproof until end of turn. Ability ability = new EntersBattlefieldTriggeredAbility(new GainAbilityTargetEffect(HexproofAbility.getInstance(), Duration.EndOfTurn), false); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // You may cast Spirit spells as though they had flash. diff --git a/Mage.Sets/src/mage/cards/r/RavenloftAdventurer.java b/Mage.Sets/src/mage/cards/r/RavenloftAdventurer.java index 61630d1b877..089f9f62d12 100644 --- a/Mage.Sets/src/mage/cards/r/RavenloftAdventurer.java +++ b/Mage.Sets/src/mage/cards/r/RavenloftAdventurer.java @@ -6,7 +6,6 @@ import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.CompletedDungeonCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.TakeTheInitiativeEffect; @@ -46,12 +45,9 @@ public final class RavenloftAdventurer extends CardImpl { this.addAbility(new SimpleStaticAbility(new RavenloftAdventurerReplacementEffect())); // Whenever Ravenloft Adventurer attacks, if you've completed a dungeon, defending player loses 1 life for each card they own in exile with a hit counter on it. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility( - new RavenloftAdventurerLifeEffect(), false, "", SetTargetPointer.PLAYER - ), CompletedDungeonCondition.instance, "Whenever {this} attacks, if you've completed a dungeon, " + - "defending player loses 1 life for each card they own in exile with a hit counter on it." - ).addHint(CompletedDungeonCondition.getHint()), new CompletedDungeonWatcher()); + this.addAbility(new AttacksTriggeredAbility( + new RavenloftAdventurerLifeEffect(), false, "", SetTargetPointer.PLAYER + ).withInterveningIf(CompletedDungeonCondition.instance).addHint(CompletedDungeonCondition.getHint()), new CompletedDungeonWatcher()); } private RavenloftAdventurer(final RavenloftAdventurer card) { @@ -108,6 +104,7 @@ class RavenloftAdventurerLifeEffect extends OneShotEffect { RavenloftAdventurerLifeEffect() { super(Outcome.Benefit); + staticText = "defending player loses 1 life for each card they own in exile with a hit counter on it"; } private RavenloftAdventurerLifeEffect(final RavenloftAdventurerLifeEffect effect) { diff --git a/Mage.Sets/src/mage/cards/r/RavenousChupacabra.java b/Mage.Sets/src/mage/cards/r/RavenousChupacabra.java index 32fad1fc866..b48c7c2bfd0 100644 --- a/Mage.Sets/src/mage/cards/r/RavenousChupacabra.java +++ b/Mage.Sets/src/mage/cards/r/RavenousChupacabra.java @@ -11,8 +11,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author L_J @@ -28,7 +31,7 @@ public final class RavenousChupacabra extends CardImpl { // When Ravenous Chupacabra enters the battlefield, destroy target creature an opponent controls. Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RavenousGigantotherium.java b/Mage.Sets/src/mage/cards/r/RavenousGigantotherium.java index eeaacab7a2b..1e877367a4f 100644 --- a/Mage.Sets/src/mage/cards/r/RavenousGigantotherium.java +++ b/Mage.Sets/src/mage/cards/r/RavenousGigantotherium.java @@ -3,6 +3,8 @@ package mage.cards.r; 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.OneShotEffect; import mage.abilities.effects.common.DamageMultiEffect; import mage.abilities.keyword.DevourAbility; @@ -12,10 +14,10 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; import mage.game.Game; -import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.target.Target; import mage.target.common.TargetCreaturePermanentAmount; +import mage.util.CardUtil; import java.util.Collection; import java.util.List; @@ -39,7 +41,11 @@ public final class RavenousGigantotherium extends CardImpl { this.addAbility(new DevourAbility(3)); // When Ravenous Gigantotherium enters the battlefield, it deals X damage divided as you choose among up to X target creatures, where X is its power. Each of those creatures deals damage equal to its power to Ravenous Gigantotherium. - this.addAbility(new RavenousGigantotheriumAbility()); + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageMultiEffect()); + ability.addEffect(new RavenousGigantotheriumEffect()); + ability.addTarget(new TargetCreaturePermanentAmount(RavenousGigantotheriumAmount.instance) + .withTargetName("up to X target creatures, where X is its power")); + this.addAbility(ability); } private RavenousGigantotherium(final RavenousGigantotherium card) { @@ -52,47 +58,28 @@ public final class RavenousGigantotherium extends CardImpl { } } -class RavenousGigantotheriumAbility extends EntersBattlefieldTriggeredAbility { +enum RavenousGigantotheriumAmount implements DynamicValue { + instance; - RavenousGigantotheriumAbility() { - super(null, false); - } - - private RavenousGigantotheriumAbility(final RavenousGigantotheriumAbility ability) { - super(ability); + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + return CardUtil.getEffectValueFromAbility(sourceAbility, "permanentEnteredBattlefield", Permanent.class) + .map(permanent -> permanent.getPower().getValue()).orElse(0); } @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (!super.checkTrigger(event, game)) { - return false; - } - Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); - if (permanent == null) { - return false; - } - int power = Math.max(permanent.getPower().getValue(), 0); - this.getEffects().clear(); - this.addEffect(new DamageMultiEffect()); - this.addEffect(new RavenousGigantotheriumEffect()); - this.getTargets().clear(); - if (power < 1) { - return true; - } - this.addTarget(new TargetCreaturePermanentAmount(power, 0, power)); - return true; + public DynamicValue copy() { + return instance; } @Override - public String getRule() { - return "When {this} enters, it deals X damage " + - "divided as you choose among up to X target creatures, where X is its power. " + - "Each of those creatures deals damage equal to its power to {this}."; + public String getMessage() { + return "its power"; } @Override - public RavenousGigantotheriumAbility copy() { - return new RavenousGigantotheriumAbility(this); + public String toString() { + return "X"; } } @@ -100,6 +87,7 @@ class RavenousGigantotheriumEffect extends OneShotEffect { RavenousGigantotheriumEffect() { super(Outcome.Benefit); + this.setText("Each of those creatures deals damage equal to its power to {this}."); } private RavenousGigantotheriumEffect(final RavenousGigantotheriumEffect effect) { diff --git a/Mage.Sets/src/mage/cards/r/RavenousTyrannosaurus.java b/Mage.Sets/src/mage/cards/r/RavenousTyrannosaurus.java index 64b0cdab0ef..7460dc4fbfc 100644 --- a/Mage.Sets/src/mage/cards/r/RavenousTyrannosaurus.java +++ b/Mage.Sets/src/mage/cards/r/RavenousTyrannosaurus.java @@ -12,12 +12,11 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; /** - * * @author notgreat */ public final class RavenousTyrannosaurus extends CardImpl { @@ -27,6 +26,7 @@ public final class RavenousTyrannosaurus extends CardImpl { static { filter.add(AnotherPredicate.instance); } + public RavenousTyrannosaurus(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}{G}"); this.subtype.add(SubType.DINOSAUR); @@ -39,7 +39,7 @@ public final class RavenousTyrannosaurus extends CardImpl { // Whenever Ravenous Tyrannosaurus attacks, it deals damage equal to its power to up to one other target creature. Excess damage is dealt to that creature's controller instead. Ability ability = new AttacksTriggeredAbility(new DamageWithExcessEffect(SourcePermanentPowerValue.NOT_NEGATIVE) .setText("it deals damage equal to its power to up to one other target creature. Excess damage is dealt to that creature's controller instead.")); - ability.addTarget(new TargetCreaturePermanent(0, 1, filter, false)); + ability.addTarget(new TargetPermanent(0, 1, filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RavingVisionary.java b/Mage.Sets/src/mage/cards/r/RavingVisionary.java index 5703d4286b3..2ccbbb7cf33 100644 --- a/Mage.Sets/src/mage/cards/r/RavingVisionary.java +++ b/Mage.Sets/src/mage/cards/r/RavingVisionary.java @@ -15,7 +15,6 @@ import mage.cards.CardSetInfo; import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import java.util.UUID; @@ -41,8 +40,7 @@ public final class RavingVisionary extends CardImpl { // Delirium — {2}{U}, {T}: Draw a card. Activate only if there are four or more card types among cards in your graveyard. ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), - new ManaCostsImpl<>("{2}{U}"), DeliriumCondition.instance + new DrawCardSourceControllerEffect(1), new ManaCostsImpl<>("{2}{U}"), DeliriumCondition.instance ); ability.addCost(new TapSourceCost()); this.addAbility(ability.addHint(CardTypesInGraveyardCount.YOU.getHint()).setAbilityWord(AbilityWord.DELIRIUM)); diff --git a/Mage.Sets/src/mage/cards/r/RayOfCommand.java b/Mage.Sets/src/mage/cards/r/RayOfCommand.java index dc57a6e4f06..def359df27c 100644 --- a/Mage.Sets/src/mage/cards/r/RayOfCommand.java +++ b/Mage.Sets/src/mage/cards/r/RayOfCommand.java @@ -16,8 +16,11 @@ import mage.constants.Duration; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -32,7 +35,7 @@ public final class RayOfCommand extends CardImpl { this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.EndOfTurn).setText("and gain control of it until end of turn")); this.getSpellAbility().addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn).setText("that creature gains haste until end of turn")); this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new RayOfCommandDelayedTriggeredAbility(), true)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); } private RayOfCommand(final RayOfCommand card) { diff --git a/Mage.Sets/src/mage/cards/r/RayOfFrost.java b/Mage.Sets/src/mage/cards/r/RayOfFrost.java index 1fc0da9b8cb..1f5773ee892 100644 --- a/Mage.Sets/src/mage/cards/r/RayOfFrost.java +++ b/Mage.Sets/src/mage/cards/r/RayOfFrost.java @@ -1,32 +1,44 @@ package mage.cards.r; -import java.util.UUID; - +import mage.ObjectColor; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.condition.common.AttachedToMatchesFilterCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.DontUntapInControllersUntapStepEnchantedEffect; import mage.abilities.effects.common.TapEnchantedEffect; -import mage.constants.*; -import mage.abilities.keyword.FlashAbility; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.target.common.TargetCreaturePermanent; -import mage.abilities.Ability; -import mage.abilities.effects.common.AttachEffect; -import mage.target.TargetPermanent; +import mage.abilities.effects.common.continuous.LoseAllAbilitiesAttachedEffect; import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.FlashAbility; 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.filter.FilterPermanent; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; /** - * * @author weirddan455 */ public final class RayOfFrost extends CardImpl { + private static final FilterPermanent filter = new FilterPermanent("enchanted creature is red"); + + static { + filter.add(new ColorPredicate(ObjectColor.RED)); + } + + private static final Condition condition = new AttachedToMatchesFilterCondition(filter); + public RayOfFrost(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); @@ -43,14 +55,15 @@ public final class RayOfFrost extends CardImpl { this.addAbility(ability); // When Ray of Frost enters the battlefield, if enchanted creature is red, tap it. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new TapEnchantedEffect()), - RayOfFrostCondition.instance, - "When {this} enters, if enchanted creature is red, tap it." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new TapEnchantedEffect().setText("tap it") + ).withInterveningIf(condition)); // As long as enchanted creature is red, it loses all abilities. - this.addAbility(new SimpleStaticAbility(new RayOfFrostLoseAbilitiesEffect())); + this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect( + new LoseAllAbilitiesAttachedEffect(AttachmentType.AURA), condition, + "as long as enchanted creature is red, it loses all abilities" + ))); // Enchanted creature doesn't untap during its controller's untap step. this.addAbility(new SimpleStaticAbility(new DontUntapInControllersUntapStepEnchantedEffect())); @@ -65,52 +78,3 @@ public final class RayOfFrost extends CardImpl { return new RayOfFrost(this); } } - -enum RayOfFrostCondition implements Condition { - instance; - - @Override - public boolean apply(Game game, Ability source) { - Permanent enchantment = source.getSourcePermanentIfItStillExists(game); - if (enchantment == null) { - return false; - } - Permanent creature = game.getPermanent(enchantment.getAttachedTo()); - return creature != null && creature.getColor(game).isRed(); - } - - @Override - public String toString() { - return "if enchanted creature is red"; - } -} - -class RayOfFrostLoseAbilitiesEffect extends ContinuousEffectImpl { - - RayOfFrostLoseAbilitiesEffect() { - super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.LoseAbility); - this.staticText = "As long as enchanted creature is red, it loses all abilities"; - } - - private RayOfFrostLoseAbilitiesEffect(final RayOfFrostLoseAbilitiesEffect effect) { - super(effect); - } - - @Override - public RayOfFrostLoseAbilitiesEffect copy() { - return new RayOfFrostLoseAbilitiesEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent enchantment = source.getSourcePermanentIfItStillExists(game); - if (enchantment != null) { - Permanent creature = game.getPermanent(enchantment.getAttachedTo()); - if (creature != null && creature.getColor(game).isRed()) { - creature.removeAllAbilities(source.getSourceId(), game); - return true; - } - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/r/RaziaBorosArchangel.java b/Mage.Sets/src/mage/cards/r/RaziaBorosArchangel.java index efe756e5831..319e6cd964d 100644 --- a/Mage.Sets/src/mage/cards/r/RaziaBorosArchangel.java +++ b/Mage.Sets/src/mage/cards/r/RaziaBorosArchangel.java @@ -24,6 +24,7 @@ import mage.filter.predicate.other.AnotherTargetPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; @@ -59,7 +60,7 @@ public final class RaziaBorosArchangel extends CardImpl { FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature (damage is redirected to)"); filter.add(new AnotherTargetPredicate(2)); - target = new TargetCreaturePermanent(filter); + target = new TargetPermanent(filter); target.setTargetTag(2); ability.addTarget(target); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/r/RazorPendulum.java b/Mage.Sets/src/mage/cards/r/RazorPendulum.java index 238040897a7..a611d207e30 100644 --- a/Mage.Sets/src/mage/cards/r/RazorPendulum.java +++ b/Mage.Sets/src/mage/cards/r/RazorPendulum.java @@ -1,17 +1,14 @@ package mage.cards.r; -import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.condition.common.LifeCompareCondition; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; +import mage.constants.ComparisonType; import mage.constants.TargetController; -import mage.game.Game; -import mage.players.Player; import java.util.UUID; @@ -20,17 +17,17 @@ import java.util.UUID; */ public final class RazorPendulum extends CardImpl { + private static final Condition condition = new LifeCompareCondition(TargetController.ACTIVE, ComparisonType.OR_LESS, 5); + public RazorPendulum(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); - // At the beginning of each player’s end step, if that player has 5 or less life, Razor Pendulum deals 2 damage to that player. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - TargetController.ANY, new RazorPendulumEffect(), false - ), RazorPendulumCondition.instance, "At the beginning of each player's end step, " + - "if that player has 5 or less life, {this} deals 2 damage to that player." - )); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.EACH_PLAYER, + new DamageTargetEffect(2, true, "that player"), + false, condition + ).withTargetPointerSet(true)); } private RazorPendulum(final RazorPendulum card) { @@ -42,41 +39,3 @@ public final class RazorPendulum extends CardImpl { return new RazorPendulum(this); } } - -class RazorPendulumEffect extends OneShotEffect { - - RazorPendulumEffect() { - super(Outcome.Benefit); - } - - private RazorPendulumEffect(final RazorPendulumEffect effect) { - super(effect); - } - - @Override - public RazorPendulumEffect copy() { - return new RazorPendulumEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(game.getActivePlayerId()); - if (player == null) { - return false; - } - return player.damage(2, source.getSourceId(), source, game) > 0; - } -} - -enum RazorPendulumCondition implements Condition { - instance; - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(game.getActivePlayerId()); - if (player == null) { - return false; - } - return player.getLife() < 6; - } -} diff --git a/Mage.Sets/src/mage/cards/r/RazorfinAbolisher.java b/Mage.Sets/src/mage/cards/r/RazorfinAbolisher.java index 5eb4ebe3cbf..8b97aa063d4 100644 --- a/Mage.Sets/src/mage/cards/r/RazorfinAbolisher.java +++ b/Mage.Sets/src/mage/cards/r/RazorfinAbolisher.java @@ -16,6 +16,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.CounterAnyPredicate; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -41,7 +42,7 @@ public final class RazorfinAbolisher extends CardImpl { // {1}{U}, {tap}: Return target creature with a counter on it to its owner's hand. Ability ability = new SimpleActivatedAbility(new ReturnToHandTargetEffect(), new ManaCostsImpl<>("{1}{U}")); ability.addCost(new TapSourceCost()); - Target target = new TargetCreaturePermanent(filter); + Target target = new TargetPermanent(filter); ability.addTarget(target); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/r/RazorgrassInvoker.java b/Mage.Sets/src/mage/cards/r/RazorgrassInvoker.java index 0bbced7dc8e..2bcaeed45fb 100644 --- a/Mage.Sets/src/mage/cards/r/RazorgrassInvoker.java +++ b/Mage.Sets/src/mage/cards/r/RazorgrassInvoker.java @@ -13,7 +13,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.filter.StaticFilters; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -36,7 +36,7 @@ public final class RazorgrassInvoker extends CardImpl { // {8}: Razorgrass Invoker and up to one other target creature each get +3/+3 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostSourceEffect(3, 3, Duration.EndOfTurn).setText("{this}"), new ManaCostsImpl<>("{8}")); ability.addEffect(new BoostTargetEffect(3, 3, Duration.EndOfTurn).setText("and up to one other target creature each get +3/+3 until end of turn")); - ability.addTarget(new TargetCreaturePermanent(0, 1, StaticFilters.FILTER_ANOTHER_TARGET_CREATURE, false)); + ability.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/ReachOfShadows.java b/Mage.Sets/src/mage/cards/r/ReachOfShadows.java index a956f8e6fd2..679bda0f4cc 100644 --- a/Mage.Sets/src/mage/cards/r/ReachOfShadows.java +++ b/Mage.Sets/src/mage/cards/r/ReachOfShadows.java @@ -9,6 +9,7 @@ import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorlessPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -28,7 +29,7 @@ public final class ReachOfShadows extends CardImpl { // Destroy target creature that's one or more colors. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private ReachOfShadows(final ReachOfShadows card) { diff --git a/Mage.Sets/src/mage/cards/r/RealmScorcherHellkite.java b/Mage.Sets/src/mage/cards/r/RealmScorcherHellkite.java index 979122cd0b7..c50c2dca1cd 100644 --- a/Mage.Sets/src/mage/cards/r/RealmScorcherHellkite.java +++ b/Mage.Sets/src/mage/cards/r/RealmScorcherHellkite.java @@ -6,7 +6,6 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.BargainedCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.mana.AddManaInAnyCombinationEffect; import mage.abilities.keyword.BargainAbility; @@ -42,11 +41,8 @@ public final class RealmScorcherHellkite extends CardImpl { this.addAbility(HasteAbility.getInstance()); // When Realm-Scorcher Hellkite enters the battlefield, if it was bargained, add four mana in any combination of colors. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new AddManaInAnyCombinationEffect(4)), - BargainedCondition.instance, - "When {this} enters, if it was bargained, add four mana in any combination of colors." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new AddManaInAnyCombinationEffect(4)) + .withInterveningIf(BargainedCondition.instance)); // {1}{R}: Realm-Scorcher Hellkite deals 1 damage to any target. Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new ManaCostsImpl<>("{1}{R}")); diff --git a/Mage.Sets/src/mage/cards/r/ReaperOfFlightMoonsilver.java b/Mage.Sets/src/mage/cards/r/ReaperOfFlightMoonsilver.java index 598639a9933..0426b23e070 100644 --- a/Mage.Sets/src/mage/cards/r/ReaperOfFlightMoonsilver.java +++ b/Mage.Sets/src/mage/cards/r/ReaperOfFlightMoonsilver.java @@ -1,23 +1,22 @@ package mage.cards.r; -import java.util.UUID; - import mage.MageInt; import mage.abilities.condition.common.DeliriumCondition; import mage.abilities.costs.common.SacrificeTargetCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; - import mage.filter.StaticFilters; +import java.util.UUID; + /** * @author fireshoes */ @@ -34,13 +33,10 @@ public final class ReaperOfFlightMoonsilver extends CardImpl { // Delirium — Sacrifice another creature: Reaper of Flight Moonsilver gets +2/+1 until end of turn. // Activate this ability only if there are four or more card types among cards in your graveyard. - this.addAbility(new ConditionalActivatedAbility(Zone.BATTLEFIELD, + this.addAbility(new ActivateIfConditionActivatedAbility( new BoostSourceEffect(2, 1, Duration.EndOfTurn), - new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_CREATURE), - DeliriumCondition.instance, - "Delirium — Sacrifice another creature: Reaper of Flight Moonsilver gets +2/+1 until end of turn. " - + "Activate only if there are four or more card types among cards in your graveyard.") - .addHint(CardTypesInGraveyardCount.YOU.getHint())); + new SacrificeTargetCost(StaticFilters.FILTER_ANOTHER_CREATURE), DeliriumCondition.instance + ).setAbilityWord(AbilityWord.DELIRIUM).addHint(CardTypesInGraveyardCount.YOU.getHint())); } private ReaperOfFlightMoonsilver(final ReaperOfFlightMoonsilver card) { diff --git a/Mage.Sets/src/mage/cards/r/ReaperOfNight.java b/Mage.Sets/src/mage/cards/r/ReaperOfNight.java index c65a5f356a9..b36da00f5c6 100644 --- a/Mage.Sets/src/mage/cards/r/ReaperOfNight.java +++ b/Mage.Sets/src/mage/cards/r/ReaperOfNight.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.abilities.keyword.FlyingAbility; @@ -32,12 +31,9 @@ public final class ReaperOfNight extends AdventureCard { this.toughness = new MageInt(5); // Whenever Reaper of Night attacks, if defending player has two or fewer cards in hand, it gains flying until end of turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new GainAbilitySourceEffect( - FlyingAbility.getInstance(), Duration.EndOfTurn - ), false), ReaperOfNightCondition.instance, "Whenever {this} attacks, " + - "if defending player has two or fewer cards in hand, it gains flying until end of turn." - )); + this.addAbility(new AttacksTriggeredAbility(new GainAbilitySourceEffect( + FlyingAbility.getInstance(), Duration.EndOfTurn + ).setText("it gains flying until end of turn")).withInterveningIf(ReaperOfNightCondition.instance)); // Harvest Fear // Target opponent discards two cards. @@ -65,4 +61,9 @@ enum ReaperOfNightCondition implements Condition { Player player = game.getPlayer(game.getCombat().getDefendingPlayerId(source.getSourceId(), game)); return player != null && player.getHand().size() <= 2; } -} \ No newline at end of file + + @Override + public String toString() { + return "defending player has two or fewer cards in hand"; + } +} diff --git a/Mage.Sets/src/mage/cards/r/ReaveSoul.java b/Mage.Sets/src/mage/cards/r/ReaveSoul.java index f128744f362..84095ae479e 100644 --- a/Mage.Sets/src/mage/cards/r/ReaveSoul.java +++ b/Mage.Sets/src/mage/cards/r/ReaveSoul.java @@ -9,6 +9,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -28,7 +29,7 @@ public final class ReaveSoul extends CardImpl { // Destroy target creature with power 3 or less. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private ReaveSoul(final ReaveSoul card) { diff --git a/Mage.Sets/src/mage/cards/r/ReaverAmbush.java b/Mage.Sets/src/mage/cards/r/ReaverAmbush.java index c9724a11924..8a273c9ba5c 100644 --- a/Mage.Sets/src/mage/cards/r/ReaverAmbush.java +++ b/Mage.Sets/src/mage/cards/r/ReaverAmbush.java @@ -9,6 +9,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -27,7 +28,7 @@ public final class ReaverAmbush extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{B}"); // Exile target creature with power 3 or less. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new ExileTargetEffect()); } diff --git a/Mage.Sets/src/mage/cards/r/RecklessBushwhacker.java b/Mage.Sets/src/mage/cards/r/RecklessBushwhacker.java index c6686dbc3bf..f4d123f0f37 100644 --- a/Mage.Sets/src/mage/cards/r/RecklessBushwhacker.java +++ b/Mage.Sets/src/mage/cards/r/RecklessBushwhacker.java @@ -1,10 +1,9 @@ package mage.cards.r; -import java.util.UUID; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.SurgedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.keyword.HasteAbility; @@ -12,18 +11,19 @@ import mage.abilities.keyword.SurgeAbility; 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.filter.StaticFilters; +import java.util.UUID; + /** - * * @author fireshoes */ public final class RecklessBushwhacker extends CardImpl { public RecklessBushwhacker(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); this.subtype.add(SubType.GOBLIN); this.subtype.add(SubType.WARRIOR); this.subtype.add(SubType.ALLY); @@ -37,11 +37,14 @@ public final class RecklessBushwhacker extends CardImpl { this.addAbility(HasteAbility.getInstance()); // When Reckless Bushwhacker enters the battlefield, if its surge cost was paid, other creatures you control get +1/+0 and gain haste until end of turn. - EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new BoostControlledEffect(1, 0, Duration.EndOfTurn, true), false); - ability.addEffect(new GainAbilityControlledEffect(HasteAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_OTHER_CONTROLLED_CREATURES, true)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, SurgedCondition.instance, - "When {this} enters, if its surge cost was paid, other creatures you control get +1/+0 and gain haste until end of turn.")); - + Ability ability = new EntersBattlefieldTriggeredAbility(new BoostControlledEffect( + 1, 0, Duration.EndOfTurn, true + ).setText("other creatures you control get +1/+0")).withInterveningIf(SurgedCondition.instance); + ability.addEffect(new GainAbilityControlledEffect( + HasteAbility.getInstance(), Duration.EndOfTurn, + StaticFilters.FILTER_PERMANENT_CREATURE, true + ).setText("and gain haste until end of turn")); + this.addAbility(ability); } private RecklessBushwhacker(final RecklessBushwhacker card) { diff --git a/Mage.Sets/src/mage/cards/r/RecklessRage.java b/Mage.Sets/src/mage/cards/r/RecklessRage.java index 452aeb78886..79b30f0ec35 100644 --- a/Mage.Sets/src/mage/cards/r/RecklessRage.java +++ b/Mage.Sets/src/mage/cards/r/RecklessRage.java @@ -5,12 +5,15 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.SecondTargetPointer; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author JayDi85 */ @@ -20,7 +23,7 @@ public final class RecklessRage extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}"); // Reckless Rage deals 4 damage to target creature you don't control and 2 damage to target creature you control. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.getSpellAbility().addEffect(new DamageTargetEffect(4).setUseOnlyTargetPointer(true)); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); this.getSpellAbility().addEffect(new DamageTargetEffect(2).setUseOnlyTargetPointer(true) diff --git a/Mage.Sets/src/mage/cards/r/RecklessSpite.java b/Mage.Sets/src/mage/cards/r/RecklessSpite.java index 280e0a92109..3948633a390 100644 --- a/Mage.Sets/src/mage/cards/r/RecklessSpite.java +++ b/Mage.Sets/src/mage/cards/r/RecklessSpite.java @@ -6,21 +6,20 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; /** - * * @author Loki */ public final class RecklessSpite extends CardImpl { public RecklessSpite(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}{B}"); this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(2, 2, StaticFilters.FILTER_PERMANENT_CREATURES_NON_BLACK, false)); + this.getSpellAbility().addTarget(new TargetPermanent(2, StaticFilters.FILTER_PERMANENT_CREATURES_NON_BLACK)); this.getSpellAbility().addEffect(new LoseLifeSourceControllerEffect(5)); } diff --git a/Mage.Sets/src/mage/cards/r/ReclusiveWight.java b/Mage.Sets/src/mage/cards/r/ReclusiveWight.java index 13a130eaf55..00fad2016ee 100644 --- a/Mage.Sets/src/mage/cards/r/ReclusiveWight.java +++ b/Mage.Sets/src/mage/cards/r/ReclusiveWight.java @@ -1,33 +1,36 @@ package mage.cards.r; -import java.util.UUID; import mage.MageInt; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SacrificeSourceEffect; -import mage.constants.SubType; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.mageobject.AnotherPredicate; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class ReclusiveWight extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent("another nonland permanent"); + private static final FilterPermanent filter = new FilterControlledPermanent("you control another nonland permanent"); static { filter.add(Predicates.not(CardType.LAND.getPredicate())); filter.add(AnotherPredicate.instance); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); + public ReclusiveWight(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); @@ -37,11 +40,7 @@ public final class ReclusiveWight extends CardImpl { this.toughness = new MageInt(4); // At the beginning of your upkeep, if you control another nonland permanent, sacrifice Reclusive Wight. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceEffect()), - new PermanentsOnTheBattlefieldCondition(filter), - "At the beginning of your upkeep, if you control another nonland permanent, sacrifice {this}." - )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceEffect()).withInterveningIf(condition)); } private ReclusiveWight(final ReclusiveWight card) { diff --git a/Mage.Sets/src/mage/cards/r/Reconnaissance.java b/Mage.Sets/src/mage/cards/r/Reconnaissance.java index 3c0555a76d0..a84ef28130c 100644 --- a/Mage.Sets/src/mage/cards/r/Reconnaissance.java +++ b/Mage.Sets/src/mage/cards/r/Reconnaissance.java @@ -1,41 +1,38 @@ - package mage.cards.r; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.RemoveFromCombatTargetEffect; +import mage.abilities.effects.common.UntapTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Zone; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.permanent.AttackingPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author spjspj */ public final class Reconnaissance extends CardImpl { - private static FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("attacking creature controlled by you"); + private static FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("attacking creature you control"); static { filter.add(AttackingPredicate.instance); } public Reconnaissance(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}"); // {0}: Remove target attacking creature you control from combat and untap it. - Ability ability = new SimpleActivatedAbility(new ReconnaissanceRemoveFromCombatEffect(), new ManaCostsImpl<>("{0}")); - ability.addTarget(new TargetControlledCreaturePermanent(filter)); + Ability ability = new SimpleActivatedAbility(new RemoveFromCombatTargetEffect() + .setText("remove target attacking creature you control from combat"), new GenericManaCost(0)); + ability.addEffect(new UntapTargetEffect("and untap it")); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } @@ -48,33 +45,3 @@ public final class Reconnaissance extends CardImpl { return new Reconnaissance(this); } } - -class ReconnaissanceRemoveFromCombatEffect extends OneShotEffect { - - ReconnaissanceRemoveFromCombatEffect() { - super(Outcome.Benefit); - this.staticText = "Remove target attacking creature you control from combat and untap it"; - } - - private ReconnaissanceRemoveFromCombatEffect(final ReconnaissanceRemoveFromCombatEffect effect) { - super(effect); - } - - @Override - public ReconnaissanceRemoveFromCombatEffect copy() { - return new ReconnaissanceRemoveFromCombatEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent creature = game.getPermanent(source.getFirstTarget()); - Player player = game.getPlayer(source.getControllerId()); - - if (creature != null && player != null && creature.isAttacking()) { - creature.removeFromCombat(game); - creature.untap(game); - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/r/RedXIIIProudWarrior.java b/Mage.Sets/src/mage/cards/r/RedXIIIProudWarrior.java index ebe56a52fc7..e5bc2b774cc 100644 --- a/Mage.Sets/src/mage/cards/r/RedXIIIProudWarrior.java +++ b/Mage.Sets/src/mage/cards/r/RedXIIIProudWarrior.java @@ -33,7 +33,7 @@ public final class RedXIIIProudWarrior extends CardImpl { static { filter.add(ModifiedPredicate.instance); - filter.add(Predicates.or( + filter2.add(Predicates.or( SubType.AURA.getPredicate(), SubType.EQUIPMENT.getPredicate() )); diff --git a/Mage.Sets/src/mage/cards/r/RedemptionChoir.java b/Mage.Sets/src/mage/cards/r/RedemptionChoir.java index 1c3a7ff67b6..84dbd00739b 100644 --- a/Mage.Sets/src/mage/cards/r/RedemptionChoir.java +++ b/Mage.Sets/src/mage/cards/r/RedemptionChoir.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility; import mage.abilities.condition.common.CovenCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.hint.common.CovenHint; import mage.abilities.keyword.LifelinkAbility; @@ -25,14 +24,16 @@ import java.util.UUID; */ public final class RedemptionChoir extends CardImpl { - private static final FilterPermanentCard filter = new FilterPermanentCard("permanent card with mana value 3 or less from your graveyard"); + private static final FilterPermanentCard filter + = new FilterPermanentCard("permanent card with mana value 3 or less from your graveyard"); + static { filter.add(new ManaValuePredicate(ComparisonType.OR_LESS, 3)); } public RedemptionChoir(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{W}"); - + this.subtype.add(SubType.VAMPIRE); this.subtype.add(SubType.CLERIC); this.power = new MageInt(3); @@ -42,13 +43,9 @@ public final class RedemptionChoir extends CardImpl { this.addAbility(LifelinkAbility.getInstance()); // Coven -- Whenever Redemption Choir enters the battlefield or attacks, if you control three or more creatures with different powers, return target permanent card with mana value 3 or less from your graveyard to the battlefield. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldOrAttacksSourceTriggeredAbility( - new ReturnFromGraveyardToBattlefieldTargetEffect() - ), CovenCondition.instance, "Whenever {this} enters or attacks, " + - "if you control three or more creatures with different powers, " + - "return target permanent card with mana value 3 or less from your graveyard to the battlefield." - ); + Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility( + new ReturnFromGraveyardToBattlefieldTargetEffect() + ).withInterveningIf(CovenCondition.instance); ability.addTarget(new TargetCardInYourGraveyard(filter)); this.addAbility(ability.addHint(CovenHint.instance).setAbilityWord(AbilityWord.COVEN)); diff --git a/Mage.Sets/src/mage/cards/r/ReflectorMage.java b/Mage.Sets/src/mage/cards/r/ReflectorMage.java index df5dc5d9021..da145860a07 100644 --- a/Mage.Sets/src/mage/cards/r/ReflectorMage.java +++ b/Mage.Sets/src/mage/cards/r/ReflectorMage.java @@ -15,6 +15,7 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.util.CardUtil; @@ -41,7 +42,7 @@ public final class ReflectorMage extends CardImpl { // When Reflector Mage enters the battlefield, return target creature an opponent controls to its owner's hand. That creature's owner can't cast spells with the same name as that creature until your next turn. Ability ability = new EntersBattlefieldTriggeredAbility(new ReflectorMageEffect(), false); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RegalBloodlord.java b/Mage.Sets/src/mage/cards/r/RegalBloodlord.java index e739b254bfc..6c9483820d7 100644 --- a/Mage.Sets/src/mage/cards/r/RegalBloodlord.java +++ b/Mage.Sets/src/mage/cards/r/RegalBloodlord.java @@ -1,12 +1,12 @@ package mage.cards.r; import mage.MageInt; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.YouGainedLifeCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.ControllerGainedLifeCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.FlyingAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -22,6 +22,8 @@ import java.util.UUID; */ public final class RegalBloodlord extends CardImpl { + private static final Condition condition = new YouGainedLifeCondition(); + public RegalBloodlord(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{B}"); @@ -34,15 +36,8 @@ public final class RegalBloodlord extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // At the beginning of each end step, if you gained life this turn, create a 1/1 black Bat creature token with flying. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - TargetController.ANY, new CreateTokenEffect(new BatToken()), - false - ), - new YouGainedLifeCondition(), - "At the beginning of each end step, " - + "if you gained life this turn, " - + "create a 1/1 black Bat creature token with flying." + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.ANY, new CreateTokenEffect(new BatToken()), false, condition ).addHint(ControllerGainedLifeCount.getHint()), new PlayerGainedLifeWatcher()); } diff --git a/Mage.Sets/src/mage/cards/r/RegnaTheRedeemer.java b/Mage.Sets/src/mage/cards/r/RegnaTheRedeemer.java index 794e2187e35..86327b0b9af 100644 --- a/Mage.Sets/src/mage/cards/r/RegnaTheRedeemer.java +++ b/Mage.Sets/src/mage/cards/r/RegnaTheRedeemer.java @@ -1,29 +1,25 @@ - package mage.cards.r; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; -import mage.abilities.condition.IntCompareCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.effects.common.CreateTokenEffect; -import mage.constants.SubType; -import mage.constants.SuperType; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.PartnerWithAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.ComparisonType; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.constants.TargetController; import mage.game.Game; import mage.game.permanent.token.WarriorToken; -import mage.players.Player; import mage.watchers.common.PlayerGainedLifeWatcher; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class RegnaTheRedeemer extends CardImpl { @@ -43,15 +39,9 @@ public final class RegnaTheRedeemer extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // At the beginning of each end step, if your team gained life this turn, create two 1/1 white Warrior creature tokens. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - TargetController.ANY, new CreateTokenEffect(new WarriorToken(), 2), - false - ), - new RegnaTheRedeemerCondition(), - "At the beginning of each end step, " - + "if your team gained life this turn, " - + "create two 1/1 white Warrior creature tokens" + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.ANY, new CreateTokenEffect(new WarriorToken(), 2), + false, RegnaTheRedeemerCondition.instance ), new PlayerGainedLifeWatcher()); } @@ -65,27 +55,20 @@ public final class RegnaTheRedeemer extends CardImpl { } } -class RegnaTheRedeemerCondition extends IntCompareCondition { +enum RegnaTheRedeemerCondition implements Condition { + instance; - public RegnaTheRedeemerCondition() { - super(ComparisonType.MORE_THAN, 0); + @Override + public boolean apply(Game game, Ability source) { + // TODO: if teammates are ever implemented this will need to be refactored + return game + .getState() + .getWatcher(PlayerGainedLifeWatcher.class) + .getLifeGained(source.getControllerId()) > 0; } @Override - protected int getInputValue(Game game, Ability source) { - int gainedLife = 0; - PlayerGainedLifeWatcher watcher = game.getState().getWatcher(PlayerGainedLifeWatcher.class); - if (watcher != null) { - for (UUID playerId : game.getPlayerList()) { - Player player = game.getPlayer(playerId); - if (player != null && !player.hasOpponent(source.getControllerId(), game)) { - gainedLife = watcher.getLifeGained(playerId); - if (gainedLife > 0) { - break; - } - } - } - } - return gainedLife; + public String toString() { + return "your team gained life this turn"; } } diff --git a/Mage.Sets/src/mage/cards/r/ReiverDemon.java b/Mage.Sets/src/mage/cards/r/ReiverDemon.java index 8f5b71c3f74..7dc7132c13d 100644 --- a/Mage.Sets/src/mage/cards/r/ReiverDemon.java +++ b/Mage.Sets/src/mage/cards/r/ReiverDemon.java @@ -1,12 +1,9 @@ - package mage.cards.r; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromHandSourcePermanentCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyAllEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -18,8 +15,9 @@ import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; import mage.watchers.common.CastFromHandWatcher; +import java.util.UUID; + /** - * * @author daagar */ public final class ReiverDemon extends CardImpl { @@ -32,7 +30,7 @@ public final class ReiverDemon extends CardImpl { } public ReiverDemon(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}{B}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}{B}{B}{B}"); this.subtype.add(SubType.DEMON); this.power = new MageInt(6); this.toughness = new MageInt(6); @@ -41,11 +39,8 @@ public final class ReiverDemon extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // 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), - CastFromHandSourcePermanentCondition.instance, - "When {this} enters, if you cast it from your hand, destroy all nonartifact, nonblack creatures. They can't be regenerated."), - new CastFromHandWatcher()); + this.addAbility(new EntersBattlefieldTriggeredAbility(new DestroyAllEffect(filter, true)) + .withInterveningIf(CastFromHandSourcePermanentCondition.instance), new CastFromHandWatcher()); } private ReiverDemon(final ReiverDemon card) { diff --git a/Mage.Sets/src/mage/cards/r/RekindledFlame.java b/Mage.Sets/src/mage/cards/r/RekindledFlame.java index 92115531b71..daaf37c3f6a 100644 --- a/Mage.Sets/src/mage/cards/r/RekindledFlame.java +++ b/Mage.Sets/src/mage/cards/r/RekindledFlame.java @@ -1,12 +1,11 @@ package mage.cards.r; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.abilities.hint.Hint; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -22,7 +21,7 @@ import java.util.UUID; public final class RekindledFlame extends CardImpl { private static final Hint hint = new ConditionHint( - OpponentHasNoCardsInHandCondition.instance, "Opponent has no cards in hand" + OpponentHasNoCardsInHandCondition.instance, "An opponent has no cards in hand" ); public RekindledFlame(UUID ownerId, CardSetInfo setInfo) { @@ -33,13 +32,9 @@ public final class RekindledFlame extends CardImpl { this.getSpellAbility().addTarget(new TargetAnyTarget()); // 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. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility( - Zone.GRAVEYARD, TargetController.YOU, new ReturnSourceFromGraveyardToHandEffect(), - true - ), OpponentHasNoCardsInHandCondition.instance, "At the beginning of your upkeep, " + - "if an opponent has no cards in hand, you may return {this} from your graveyard to your hand." - ).addHint(hint)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + Zone.GRAVEYARD, TargetController.YOU, new ReturnSourceFromGraveyardToHandEffect(), true + ).withInterveningIf(OpponentHasNoCardsInHandCondition.instance).addHint(hint)); } private RekindledFlame(final RekindledFlame card) { diff --git a/Mage.Sets/src/mage/cards/r/RelentlessDead.java b/Mage.Sets/src/mage/cards/r/RelentlessDead.java index 3d5f3299013..ff8fbef7956 100644 --- a/Mage.Sets/src/mage/cards/r/RelentlessDead.java +++ b/Mage.Sets/src/mage/cards/r/RelentlessDead.java @@ -3,22 +3,21 @@ package mage.cards.r; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DiesSourceTriggeredAbility; +import mage.abilities.costs.common.DynamicValueGenericManaCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.dynamicvalue.common.TargetManaValue; import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.effects.common.ReturnToHandSourceEffect; import mage.abilities.keyword.MenaceAbility; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.SubType; import mage.filter.FilterCard; +import mage.filter.common.FilterCreatureCard; import mage.filter.predicate.mageobject.AnotherPredicate; -import mage.filter.predicate.mageobject.ManaValuePredicate; -import mage.game.Game; -import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; -import mage.util.ManaUtil; import java.util.UUID; @@ -27,6 +26,13 @@ import java.util.UUID; */ public final class RelentlessDead extends CardImpl { + private static final FilterCard filter = new FilterCreatureCard("another target Zombie creature card with mana value X from your graveyard"); // This target defines X + + static { + filter.add(SubType.ZOMBIE.getPredicate()); + filter.add(AnotherPredicate.instance); + } + public RelentlessDead(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}{B}"); this.subtype.add(SubType.ZOMBIE); @@ -40,7 +46,11 @@ public final class RelentlessDead extends CardImpl { this.addAbility(new DiesSourceTriggeredAbility(new DoIfCostPaid(new ReturnToHandSourceEffect().setText("return it to its owner's hand"), 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 DiesSourceTriggeredAbility(new RelentlessDeadEffect())); + Ability ability = new DiesSourceTriggeredAbility(new DoIfCostPaid( + new ReturnFromGraveyardToBattlefieldTargetEffect(), + new DynamicValueGenericManaCost(TargetManaValue.instance, "{X}"))); + ability.addTarget(new TargetCardInYourGraveyard(filter)); + this.addAbility(ability); } private RelentlessDead(final RelentlessDead card) { @@ -52,46 +62,3 @@ public final class RelentlessDead extends CardImpl { return new RelentlessDead(this); } } - -class RelentlessDeadEffect extends OneShotEffect { - - RelentlessDeadEffect() { - super(Outcome.PutCardInPlay); - this.staticText = "you may pay {X}. If you do, return another target Zombie creature card with mana value X from your graveyard to the battlefield"; - } - - private RelentlessDeadEffect(final RelentlessDeadEffect effect) { - super(effect); - } - - @Override - public RelentlessDeadEffect copy() { - return new RelentlessDeadEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - if (controller.chooseUse(Outcome.Benefit, "Do you want to pay {X} to return zombie?", source, game)) { - int payCount = ManaUtil.playerPaysXGenericMana(true, "Relentless Dead", controller, source, game); - // can be 0 - FilterCard filter = new FilterCard("Another target Zombie card with mana value {" + payCount + "}"); - filter.add(SubType.ZOMBIE.getPredicate()); - filter.add(new ManaValuePredicate(ComparisonType.EQUAL_TO, payCount)); - filter.add(AnotherPredicate.instance); - TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(filter); - if (controller.chooseTarget(outcome, target, source, game)) { - Card card = game.getCard(target.getFirstTarget()); - if (card != null) { - controller.moveCards(card, Zone.BATTLEFIELD, source, game); - } - } - - } - return true; - } - return false; - - } -} diff --git a/Mage.Sets/src/mage/cards/r/RendFlesh.java b/Mage.Sets/src/mage/cards/r/RendFlesh.java index 8c4a95520b6..6997f245a38 100644 --- a/Mage.Sets/src/mage/cards/r/RendFlesh.java +++ b/Mage.Sets/src/mage/cards/r/RendFlesh.java @@ -10,6 +10,7 @@ import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -30,7 +31,7 @@ public final class RendFlesh extends CardImpl { this.subtype.add(SubType.ARCANE); // Destroy target non-Spirit creature. - Target target = new TargetCreaturePermanent(filter); + Target target = new TargetPermanent(filter); this.getSpellAbility().addTarget(target); this.getSpellAbility().addEffect(new DestroyTargetEffect()); } diff --git a/Mage.Sets/src/mage/cards/r/RendingVolley.java b/Mage.Sets/src/mage/cards/r/RendingVolley.java index 7a877174423..2d547010c04 100644 --- a/Mage.Sets/src/mage/cards/r/RendingVolley.java +++ b/Mage.Sets/src/mage/cards/r/RendingVolley.java @@ -15,6 +15,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -43,7 +44,7 @@ public final class RendingVolley extends CardImpl { // Rending Volley deals 4 damage to target white or blue creature. this.getSpellAbility().addEffect(new DamageTargetEffect(4)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private RendingVolley(final RendingVolley card) { diff --git a/Mage.Sets/src/mage/cards/r/RenegadeSilent.java b/Mage.Sets/src/mage/cards/r/RenegadeSilent.java index 7ce19daa21f..a6fef0d7585 100644 --- a/Mage.Sets/src/mage/cards/r/RenegadeSilent.java +++ b/Mage.Sets/src/mage/cards/r/RenegadeSilent.java @@ -12,10 +12,13 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.counters.CounterType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author Susucr */ @@ -33,7 +36,7 @@ public final class RenegadeSilent extends CardImpl { Ability ability = new BeginningOfEndStepTriggeredAbility( new GoadTargetEffect().setText("goad up to one target creature you don't control") ); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + ability.addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); ability.addEffect(new AddCountersSourceEffect(CounterType.P1P1.createInstance()) .concatBy("and")); ability.addEffect(new PhaseOutSourceEffect()); diff --git a/Mage.Sets/src/mage/cards/r/RepeatingBarrage.java b/Mage.Sets/src/mage/cards/r/RepeatingBarrage.java index 52a2eb7e75c..525d1314c5b 100644 --- a/Mage.Sets/src/mage/cards/r/RepeatingBarrage.java +++ b/Mage.Sets/src/mage/cards/r/RepeatingBarrage.java @@ -3,7 +3,7 @@ package mage.cards.r; import mage.abilities.Ability; import mage.abilities.condition.common.RaidCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect; import mage.abilities.hint.common.RaidHint; @@ -30,7 +30,7 @@ public final class RepeatingBarrage extends CardImpl { this.getSpellAbility().addTarget(new TargetAnyTarget()); // Raid — {3}{R}{R}: Return Repeating Barrage from your graveyard to your hand. Activate this ability only if you attacked this turn. - Ability ability = new ConditionalActivatedAbility(Zone.GRAVEYARD, + Ability ability = new ActivateIfConditionActivatedAbility(Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(), new ManaCostsImpl<>("{3}{R}{R}"), RaidCondition.instance); diff --git a/Mage.Sets/src/mage/cards/r/RepentantVampire.java b/Mage.Sets/src/mage/cards/r/RepentantVampire.java index 1cfb1d451f9..6be51e84ac0 100644 --- a/Mage.Sets/src/mage/cards/r/RepentantVampire.java +++ b/Mage.Sets/src/mage/cards/r/RepentantVampire.java @@ -23,6 +23,7 @@ import mage.constants.SubType; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -59,7 +60,7 @@ public final class RepentantVampire extends CardImpl { ThresholdCondition.instance, "As long as seven or more cards are in your graveyard, {this} is white" )); Ability gainedAbility = new SimpleActivatedAbility(new DestroyTargetEffect(), new TapSourceCost()); - gainedAbility.addTarget(new TargetCreaturePermanent(filter)); + gainedAbility.addTarget(new TargetPermanent(filter)); ability.addEffect(new ConditionalContinuousEffect( new GainAbilitySourceEffect(gainedAbility, Duration.WhileOnBattlefield), ThresholdCondition.instance, "and has \"{T}: Destroy target black creature.\"" diff --git a/Mage.Sets/src/mage/cards/r/Reprisal.java b/Mage.Sets/src/mage/cards/r/Reprisal.java index 0d51718bf2f..219a8a605af 100644 --- a/Mage.Sets/src/mage/cards/r/Reprisal.java +++ b/Mage.Sets/src/mage/cards/r/Reprisal.java @@ -9,6 +9,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -29,7 +30,7 @@ public final class Reprisal extends CardImpl { // Destroy target creature with power 4 or greater. It can't be regenerated. this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private Reprisal(final Reprisal card) { diff --git a/Mage.Sets/src/mage/cards/r/ReservoirKraken.java b/Mage.Sets/src/mage/cards/r/ReservoirKraken.java index 33a36860b35..1f57e43a487 100644 --- a/Mage.Sets/src/mage/cards/r/ReservoirKraken.java +++ b/Mage.Sets/src/mage/cards/r/ReservoirKraken.java @@ -1,31 +1,31 @@ package mage.cards.r; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.condition.common.SourceTappedCondition; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; -import mage.constants.Outcome; -import mage.constants.SubType; import mage.abilities.keyword.TrampleAbility; import mage.abilities.keyword.WardAbility; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; 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.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.FishToken; import mage.players.Player; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author weirddan455 */ public final class ReservoirKraken extends CardImpl { @@ -44,11 +44,9 @@ public final class ReservoirKraken extends CardImpl { this.addAbility(new WardAbility(new GenericManaCost(2), false)); // At the beginning of each combat, if Reservoir Kraken is untapped, any opponent may tap an untapped creature they control. If they do, tap Reservoir Kraken and create a 1/1 blue Fish creature token with "This creature can't be blocked." - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility(TargetController.ANY, new ReservoirKrakenEffect(), false), - SourceTappedCondition.UNTAPPED, - "At the beginning of each combat, if {this} is untapped, any opponent may tap an untapped creature they control. If they do, tap {this} and create a 1/1 blue Fish creature token with \"This creature can't be blocked.\"" - )); + this.addAbility(new BeginningOfCombatTriggeredAbility( + TargetController.ANY, new ReservoirKrakenEffect(), false + ).withInterveningIf(SourceTappedCondition.UNTAPPED)); } private ReservoirKraken(final ReservoirKraken card) { @@ -71,7 +69,7 @@ class ReservoirKrakenEffect extends OneShotEffect { public ReservoirKrakenEffect() { super(Outcome.Tap); - this.staticText = "any opponent may tap an untapped creature they control. If they do, tap {this} and create a 1/1 blue Fish creature token with \"This creature can't be blocked.\""; + this.staticText = "any opponent may tap an untapped creature they control. If they do, tap {this} and create a 1/1 blue Fish creature token with \"This token can't be blocked.\""; } private ReservoirKrakenEffect(final ReservoirKrakenEffect effect) { @@ -88,15 +86,19 @@ class ReservoirKrakenEffect extends OneShotEffect { boolean opponentTapped = false; for (UUID opponentId : game.getOpponents(source.getControllerId())) { Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - TargetControlledCreaturePermanent target = new TargetControlledCreaturePermanent(1, 1, filter, true); - if (target.canChoose(opponentId, source, game) && opponent.chooseUse(Outcome.AIDontUseIt, "Tap an untapped creature you control?", source, game)) { - opponent.chooseTarget(Outcome.Tap, target, source, game); - Permanent permanent = game.getPermanent(target.getFirstTarget()); - if (permanent != null && permanent.tap(source, game)) { - opponentTapped = true; - } - } + if (opponent == null) { + continue; + } + TargetPermanent target = new TargetPermanent(StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURE); + target.withNotTarget(true); + if (!target.canChoose(opponentId, source, game) + || !opponent.chooseUse(Outcome.AIDontUseIt, "Tap an untapped creature you control?", source, game)) { + continue; + } + opponent.chooseTarget(Outcome.Tap, target, source, game); + Permanent permanent = game.getPermanent(target.getFirstTarget()); + if (permanent != null && permanent.tap(source, game)) { + opponentTapped = true; } } if (opponentTapped) { diff --git a/Mage.Sets/src/mage/cards/r/ResistanceBomber.java b/Mage.Sets/src/mage/cards/r/ResistanceBomber.java index be0c252c332..b5ca1bade46 100644 --- a/Mage.Sets/src/mage/cards/r/ResistanceBomber.java +++ b/Mage.Sets/src/mage/cards/r/ResistanceBomber.java @@ -1,32 +1,31 @@ package mage.cards.r; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.condition.common.SourceAttackingCondition; import mage.abilities.costs.common.RemoveCountersSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.SpaceflightAbility; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; +import mage.constants.SubType; import mage.counters.CounterType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author NinthWorld */ public final class ResistanceBomber extends CardImpl { public ResistanceBomber(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}{R}"); - + this.subtype.add(SubType.REBEL); this.subtype.add(SubType.STARSHIP); this.power = new MageInt(2); @@ -37,14 +36,15 @@ public final class ResistanceBomber extends CardImpl { // Resistance Bomber enters the battlefield with a charge counter on it. this.addAbility(new EntersBattlefieldAbility( - new AddCountersSourceEffect(CounterType.CHARGE.createInstance()) - .setText("with a charge counter on it"))); + new AddCountersSourceEffect(CounterType.CHARGE.createInstance()), "with a charge counter on it" + )); // Remove a charge counter from Resistance Bomber: Resistance Bomber deals 5 damage to target creature. Activate this ability only if Resistance Bomber is attacking. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, + Ability ability = new ActivateIfConditionActivatedAbility( new DamageTargetEffect(5), new RemoveCountersSourceCost(CounterType.CHARGE.createInstance()), - SourceAttackingCondition.instance); + SourceAttackingCondition.instance + ); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/ResistanceSquad.java b/Mage.Sets/src/mage/cards/r/ResistanceSquad.java index 2ea52a106b3..fe29afaf179 100644 --- a/Mage.Sets/src/mage/cards/r/ResistanceSquad.java +++ b/Mage.Sets/src/mage/cards/r/ResistanceSquad.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.hint.ConditionHint; import mage.abilities.hint.Hint; @@ -23,14 +22,14 @@ import java.util.UUID; */ public final class ResistanceSquad extends CardImpl { - private static final FilterPermanent filter = new FilterControlledPermanent(SubType.HUMAN); + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.HUMAN, "you control another Human"); static { filter.add(AnotherPredicate.instance); } private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); - private static final Hint hint = new ConditionHint(condition, "You control another Human"); + private static final Hint hint = new ConditionHint(condition); public ResistanceSquad(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); @@ -41,11 +40,8 @@ public final class ResistanceSquad extends CardImpl { this.toughness = new MageInt(2); // When Resistance Squad enters the battlefield, if you control another Human, draw a card. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility( - new DrawCardSourceControllerEffect(1)), - condition, "When {this} enters, " + - "if you control another Human, draw a card." - ).addHint(hint)); + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)) + .withInterveningIf(condition).addHint(hint)); } private ResistanceSquad(final ResistanceSquad card) { diff --git a/Mage.Sets/src/mage/cards/r/ResplendentGriffin.java b/Mage.Sets/src/mage/cards/r/ResplendentGriffin.java index d4a3045b668..2d70a3a082f 100644 --- a/Mage.Sets/src/mage/cards/r/ResplendentGriffin.java +++ b/Mage.Sets/src/mage/cards/r/ResplendentGriffin.java @@ -3,7 +3,6 @@ package mage.cards.r; import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.CitysBlessingCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.hint.common.CitysBlessingHint; import mage.abilities.keyword.AscendAbility; @@ -35,10 +34,10 @@ public final class ResplendentGriffin extends CardImpl { this.addAbility(new AscendAbility()); // Whenever Resplendent Griffin attacks, if you have the city's blessing, put a +1/+1 counter on it. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new AttacksTriggeredAbility( - new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false), CitysBlessingCondition.instance, - "Whenever {this} attacks, if you have the city's blessing, put a +1/+1 counter on it.") - .addHint(CitysBlessingHint.instance)); + this.addAbility(new AttacksTriggeredAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance()) + .setText("put a +1/+1 counter on it") + ).withInterveningIf(CitysBlessingCondition.instance).addHint(CitysBlessingHint.instance)); } private ResplendentGriffin(final ResplendentGriffin card) { diff --git a/Mage.Sets/src/mage/cards/r/RestlessVinestalk.java b/Mage.Sets/src/mage/cards/r/RestlessVinestalk.java index 8bc24640ea7..f9e66ba12e9 100644 --- a/Mage.Sets/src/mage/cards/r/RestlessVinestalk.java +++ b/Mage.Sets/src/mage/cards/r/RestlessVinestalk.java @@ -18,7 +18,7 @@ import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.game.permanent.token.custom.CreatureToken; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -53,7 +53,7 @@ public final class RestlessVinestalk extends CardImpl { // Whenever Restless Vinestalk attacks, up to one other target creature has base power and toughness 3/3 until end of turn. Ability ability = new AttacksTriggeredAbility(new SetBasePowerToughnessTargetEffect(3, 3, Duration.EndOfTurn), false); - ability.addTarget(new TargetCreaturePermanent(0, 1, filter, false)); + ability.addTarget(new TargetPermanent(0, 1, filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/ResurrectedCultist.java b/Mage.Sets/src/mage/cards/r/ResurrectedCultist.java index fb1f574e1b9..8d46aa372ef 100644 --- a/Mage.Sets/src/mage/cards/r/ResurrectedCultist.java +++ b/Mage.Sets/src/mage/cards/r/ResurrectedCultist.java @@ -30,8 +30,8 @@ public final class ResurrectedCultist extends CardImpl { this.addAbility(new ActivateIfConditionActivatedAbility( Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldWithCounterEffect(CounterType.FINALITY.createInstance(), false), - new ManaCostsImpl<>("{2}{B}{B}"), DeliriumCondition.instance, TimingRule.SORCERY - ).setAbilityWord(AbilityWord.DELIRIUM).addHint(CardTypesInGraveyardCount.YOU.getHint())); + new ManaCostsImpl<>("{2}{B}{B}"), DeliriumCondition.instance + ).setTiming(TimingRule.SORCERY).setAbilityWord(AbilityWord.DELIRIUM).addHint(CardTypesInGraveyardCount.YOU.getHint())); } private ResurrectedCultist(final ResurrectedCultist card) { diff --git a/Mage.Sets/src/mage/cards/r/Retribution.java b/Mage.Sets/src/mage/cards/r/Retribution.java index 6a26dec77ad..9c855f3878b 100644 --- a/Mage.Sets/src/mage/cards/r/Retribution.java +++ b/Mage.Sets/src/mage/cards/r/Retribution.java @@ -1,8 +1,5 @@ - package mage.cards.r; -import java.util.UUID; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; @@ -10,15 +7,22 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; import mage.counters.CounterType; +import mage.filter.FilterPermanent; import mage.filter.StaticFilters; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.PermanentReferenceInCollectionPredicate; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetImpl; +import mage.target.TargetPermanent; +import mage.target.common.TargetPermanentSameController; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; /** - * * @author jeffwadsworth */ public final class Retribution extends CardImpl { @@ -28,8 +32,7 @@ public final class Retribution extends CardImpl { // Choose two target creatures an opponent controls. That player chooses and sacrifices one of those creatures. Put a -1/-1 counter on the other. this.getSpellAbility().addEffect(new RetributionEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanentOpponentSameController(2, 2, StaticFilters.FILTER_PERMANENT_CREATURE, false)); - + this.getSpellAbility().addTarget(new TargetPermanentSameController(2, StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURES)); } private Retribution(final Retribution card) { @@ -60,66 +63,48 @@ class RetributionEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - MageObject sourceObject = source.getSourceObject(game); - if (sourceObject != null) { - boolean sacrificeDone = false; - int count = 0; - for (UUID targetId : getTargetPointer().getTargets(game, source)) { - Permanent creature = game.getPermanent(targetId); - if (creature != null) { - Player controllerOfCreature = game.getPlayer(creature.getControllerId()); - if ((count == 0 && controllerOfCreature != null - && controllerOfCreature.chooseUse(Outcome.Sacrifice, "Sacrifice " + creature.getLogName() + '?', source, game)) - || (count == 1 - && !sacrificeDone)) { - creature.sacrifice(source, game); - sacrificeDone = true; - } else { - creature.addCounters(CounterType.M1M1.createInstance(), source.getControllerId(), source, game); - } - count++; - } - } - return true; + List permanents = this + .getTargetPointer() + .getTargets(game, source) + .stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + List canSac = permanents + .stream() + .filter(Permanent::canBeSacrificed) + .collect(Collectors.toList()); + Permanent toSacrifice; + switch (canSac.size()) { + case 0: + toSacrifice = null; + break; + case 1: + toSacrifice = canSac.get(0); + break; + default: + toSacrifice = Optional + .ofNullable(canSac.get(0).getControllerId()) + .map(game::getPlayer) + .map(player -> { + FilterPermanent filter = new FilterPermanent(); + filter.add(new PermanentReferenceInCollectionPredicate(canSac, game)); + TargetPermanent target = new TargetPermanent(filter); + target.withNotTarget(true); + player.choose(Outcome.Sacrifice, target, source, game); + return target; + }) + .map(TargetImpl::getFirstTarget) + .map(game::getPermanent) + .orElse(null); } - return false; - } -} - -class TargetCreaturePermanentOpponentSameController extends TargetCreaturePermanent { - - public TargetCreaturePermanentOpponentSameController(int minNumTargets, int maxNumTargets, FilterCreaturePermanent filter, boolean notTarget) { - super(minNumTargets, maxNumTargets, filter, notTarget); - } - - private TargetCreaturePermanentOpponentSameController(final TargetCreaturePermanentOpponentSameController target) { - super(target); - } - - @Override - public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) { - if (super.canTarget(controllerId, id, source, game)) { - Permanent firstTargetPermanent = game.getPermanent(id); - if (firstTargetPermanent != null - && game.getOpponents(controllerId).contains(firstTargetPermanent.getControllerId())) { - for (UUID targetId : getTargets()) { - Permanent targetPermanent = game.getPermanent(targetId); - if (targetPermanent != null) { - if (!firstTargetPermanent.getId().equals(targetPermanent.getId())) { - if (!firstTargetPermanent.isControlledBy(targetPermanent.getOwnerId())) { - return false; - } - } - } - } - return true; - } - } - return false; - } - - @Override - public TargetCreaturePermanentOpponentSameController copy() { - return new TargetCreaturePermanentOpponentSameController(this); + if (toSacrifice != null) { + permanents.remove(toSacrifice); + toSacrifice.sacrifice(source, game); + } + for (Permanent permanent : permanents) { + permanent.addCounters(CounterType.M1M1.createInstance(), source, game); + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/r/RetrieverPhoenix.java b/Mage.Sets/src/mage/cards/r/RetrieverPhoenix.java index 61219940ad9..af5ef5abc79 100644 --- a/Mage.Sets/src/mage/cards/r/RetrieverPhoenix.java +++ b/Mage.Sets/src/mage/cards/r/RetrieverPhoenix.java @@ -1,12 +1,10 @@ package mage.cards.r; import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.CastFromEverywhereSourceCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.LearnEffect; import mage.abilities.hint.common.OpenSideboardHint; @@ -41,10 +39,8 @@ public final class RetrieverPhoenix extends CardImpl { this.addAbility(HasteAbility.getInstance()); // When Retriever Phoenix enters the battlefield, if you cast it, learn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new LearnEffect()), CastFromEverywhereSourceCondition.instance, - "When {this} enters, if you cast it, " + LearnEffect.getDefaultText() - ).addHint(OpenSideboardHint.instance)); + this.addAbility(new EntersBattlefieldTriggeredAbility(new LearnEffect()) + .withInterveningIf(CastFromEverywhereSourceCondition.instance).addHint(OpenSideboardHint.instance)); // As long as Retriever Phoenix is in your graveyard, if you would learn, you may instead return Retriever Phoenix to the battlefield. this.addAbility(new SimpleStaticAbility(Zone.GRAVEYARD, new RetrieverPhoenixEffect())); @@ -64,8 +60,8 @@ class RetrieverPhoenixEffect extends ReplacementEffectImpl { RetrieverPhoenixEffect() { super(Duration.WhileInGraveyard, Outcome.PutCreatureInPlay); - staticText = "as long as {this} is in your graveyard, if you would learn, " + - "you may instead return {this} to the battlefield"; + staticText = "as long as this card is in your graveyard, if you would learn, " + + "you may instead return this card to the battlefield"; } private RetrieverPhoenixEffect(final RetrieverPhoenixEffect effect) { diff --git a/Mage.Sets/src/mage/cards/r/RevealingWind.java b/Mage.Sets/src/mage/cards/r/RevealingWind.java index e57804aa3c8..d02d9e8f212 100644 --- a/Mage.Sets/src/mage/cards/r/RevealingWind.java +++ b/Mage.Sets/src/mage/cards/r/RevealingWind.java @@ -17,6 +17,7 @@ import mage.filter.predicate.card.FaceDownPredicate; import mage.game.Game; import mage.players.Player; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -77,7 +78,7 @@ class RevealingWindEffect extends OneShotEffect { if (!controller.canRespond()) { return false; } - Target target = new TargetCreaturePermanent(filter); + Target target = new TargetPermanent(filter); if (controller.chooseTarget(outcome, target, source, game)) { Card card = game.getCard(target.getFirstTarget()); if (card != null) { diff --git a/Mage.Sets/src/mage/cards/r/RevelInRiches.java b/Mage.Sets/src/mage/cards/r/RevelInRiches.java index 4a98b043e30..34bebbde4e5 100644 --- a/Mage.Sets/src/mage/cards/r/RevelInRiches.java +++ b/Mage.Sets/src/mage/cards/r/RevelInRiches.java @@ -1,14 +1,14 @@ package mage.cards.r; -import mage.abilities.TriggeredAbility; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.WinGameSourceControllerEffect; +import mage.abilities.hint.Hint; import mage.abilities.hint.ValueHint; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -26,24 +26,22 @@ import java.util.UUID; */ public final class RevelInRiches extends CardImpl { - private static final FilterPermanent filter = new FilterControlledPermanent("Treasures"); - - static { - filter.add(SubType.TREASURE.getPredicate()); - } + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.TREASURE, "you control ten or more Treasures"); + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 9); + private static final Hint hint = new ValueHint("Treasures you control", new PermanentsOnBattlefieldCount(filter)); public RevelInRiches(UUID ownerId, CardSetInfo setInfo) { 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()), false, StaticFilters.FILTER_OPPONENTS_PERMANENT_A_CREATURE)); + this.addAbility(new DiesCreatureTriggeredAbility( + new CreateTokenEffect(new TreasureToken()), false, + StaticFilters.FILTER_OPPONENTS_PERMANENT_A_CREATURE + )); + // At the beginning of your upkeep, if you control ten or more Treasures, you win the game. - TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - ability, - new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 9), - "At the beginning of your upkeep, if you control ten or more Treasures, you win the game.") - .addHint(new ValueHint("Treasures you control", new PermanentsOnBattlefieldCount(filter)))); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect()) + .withInterveningIf(condition).addHint(hint)); } private RevelInRiches(final RevelInRiches card) { diff --git a/Mage.Sets/src/mage/cards/r/RevenantPatriarch.java b/Mage.Sets/src/mage/cards/r/RevenantPatriarch.java index c2da5059104..93ae00b6cb0 100644 --- a/Mage.Sets/src/mage/cards/r/RevenantPatriarch.java +++ b/Mage.Sets/src/mage/cards/r/RevenantPatriarch.java @@ -1,27 +1,25 @@ package mage.cards.r; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.CantBlockAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.ManaWasSpentCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SkipCombatStepEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.ColoredManaSymbol; import mage.constants.Duration; +import mage.constants.SubType; import mage.target.TargetPlayer; +import java.util.UUID; + /** - * * @author ilcartographer */ public final class RevenantPatriarch extends CardImpl { - + public RevenantPatriarch(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}"); this.subtype.add(SubType.SPIRIT); @@ -29,18 +27,21 @@ public final class RevenantPatriarch extends CardImpl { this.toughness = new MageInt(3); // When Revenant Patriarch enters the battlefield, if {W} was spent to cast it, target player skips their next combat phase. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new SkipCombatStepEffect(Duration.OneUse).setText("target player skips their next combat phase."), false); + Ability ability = new EntersBattlefieldTriggeredAbility( + new SkipCombatStepEffect(Duration.OneUse) + .setText("target player skips their next combat phase.") + ).withInterveningIf(ManaWasSpentCondition.WHITE); ability.addTarget(new TargetPlayer()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, ManaWasSpentCondition.WHITE, - "When {this} enters, if {W} was spent to cast it, target player skips their next combat phase.")); + this.addAbility(ability); + // Revenant Patriarch can't block. this.addAbility(new CantBlockAbility()); } - + private RevenantPatriarch(final RevenantPatriarch card) { super(card); } - + @Override public RevenantPatriarch copy() { return new RevenantPatriarch(this); diff --git a/Mage.Sets/src/mage/cards/r/RhonasTheIndomitable.java b/Mage.Sets/src/mage/cards/r/RhonasTheIndomitable.java index 34ac88a308b..54386f927d0 100644 --- a/Mage.Sets/src/mage/cards/r/RhonasTheIndomitable.java +++ b/Mage.Sets/src/mage/cards/r/RhonasTheIndomitable.java @@ -22,10 +22,13 @@ import mage.filter.predicate.mageobject.AnotherPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * @author fireshoes */ @@ -55,7 +58,7 @@ public final class RhonasTheIndomitable extends CardImpl { effect = new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn); effect.setText("and gains trample until end of turn"); ability.addEffect(effect); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RhoxMeditant.java b/Mage.Sets/src/mage/cards/r/RhoxMeditant.java index 53565f142e9..81b367df20d 100644 --- a/Mage.Sets/src/mage/cards/r/RhoxMeditant.java +++ b/Mage.Sets/src/mage/cards/r/RhoxMeditant.java @@ -1,13 +1,10 @@ - package mage.cards.r; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; -import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +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; @@ -16,22 +13,23 @@ import mage.constants.SubType; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class RhoxMeditant extends CardImpl { - - private static final FilterControlledPermanent filter = new FilterControlledPermanent("green permanent"); - + + private static final FilterControlledPermanent filter = new FilterControlledPermanent("you control a green permanent"); + static { filter.add(new ColorPredicate(ObjectColor.GREEN)); } - - private static final String rule = "When {this} enters, if you control a green permanent, draw a card."; + + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); public RhoxMeditant(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.RHINO); this.subtype.add(SubType.MONK); @@ -39,9 +37,7 @@ public final class RhoxMeditant extends CardImpl { this.toughness = new MageInt(4); // When Rhox Meditant enters the battlefield, if you control a green permanent, draw a card. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1), false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new PermanentsOnTheBattlefieldCondition(filter), rule)); - + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)).withInterveningIf(condition)); } private RhoxMeditant(final RhoxMeditant card) { diff --git a/Mage.Sets/src/mage/cards/r/RictusRobber.java b/Mage.Sets/src/mage/cards/r/RictusRobber.java index caedfac1ebf..b3eca840cf5 100644 --- a/Mage.Sets/src/mage/cards/r/RictusRobber.java +++ b/Mage.Sets/src/mage/cards/r/RictusRobber.java @@ -3,7 +3,6 @@ package mage.cards.r; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.MorbidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.hint.common.MorbidHint; import mage.abilities.keyword.PlotAbility; @@ -29,11 +28,8 @@ public final class RictusRobber extends CardImpl { this.toughness = new MageInt(3); // When Rictus Robber enters the battlefield, if a creature died this turn, create a 2/2 blue and black Zombie Rogue creature token. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ZombieRogueToken())), - MorbidCondition.instance, - "When {this} enters, if a creature died this turn, create a 2/2 blue and black Zombie Rogue creature token." - ).addHint(MorbidHint.instance)); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ZombieRogueToken())) + .withInterveningIf(MorbidCondition.instance).addHint(MorbidHint.instance)); // Plot {2}{B} this.addAbility(new PlotAbility("{2}{B}")); diff --git a/Mage.Sets/src/mage/cards/r/RiddlemasterSphinx.java b/Mage.Sets/src/mage/cards/r/RiddlemasterSphinx.java index dd84c95e107..3e575d469bf 100644 --- a/Mage.Sets/src/mage/cards/r/RiddlemasterSphinx.java +++ b/Mage.Sets/src/mage/cards/r/RiddlemasterSphinx.java @@ -11,8 +11,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author TheElk801 @@ -31,7 +34,7 @@ public final class RiddlemasterSphinx extends CardImpl { // When Riddlemaster Sphinx enters the battlefield, you may return target creature an opponent controls to its owner's hand. Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RideDown.java b/Mage.Sets/src/mage/cards/r/RideDown.java index aa53517e959..ba2b17c53a7 100644 --- a/Mage.Sets/src/mage/cards/r/RideDown.java +++ b/Mage.Sets/src/mage/cards/r/RideDown.java @@ -17,6 +17,7 @@ import mage.game.Game; import mage.game.combat.CombatGroup; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; @@ -37,7 +38,7 @@ public final class RideDown extends CardImpl { // Destroy target blocking creature. Creatures that were blocked by that creature this combat gain trample until end of turn. this.getSpellAbility().addEffect(new RideDownEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } diff --git a/Mage.Sets/src/mage/cards/r/Righteousness.java b/Mage.Sets/src/mage/cards/r/Righteousness.java index 70cbd275712..0a6c6294ede 100644 --- a/Mage.Sets/src/mage/cards/r/Righteousness.java +++ b/Mage.Sets/src/mage/cards/r/Righteousness.java @@ -9,6 +9,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.filter.common.FilterBlockingCreature; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -24,7 +25,7 @@ public final class Righteousness extends CardImpl { this.getSpellAbility().addEffect(new BoostTargetEffect(7, 7, Duration.EndOfTurn)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private Righteousness(final Righteousness card) { diff --git a/Mage.Sets/src/mage/cards/r/RilingDawnbreaker.java b/Mage.Sets/src/mage/cards/r/RilingDawnbreaker.java index 21921919b2b..fdb12b8eb59 100644 --- a/Mage.Sets/src/mage/cards/r/RilingDawnbreaker.java +++ b/Mage.Sets/src/mage/cards/r/RilingDawnbreaker.java @@ -16,6 +16,7 @@ import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.game.permanent.token.Soldier22Token; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -46,7 +47,7 @@ public final class RilingDawnbreaker extends OmenCard { // At the beginning of combat on your turn, another target creature you control gets +1/+0 until end of turn. Ability ability = new BeginningOfCombatTriggeredAbility(new BoostTargetEffect(1, 0)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // Signaling Roar diff --git a/Mage.Sets/src/mage/cards/r/RimehornAurochs.java b/Mage.Sets/src/mage/cards/r/RimehornAurochs.java index 36926fd0039..a31e80e47e7 100644 --- a/Mage.Sets/src/mage/cards/r/RimehornAurochs.java +++ b/Mage.Sets/src/mage/cards/r/RimehornAurochs.java @@ -20,6 +20,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.watchers.common.BlockedAttackerWatcher; @@ -53,8 +54,8 @@ public final class RimehornAurochs extends CardImpl { // {2}{S}: Target creature blocks target creature this turn if able. Ability ability = new SimpleActivatedAbility(new RimehornAurochsEffect(), new ManaCostsImpl<>("{2}{S}")); - ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature that must block"))); - ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature that is to be blocked"))); + ability.addTarget(new TargetPermanent(new FilterCreaturePermanent("creature that must block"))); + ability.addTarget(new TargetPermanent(new FilterCreaturePermanent("creature that is to be blocked"))); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RimescaleDragon.java b/Mage.Sets/src/mage/cards/r/RimescaleDragon.java index ebfd7ba63f1..0d6218c7bf2 100644 --- a/Mage.Sets/src/mage/cards/r/RimescaleDragon.java +++ b/Mage.Sets/src/mage/cards/r/RimescaleDragon.java @@ -20,7 +20,6 @@ import mage.target.common.TargetCreaturePermanent; import java.util.UUID; /** - * * @author JRHerlehy */ public final class RimescaleDragon extends CardImpl { @@ -33,7 +32,7 @@ public final class RimescaleDragon extends CardImpl { public RimescaleDragon(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{R}{R}"); - + this.supertype.add(SuperType.SNOW); this.subtype.add(SubType.DRAGON); this.power = new MageInt(5); @@ -50,7 +49,7 @@ public final class RimescaleDragon extends CardImpl { Effect effect = new AddCountersTargetEffect(CounterType.ICE.createInstance()); effect.setText("and put an ice counter on it"); ability.addEffect(effect); - ability.addTarget(new TargetCreaturePermanent(1)); + ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); // Creatures with ice counters on them don't untap during their controllers' untap steps. diff --git a/Mage.Sets/src/mage/cards/r/RimewindCryomancer.java b/Mage.Sets/src/mage/cards/r/RimewindCryomancer.java index 5eeca35b0f8..12588de2d9f 100644 --- a/Mage.Sets/src/mage/cards/r/RimewindCryomancer.java +++ b/Mage.Sets/src/mage/cards/r/RimewindCryomancer.java @@ -1,10 +1,9 @@ - package mage.cards.r; -import java.util.UUID; 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.GenericManaCost; @@ -12,37 +11,39 @@ import mage.abilities.effects.common.CounterTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.ComparisonType; +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.TargetActivatedAbility; +import java.util.UUID; + /** - * * @author fireshoes */ public final class RimewindCryomancer extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent("you control four or more snow permanents"); + private static final FilterPermanent filter = new FilterControlledPermanent("you control four or more snow permanents"); static { filter.add(SuperType.SNOW.getPredicate()); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 3); + public RimewindCryomancer(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WIZARD); this.power = new MageInt(2); this.toughness = new MageInt(3); // {1}, {tap}: Counter target activated ability. Activate this ability only if you control four or more snow permanents. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new CounterTargetEffect(), - new GenericManaCost(1), - new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 3)); + Ability ability = new ActivateIfConditionActivatedAbility( + new CounterTargetEffect(), new GenericManaCost(1), condition + ); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetActivatedAbility()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/r/RimewindTaskmage.java b/Mage.Sets/src/mage/cards/r/RimewindTaskmage.java index c0c2a709d71..c1b49f2160e 100644 --- a/Mage.Sets/src/mage/cards/r/RimewindTaskmage.java +++ b/Mage.Sets/src/mage/cards/r/RimewindTaskmage.java @@ -1,10 +1,9 @@ - package mage.cards.r; -import java.util.UUID; 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.GenericManaCost; @@ -12,15 +11,15 @@ import mage.abilities.effects.common.MayTapOrUntapTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.ComparisonType; +import mage.constants.SubType; import mage.constants.SuperType; -import mage.constants.Zone; import mage.filter.common.FilterControlledPermanent; import mage.target.TargetPermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class RimewindTaskmage extends CardImpl { @@ -31,18 +30,19 @@ public final class RimewindTaskmage extends CardImpl { filter.add(SuperType.SNOW.getPredicate()); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 3); + public RimewindTaskmage(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.HUMAN); this.subtype.add(SubType.WIZARD); this.power = new MageInt(1); this.toughness = new MageInt(2); // {1}, {tap}: You may tap or untap target permanent. Activate this ability only if you control four or more snow permanents. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new MayTapOrUntapTargetEffect(), - new GenericManaCost(1), - new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 3)); + Ability ability = new ActivateIfConditionActivatedAbility( + new MayTapOrUntapTargetEffect(), new GenericManaCost(1), condition + ); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetPermanent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/r/RisonaAsariCommander.java b/Mage.Sets/src/mage/cards/r/RisonaAsariCommander.java index bd0bbdeba0a..ca678994940 100644 --- a/Mage.Sets/src/mage/cards/r/RisonaAsariCommander.java +++ b/Mage.Sets/src/mage/cards/r/RisonaAsariCommander.java @@ -45,7 +45,7 @@ public final class RisonaAsariCommander extends CardImpl { // Whenever Risona, Asari Commander deals combat damage to a player, if it doesn't have an indestructible counter on it, put an indestructible counter on it. this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new AddCountersSourceEffect( CounterType.INDESTRUCTIBLE.createInstance()), false - ).withInterveningIf(RisonaAsariCommanderCondition.instance)); + ).withInterveningIf(RisonaAsariCommanderCondition.instance).withRuleTextReplacement(true)); // Whenever combat damage is dealt to you, remove an indestructible counter from Risona. this.addAbility(new RisonaAsariCommanderTriggeredAbility()); diff --git a/Mage.Sets/src/mage/cards/r/RitesOfReaping.java b/Mage.Sets/src/mage/cards/r/RitesOfReaping.java index f44dd378d39..42a3bce85af 100644 --- a/Mage.Sets/src/mage/cards/r/RitesOfReaping.java +++ b/Mage.Sets/src/mage/cards/r/RitesOfReaping.java @@ -1,45 +1,31 @@ - package mage.cards.r; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.effects.ContinuousEffectImpl; +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.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.other.AnotherTargetPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.SecondTargetPointer; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class RitesOfReaping extends CardImpl { public RitesOfReaping(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{B}{G}"); - + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{B}{G}"); // Target creature gets +3/+3 until end of turn. Another target creature gets -3/-3 until end of turn. - this.getSpellAbility().addEffect(new RitesOfReapingEffect()); - - FilterCreaturePermanent filter1 = new FilterCreaturePermanent("creature (gets +3/+3 until end of turn)"); - TargetCreaturePermanent target1 = new TargetCreaturePermanent(filter1); - target1.setTargetTag(1); - this.getSpellAbility().addTarget(target1); - - FilterCreaturePermanent filter2 = new FilterCreaturePermanent("another creature (gets -3/-3 until end of turn)"); - filter2.add(new AnotherTargetPredicate(2)); - TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter2); - target2.setTargetTag(2); - this.getSpellAbility().addTarget(target2); + this.getSpellAbility().addEffect(new BoostTargetEffect(3, 3)); + this.getSpellAbility().addEffect(new BoostTargetEffect(-3, -3) + .setTargetPointer(new SecondTargetPointer()) + .setText("Another target creature gets -3/-3 until end of turn")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent().withChooseHint("+3/+3").setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2).withChooseHint("-3/-3").setTargetTag(2)); } private RitesOfReaping(final RitesOfReaping card) { @@ -51,35 +37,3 @@ public final class RitesOfReaping extends CardImpl { return new RitesOfReaping(this); } } - -class RitesOfReapingEffect extends ContinuousEffectImpl { - - RitesOfReapingEffect() { - super(Duration.EndOfTurn, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature); - this.staticText = "Target creature gets +3/+3 until end of turn. Another target creature gets -3/-3 until end of turn"; - } - - private RitesOfReapingEffect(final RitesOfReapingEffect effect) { - super(effect); - } - - @Override - public RitesOfReapingEffect copy() { - return new RitesOfReapingEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getFirstTarget()); - if (permanent != null) { - permanent.addPower(3); - permanent.addToughness(3); - } - permanent = game.getPermanent(source.getTargets().get(1).getFirstTarget()); - if (permanent != null) { - permanent.addPower(-3); - permanent.addToughness(-3); - } - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/r/RitualGuardian.java b/Mage.Sets/src/mage/cards/r/RitualGuardian.java index 4b0e08f5126..df4d4403494 100644 --- a/Mage.Sets/src/mage/cards/r/RitualGuardian.java +++ b/Mage.Sets/src/mage/cards/r/RitualGuardian.java @@ -1,15 +1,17 @@ package mage.cards.r; import mage.MageInt; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.condition.common.CovenCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.hint.common.CovenHint; import mage.abilities.keyword.LifelinkAbility; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.AbilityWord; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; import java.util.UUID; @@ -27,14 +29,9 @@ public final class RitualGuardian extends CardImpl { this.toughness = new MageInt(2); // Coven — At the beginning of combat on your turn, if you control three or more creatures with different powers, Ritual Guardian gains lifelink until end of turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility( - new GainAbilitySourceEffect( - LifelinkAbility.getInstance(), Duration.EndOfTurn - ) - ), CovenCondition.instance, "At the beginning of combat on your turn, if you control three " + - "or more creatures with different powers, {this} gains lifelink until end of turn." - ).addHint(CovenHint.instance).setAbilityWord(AbilityWord.COVEN)); + this.addAbility(new BeginningOfCombatTriggeredAbility(new GainAbilitySourceEffect( + LifelinkAbility.getInstance(), Duration.EndOfTurn + )).withInterveningIf(CovenCondition.instance).addHint(CovenHint.instance).setAbilityWord(AbilityWord.COVEN)); } private RitualGuardian(final RitualGuardian card) { diff --git a/Mage.Sets/src/mage/cards/r/RitualOfTheMachine.java b/Mage.Sets/src/mage/cards/r/RitualOfTheMachine.java index e53f1fd0d7a..f341cf356c1 100644 --- a/Mage.Sets/src/mage/cards/r/RitualOfTheMachine.java +++ b/Mage.Sets/src/mage/cards/r/RitualOfTheMachine.java @@ -13,6 +13,7 @@ import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; @@ -36,7 +37,7 @@ public final class RitualOfTheMachine extends CardImpl { this.getSpellAbility().addCost(new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_CREATURE)); // Gain control of target nonartifact, nonblack creature. this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.EndOfGame)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private RitualOfTheMachine(final RitualOfTheMachine card) { diff --git a/Mage.Sets/src/mage/cards/r/RivalsDuel.java b/Mage.Sets/src/mage/cards/r/RivalsDuel.java index ce690c589b0..8e4851faec7 100644 --- a/Mage.Sets/src/mage/cards/r/RivalsDuel.java +++ b/Mage.Sets/src/mage/cards/r/RivalsDuel.java @@ -1,19 +1,23 @@ package mage.cards.r; -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.filter.StaticFilters; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.target.common.TargetCreaturePermanentWithDifferentTypes; +import mage.target.TargetPermanent; + +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; /** - * * @author LevelX2 */ public final class RivalsDuel extends CardImpl { @@ -22,9 +26,8 @@ public final class RivalsDuel extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}"); // Choose two target creatures that share no creature types. Those creatures fight each other. - this.getSpellAbility().addEffect(new RivalsDuelFightTargetsEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanentWithDifferentTypes(2, 2, StaticFilters.FILTER_PERMANENT_CREATURE, false)); - + this.getSpellAbility().addEffect(new RivalsDuelEffect()); + this.getSpellAbility().addTarget(new RivalsDuelTarget()); } private RivalsDuel(final RivalsDuel card) { @@ -37,42 +40,68 @@ public final class RivalsDuel extends CardImpl { } } -class RivalsDuelFightTargetsEffect extends OneShotEffect { +class RivalsDuelEffect extends OneShotEffect { - RivalsDuelFightTargetsEffect() { - super(Outcome.Damage); - staticText = "Choose two target creatures that share no creature types. " + - "Those creatures fight each other. (Each deals damage equal to its power to the other.)"; + RivalsDuelEffect() { + super(Outcome.Benefit); + staticText = "choose two target creatures that share no creature types. Those creatures fight each other"; } - private RivalsDuelFightTargetsEffect(final RivalsDuelFightTargetsEffect effect) { + private RivalsDuelEffect(final RivalsDuelEffect effect) { super(effect); } @Override - public boolean apply(Game game, Ability source) { - Permanent creature1 = null; - Permanent creature2 = null; - for (UUID targetId : getTargetPointer().getTargets(game, source)) { - if (creature1 == null) { - creature1 = game.getPermanent(targetId); - } else { - creature2 = game.getPermanent(targetId); - } - } - - // 20110930 - 701.10 - if (creature1 != null - && creature2 != null) { - creature1.damage(creature2.getPower().getValue(), creature2.getId(), source, game, false, true); - creature2.damage(creature1.getPower().getValue(), creature1.getId(), source, game, false, true); - return true; - } - return false; + public RivalsDuelEffect copy() { + return new RivalsDuelEffect(this); } @Override - public RivalsDuelFightTargetsEffect copy() { - return new RivalsDuelFightTargetsEffect(this); + public boolean apply(Game game, Ability source) { + List permanents = this + .getTargetPointer() + .getTargets(game, source) + .stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + System.out.println(permanents.size()); + System.out.println(permanents.get(0)); + System.out.println(permanents.get(1)); + return permanents.size() >= 2 && permanents.get(0).fight(permanents.get(1), source, game); + } +} + +class RivalsDuelTarget extends TargetPermanent { + + private static final FilterPermanent filter = new FilterCreaturePermanent("creatures that share no creature types"); + + RivalsDuelTarget() { + super(2, 2, filter, false); + } + + private RivalsDuelTarget(final RivalsDuelTarget target) { + super(target); + } + + @Override + public RivalsDuelTarget copy() { + return new RivalsDuelTarget(this); + } + + @Override + public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) { + if (!super.canTarget(controllerId, id, source, game)) { + return false; + } + Permanent creature = game.getPermanent(id); + return creature != null + && this + .getTargets() + .stream() + .filter(uuid -> !id.equals(uuid)) + .map(game::getPermanent) + .filter(Objects::nonNull) + .noneMatch(permanent -> permanent.shareCreatureTypes(game, creature)); } } diff --git a/Mage.Sets/src/mage/cards/r/Rivendell.java b/Mage.Sets/src/mage/cards/r/Rivendell.java index 4a797a90182..2f0d377e354 100644 --- a/Mage.Sets/src/mage/cards/r/Rivendell.java +++ b/Mage.Sets/src/mage/cards/r/Rivendell.java @@ -12,7 +12,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SuperType; -import mage.constants.Zone; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; @@ -44,9 +43,7 @@ public final class Rivendell extends CardImpl { // {1}{U}, {T}: Scry 2. Activate only if you control a legendary creature. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, - new ScryEffect(2, false), - new ManaCostsImpl<>("{1}{U}"), condition + new ScryEffect(2, false), new ManaCostsImpl<>("{1}{U}"), condition ); ability.addCost(new TapSourceCost()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/r/RiverHeraldsBoon.java b/Mage.Sets/src/mage/cards/r/RiverHeraldsBoon.java index 947e3f67893..6ae8b33d170 100644 --- a/Mage.Sets/src/mage/cards/r/RiverHeraldsBoon.java +++ b/Mage.Sets/src/mage/cards/r/RiverHeraldsBoon.java @@ -1,36 +1,34 @@ - package mage.cards.r; -import java.util.UUID; -import mage.abilities.effects.Effect; 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.common.FilterCreaturePermanent; +import mage.filter.FilterPermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.SecondTargetPointer; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class RiverHeraldsBoon extends CardImpl { + private static final FilterPermanent filter = new FilterPermanent(SubType.MERFOLK, "Merfolk"); + public RiverHeraldsBoon(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}"); // Put a +1/+1 counter on target creature and a +1/+1 counter on up to one target Merfolk. this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance())); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - Effect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance()); - effect.setTargetPointer(new SecondTargetPointer()); - effect.setText("and a +1/+1 counter on up to one target Merfolk"); - this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 1, new FilterCreaturePermanent(SubType.MERFOLK, "Merfolk"), false)); - + this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance()) + .setTargetPointer(new SecondTargetPointer()).setText("and a +1/+1 counter on up to one target Merfolk")); + this.getSpellAbility().addTarget(new TargetPermanent(0, 1, filter)); } private RiverHeraldsBoon(final RiverHeraldsBoon card) { diff --git a/Mage.Sets/src/mage/cards/r/RixMaadiGuildmage.java b/Mage.Sets/src/mage/cards/r/RixMaadiGuildmage.java index d1e671cd5fb..56e662f6d52 100644 --- a/Mage.Sets/src/mage/cards/r/RixMaadiGuildmage.java +++ b/Mage.Sets/src/mage/cards/r/RixMaadiGuildmage.java @@ -19,6 +19,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicate; import mage.game.Game; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.TargetPlayer; import mage.target.common.TargetCreaturePermanent; import mage.watchers.common.PlayerLostLifeWatcher; @@ -45,7 +46,7 @@ public final class RixMaadiGuildmage extends CardImpl { // {B}{R}: Target blocking creature gets -1/-1 until end of turn. SimpleActivatedAbility ability = new SimpleActivatedAbility(new BoostTargetEffect(-1, -1, Duration.EndOfTurn),new ManaCostsImpl<>("{B}{R}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // {B}{R}: Target player who lost life this turn loses 1 life. diff --git a/Mage.Sets/src/mage/cards/r/RoamingGhostlight.java b/Mage.Sets/src/mage/cards/r/RoamingGhostlight.java index 3eb1a648a1b..7a127b1ac3a 100644 --- a/Mage.Sets/src/mage/cards/r/RoamingGhostlight.java +++ b/Mage.Sets/src/mage/cards/r/RoamingGhostlight.java @@ -11,7 +11,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -38,7 +38,7 @@ public final class RoamingGhostlight extends CardImpl { // 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 TargetCreaturePermanent(0, 1, filter, false)); + ability.addTarget(new TargetPermanent(0, 1, filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RoaringPrimadox.java b/Mage.Sets/src/mage/cards/r/RoaringPrimadox.java index 48cadc0c2e3..2dae20f86ce 100644 --- a/Mage.Sets/src/mage/cards/r/RoaringPrimadox.java +++ b/Mage.Sets/src/mage/cards/r/RoaringPrimadox.java @@ -1,31 +1,32 @@ package mage.cards.r; -import java.util.UUID; import mage.MageInt; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.effects.common.ReturnToHandChosenControlledPermanentEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; -import mage.game.events.GameEvent.EventType; + +import java.util.UUID; /** - * * @author North */ public final class RoaringPrimadox extends CardImpl { public RoaringPrimadox(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.BEAST); this.power = new MageInt(4); this.toughness = new MageInt(4); // At the beginning of your upkeep, return a creature you control to its owner's hand. - this.addAbility(new OnEventTriggeredAbility(EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", new ReturnToHandChosenControlledPermanentEffect(StaticFilters.FILTER_CONTROLLED_CREATURE))); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new ReturnToHandChosenControlledPermanentEffect(StaticFilters.FILTER_CONTROLLED_CREATURE) + )); } private RoaringPrimadox(final RoaringPrimadox card) { diff --git a/Mage.Sets/src/mage/cards/r/Roast.java b/Mage.Sets/src/mage/cards/r/Roast.java index 2a1f2d55e15..a030625ce49 100644 --- a/Mage.Sets/src/mage/cards/r/Roast.java +++ b/Mage.Sets/src/mage/cards/r/Roast.java @@ -10,6 +10,7 @@ import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -29,7 +30,7 @@ public final class Roast extends CardImpl { // Roast deals 5 damage to target creature without flying. this.getSpellAbility().addEffect(new DamageTargetEffect(5)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private Roast(final Roast card) { diff --git a/Mage.Sets/src/mage/cards/r/RobberOfTheRich.java b/Mage.Sets/src/mage/cards/r/RobberOfTheRich.java index 2ab326cebe2..7bbfbffefe4 100644 --- a/Mage.Sets/src/mage/cards/r/RobberOfTheRich.java +++ b/Mage.Sets/src/mage/cards/r/RobberOfTheRich.java @@ -4,9 +4,12 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.decorator.ConditionalAsThoughEffect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect; +import mage.abilities.effects.common.asthought.YouMaySpendManaAsAnyColorToCastTargetEffect; import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.Hint; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.ReachAbility; import mage.cards.Card; @@ -15,20 +18,20 @@ import mage.cards.CardSetInfo; import mage.constants.*; import mage.game.Game; import mage.players.Player; +import mage.target.targetpointer.FixedTarget; import mage.util.CardUtil; import mage.watchers.common.AttackedThisTurnWatcher; + import java.util.Objects; import java.util.UUID; -import mage.abilities.decorator.ConditionalAsThoughEffect; -import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect; -import mage.abilities.effects.common.asthought.YouMaySpendManaAsAnyColorToCastTargetEffect; -import mage.target.targetpointer.FixedTarget; /** * @author TheElk801 */ public final class RobberOfTheRich extends CardImpl { + private static final Hint hint = new ConditionHint(new RogueAttackedThisTurnCondition(null)); + public RobberOfTheRich(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); @@ -45,14 +48,9 @@ public final class RobberOfTheRich extends CardImpl { this.addAbility(HasteAbility.getInstance()); // Whenever Robber of the Rich attacks, if defending player has more cards in hand than you, exile the top card of their library. During any turn you attacked with a Rogue, you may cast that card and you may spend mana as though it were mana of any color to cast that spell. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility( - new RobberOfTheRichEffect(), false, "", SetTargetPointer.PLAYER - ), RobberOfTheRichAttacksCondition.instance, "Whenever {this} attacks, " + - "if defending player has more cards in hand than you, exile the top card of their library. " + - "During any turn you attacked with a Rogue, you may cast that card and " + - "you may spend mana as though it were mana of any color to cast that spell." - ).addHint(new ConditionHint(new RogueAttackedThisTurnCondition(null)))); + this.addAbility(new AttacksTriggeredAbility( + new RobberOfTheRichEffect(), false, "", SetTargetPointer.PLAYER + ).withInterveningIf(RobberOfTheRichAttacksCondition.instance).addHint(hint)); } private RobberOfTheRich(final RobberOfTheRich card) { @@ -72,16 +70,21 @@ enum RobberOfTheRichAttacksCondition implements Condition { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); Player player = game.getPlayer(game.getCombat().getDefendingPlayerId(source.getSourceId(), game)); - return controller != null - && player != null + return controller != null + && player != null && controller.getHand().size() < player.getHand().size(); } + + @Override + public String toString() { + return "defending player has more cards in hand than you"; + } } class RogueAttackedThisTurnCondition implements Condition { - + private Ability ability; - + RogueAttackedThisTurnCondition(Ability source) { this.ability = source; } @@ -108,7 +111,7 @@ class RogueAttackedThisTurnCondition implements Condition { @Override public String toString() { - return "During that turn you attacked with a Rogue"; + return "You attacked with a Rogue this turn"; } } @@ -116,6 +119,8 @@ class RobberOfTheRichEffect extends OneShotEffect { RobberOfTheRichEffect() { super(Outcome.Benefit); + staticText = "exile the top card of their library. During any turn you attacked with a Rogue, " + + "you may cast that card and you may spend mana as though it were mana of any color to cast that spell"; } private RobberOfTheRichEffect(final RobberOfTheRichEffect effect) { @@ -131,7 +136,7 @@ class RobberOfTheRichEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); Player damagedPlayer = game.getPlayer(this.getTargetPointer().getFirst(game, source)); - if (controller == null + if (controller == null || damagedPlayer == null) { return false; } diff --git a/Mage.Sets/src/mage/cards/r/RocCharger.java b/Mage.Sets/src/mage/cards/r/RocCharger.java index 7a7212decae..1dee9925353 100644 --- a/Mage.Sets/src/mage/cards/r/RocCharger.java +++ b/Mage.Sets/src/mage/cards/r/RocCharger.java @@ -14,6 +14,7 @@ import mage.constants.Duration; import mage.filter.common.FilterAttackingCreature; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -46,7 +47,7 @@ public final class RocCharger extends CardImpl { Duration.EndOfTurn ), false ); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RoccoCabarettiCaterer.java b/Mage.Sets/src/mage/cards/r/RoccoCabarettiCaterer.java index 16307357db7..a5cd42f5e3e 100644 --- a/Mage.Sets/src/mage/cards/r/RoccoCabarettiCaterer.java +++ b/Mage.Sets/src/mage/cards/r/RoccoCabarettiCaterer.java @@ -3,7 +3,6 @@ package mage.cards.r; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromEverywhereSourceCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.GetXValue; import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; import mage.cards.Card; @@ -42,16 +41,9 @@ public final class RoccoCabarettiCaterer extends CardImpl { this.toughness = new MageInt(1); // When Rocco, Cabaretti Caterer enters the battlefield, if you cast it, you may search your library for a creature card with mana value X or less, put it onto the battlefield, then shuffle. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility( - new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter)), - true - ), - CastFromEverywhereSourceCondition.instance, - "When {this} enters, " + - "if you cast it, you may search your library for a creature card with mana value X or less, " + - "put it onto the battlefield, then shuffle.") - ); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter)), true + ).withInterveningIf(CastFromEverywhereSourceCondition.instance)); } private RoccoCabarettiCaterer(final RoccoCabarettiCaterer card) { diff --git a/Mage.Sets/src/mage/cards/r/RockHydra.java b/Mage.Sets/src/mage/cards/r/RockHydra.java index dc794a77e46..d384833e68e 100644 --- a/Mage.Sets/src/mage/cards/r/RockHydra.java +++ b/Mage.Sets/src/mage/cards/r/RockHydra.java @@ -1,6 +1,5 @@ package mage.cards.r; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; @@ -8,7 +7,7 @@ import mage.abilities.common.SimpleActivatedAbility; 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.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.PreventionEffectImpl; import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect; import mage.abilities.effects.common.PreventDamageToSourceEffect; @@ -16,36 +15,43 @@ 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.Duration; -import mage.constants.PhaseStep; -import mage.constants.Zone; +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 anonymous */ public final class RockHydra extends CardImpl { public RockHydra(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{X}{R}{R}"); - + this.subtype.add(SubType.HYDRA); this.power = new MageInt(0); this.toughness = new MageInt(0); - + // Rock Hydra enters the battlefield with X +1/+1 counters on it. this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.P1P1.createInstance()))); + // For each 1 damage that would be dealt to Rock Hydra, if it has a +1/+1 counter on it, remove a +1/+1 counter from it and prevent that 1 damage. this.addAbility(new SimpleStaticAbility(new RockHydraEffect())); + // {R}: Prevent the next 1 damage that would be dealt to Rock Hydra this turn. - this.addAbility(new SimpleActivatedAbility(new PreventDamageToSourceEffect(Duration.EndOfTurn, 1), new ManaCostsImpl<>("{R}"))); + this.addAbility(new SimpleActivatedAbility( + new PreventDamageToSourceEffect(Duration.EndOfTurn, 1), new ManaCostsImpl<>("{R}") + )); + // {R}{R}{R}: Put a +1/+1 counter on Rock Hydra. Activate this ability only during your upkeep. - this.addAbility(new ConditionalActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance(1)), new ManaCostsImpl<>("{R}{R}{R}"), new IsStepCondition(PhaseStep.UPKEEP), null)); + this.addAbility(new ActivateIfConditionActivatedAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance(1)), + new ManaCostsImpl<>("{R}{R}{R}"), IsStepCondition.getMyUpkeep() + )); } private RockHydra(final RockHydra card) { @@ -95,5 +101,4 @@ class RockHydraEffect extends PreventionEffectImpl { } return false; } - } diff --git a/Mage.Sets/src/mage/cards/r/RocketLauncher.java b/Mage.Sets/src/mage/cards/r/RocketLauncher.java index 810db5ba37f..f5fcb40b204 100644 --- a/Mage.Sets/src/mage/cards/r/RocketLauncher.java +++ b/Mage.Sets/src/mage/cards/r/RocketLauncher.java @@ -4,14 +4,13 @@ import mage.abilities.Ability; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.DestroySourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetAnyTarget; @@ -27,9 +26,9 @@ public final class RocketLauncher extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); // {2}: Rocket Launcher deals 1 damage to any target. Destroy Rocket Launcher at the beginning of the next end step. Activate this ability only if you've controlled Rocket Launcher continuously since the beginning of your most recent turn. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, new DamageTargetEffect(1), - new GenericManaCost(2), RocketLauncherCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new DamageTargetEffect(1), new GenericManaCost(2), RocketLauncherCondition.instance + ); ability.addTarget(new TargetAnyTarget()); ability.addEffect(new CreateDelayedTriggeredAbilityEffect( new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new DestroySourceEffect()) diff --git a/Mage.Sets/src/mage/cards/r/RoonOfTheHiddenRealm.java b/Mage.Sets/src/mage/cards/r/RoonOfTheHiddenRealm.java index b28621a44f0..16e517a6fd9 100644 --- a/Mage.Sets/src/mage/cards/r/RoonOfTheHiddenRealm.java +++ b/Mage.Sets/src/mage/cards/r/RoonOfTheHiddenRealm.java @@ -15,10 +15,13 @@ import mage.constants.SubType; import mage.constants.SuperType; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * @author LevelX2 */ @@ -39,7 +42,7 @@ public final class RoonOfTheHiddenRealm extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // {2}, {tap}: Exile another target creature. Return that card to the battlefield under its owner's control at the beginning of the next end step. Ability ability = new SimpleActivatedAbility(new ExileReturnBattlefieldNextEndStepTargetEffect(), new GenericManaCost(2)); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); ability.addCost(new TapSourceCost()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/r/RoostOfDrakes.java b/Mage.Sets/src/mage/cards/r/RoostOfDrakes.java index ac97dd237b2..adbe06fb6b1 100644 --- a/Mage.Sets/src/mage/cards/r/RoostOfDrakes.java +++ b/Mage.Sets/src/mage/cards/r/RoostOfDrakes.java @@ -3,7 +3,6 @@ package mage.cards.r; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -26,11 +25,7 @@ public final class RoostOfDrakes extends CardImpl { this.addAbility(new KickerAbility("{2}{U}")); // When Roost of Drakes enters the battlefield, if it was kicked, create a 2/2 blue Drake creature token with flying. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new DrakeToken())), - KickedCondition.ONCE, "When {this} enters, if it was kicked, " + - "create a 2/2 blue Drake creature token with flying." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new DrakeToken())).withInterveningIf(KickedCondition.ONCE)); // Whenever you cast a kicked spell, create a 2/2 blue Drake creature token with flying. this.addAbility(new SpellCastControllerTriggeredAbility( diff --git a/Mage.Sets/src/mage/cards/r/RootKinAlly.java b/Mage.Sets/src/mage/cards/r/RootKinAlly.java index a3ae36850e9..f4e8e217bed 100644 --- a/Mage.Sets/src/mage/cards/r/RootKinAlly.java +++ b/Mage.Sets/src/mage/cards/r/RootKinAlly.java @@ -1,7 +1,5 @@ - package mage.cards.r; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapTargetCost; @@ -10,26 +8,27 @@ import mage.abilities.keyword.ConvokeAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; +import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; /** - * * @author emerald000 */ public final class RootKinAlly extends CardImpl { - + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); + static { filter.add(TappedPredicate.UNTAPPED); } public RootKinAlly(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}{G}"); this.subtype.add(SubType.ELEMENTAL); this.subtype.add(SubType.WARRIOR); this.power = new MageInt(3); @@ -37,9 +36,12 @@ public final class RootKinAlly extends CardImpl { // Convoke this.addAbility(new ConvokeAbility()); - + // Tap two untapped creatures you control: Root-Kin Ally gets +2/+2 until end of turn. - this.addAbility(new SimpleActivatedAbility(new BoostSourceEffect(2, 2, Duration.EndOfTurn), new TapTargetCost(new TargetControlledCreaturePermanent(2, 2, filter, true)))); + this.addAbility(new SimpleActivatedAbility( + new BoostSourceEffect(2, 2, Duration.EndOfTurn), + new TapTargetCost(2, StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURES) + )); } private RootKinAlly(final RootKinAlly card) { diff --git a/Mage.Sets/src/mage/cards/r/Roots.java b/Mage.Sets/src/mage/cards/r/Roots.java index de83cbf0074..d142c1bd402 100644 --- a/Mage.Sets/src/mage/cards/r/Roots.java +++ b/Mage.Sets/src/mage/cards/r/Roots.java @@ -38,7 +38,7 @@ public final class Roots extends CardImpl { this.subtype.add(SubType.AURA); // Enchant creature without flying - TargetPermanent auraTarget = new TargetCreaturePermanent(filter); + TargetPermanent auraTarget = new TargetPermanent(filter); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); this.addAbility(new EnchantAbility(auraTarget)); diff --git a/Mage.Sets/src/mage/cards/r/RoseCutthroatRaider.java b/Mage.Sets/src/mage/cards/r/RoseCutthroatRaider.java index 598e86ea29e..0144f57bf14 100644 --- a/Mage.Sets/src/mage/cards/r/RoseCutthroatRaider.java +++ b/Mage.Sets/src/mage/cards/r/RoseCutthroatRaider.java @@ -2,21 +2,16 @@ package mage.cards.r; import mage.MageInt; import mage.Mana; -import mage.abilities.Ability; import mage.abilities.common.EndOfCombatTriggeredAbility; import mage.abilities.common.SacrificePermanentTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.AttackedThisTurnOpponentsCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.mana.AddManaToManaPoolSourceControllerEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AbilityWord; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.SuperType; +import mage.constants.*; import mage.filter.FilterPermanent; import mage.game.permanent.token.JunkToken; import mage.watchers.common.PlayerAttackedWatcher; @@ -47,17 +42,14 @@ public final class RoseCutthroatRaider extends CardImpl { this.addAbility(FirstStrikeAbility.getInstance()); // Raid -- At end of combat on your turn, if you attacked this turn, create a Junk token for each opponent you attacked. - Ability ability = new ConditionalInterveningIfTriggeredAbility(new EndOfCombatTriggeredAbility( - new CreateTokenEffect(new JunkToken(), AttackedThisTurnOpponentsCount.instance), false), RaidCondition.instance, - "At end of combat on your turn, if you attacked this turn, create a Junk token for each opponent you attacked."); - ability.setAbilityWord(AbilityWord.RAID); - ability.addHint(AttackedThisTurnOpponentsCount.getHint()); - ability.addWatcher(new PlayerAttackedWatcher()); - ability.addWatcher(new PlayersAttackedThisTurnWatcher()); - this.addAbility(ability); + this.addAbility(new EndOfCombatTriggeredAbility( + new CreateTokenEffect(new JunkToken(), AttackedThisTurnOpponentsCount.instance) + .setText("create a Junk token for each opponent you attacked"), + TargetController.YOU, false + ).withInterveningIf(RaidCondition.instance).setAbilityWord(AbilityWord.RAID).addHint(AttackedThisTurnOpponentsCount.getHint()), new PlayersAttackedThisTurnWatcher()); // Whenever you sacrifice a Junk, add {R}. - this.addAbility(new SacrificePermanentTriggeredAbility(new AddManaToManaPoolSourceControllerEffect(Mana.RedMana(1)), filter)); + this.addAbility(new SacrificePermanentTriggeredAbility(new AddManaToManaPoolSourceControllerEffect(Mana.RedMana(1)), filter), new PlayerAttackedWatcher()); } private RoseCutthroatRaider(final RoseCutthroatRaider card) { diff --git a/Mage.Sets/src/mage/cards/r/RoyalAssassin.java b/Mage.Sets/src/mage/cards/r/RoyalAssassin.java index f806d427d94..5f49fe6c56e 100644 --- a/Mage.Sets/src/mage/cards/r/RoyalAssassin.java +++ b/Mage.Sets/src/mage/cards/r/RoyalAssassin.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,7 +39,7 @@ public final class RoyalAssassin extends CardImpl { this.toughness = new MageInt(1); Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RubblebeltBraggart.java b/Mage.Sets/src/mage/cards/r/RubblebeltBraggart.java index c6a955abe55..b354f3fde00 100644 --- a/Mage.Sets/src/mage/cards/r/RubblebeltBraggart.java +++ b/Mage.Sets/src/mage/cards/r/RubblebeltBraggart.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SuspectSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -29,11 +28,8 @@ public final class RubblebeltBraggart extends CardImpl { this.toughness = new MageInt(5); // Whenever Rubblebelt Braggart attacks, if it's not suspected, you may suspect it. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new SuspectSourceEffect(), true), - RubblebeltBraggartCondition.instance, "Whenever {this} attacks, " + - "if it's not suspected, you may suspect it." - )); + this.addAbility(new AttacksTriggeredAbility(new SuspectSourceEffect(), true) + .withInterveningIf(RubblebeltBraggartCondition.instance)); } private RubblebeltBraggart(final RubblebeltBraggart card) { @@ -53,7 +49,12 @@ enum RubblebeltBraggartCondition implements Condition { public boolean apply(Game game, Ability source) { return Optional .ofNullable(source.getSourcePermanentIfItStillExists(game)) - .map(permanent -> !permanent.isSuspected()) - .orElse(false); + .filter(permanent -> !permanent.isSuspected()) + .isPresent(); + } + + @Override + public String toString() { + return "it's not suspected"; } } diff --git a/Mage.Sets/src/mage/cards/r/RuinRaider.java b/Mage.Sets/src/mage/cards/r/RuinRaider.java index 80449a637c7..dee50a5af80 100644 --- a/Mage.Sets/src/mage/cards/r/RuinRaider.java +++ b/Mage.Sets/src/mage/cards/r/RuinRaider.java @@ -1,12 +1,10 @@ package mage.cards.r; import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.RevealPutInHandLoseLifeEffect; import mage.abilities.hint.common.RaidHint; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AbilityWord; @@ -30,16 +28,8 @@ public final class RuinRaider extends CardImpl { this.toughness = new MageInt(2); // Raid — At the beginning of your end step, if you attacked this turn, reveal the top card of your library and put that card into your hand. You lose life equal to the card's converted mana cost. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - new RevealPutInHandLoseLifeEffect() - ), RaidCondition.instance, "At the beginning of your end step, " + - "if you attacked this turn, reveal the top card of your library " + - "and put that card into your hand. You lose life equal to the card's mana value." - ); - ability.setAbilityWord(AbilityWord.RAID); - ability.addHint(RaidHint.instance); - this.addAbility(ability, new PlayerAttackedWatcher()); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new RevealPutInHandLoseLifeEffect()) + .withInterveningIf(RaidCondition.instance).setAbilityWord(AbilityWord.RAID).addHint(RaidHint.instance), new PlayerAttackedWatcher()); } private RuinRaider(final RuinRaider card) { diff --git a/Mage.Sets/src/mage/cards/r/RuinsOfOranRief.java b/Mage.Sets/src/mage/cards/r/RuinsOfOranRief.java index b1890609b7b..5968ca5623d 100644 --- a/Mage.Sets/src/mage/cards/r/RuinsOfOranRief.java +++ b/Mage.Sets/src/mage/cards/r/RuinsOfOranRief.java @@ -16,6 +16,7 @@ import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorlessPredicate; import mage.filter.predicate.permanent.EnteredThisTurnPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class RuinsOfOranRief extends CardImpl { this.addAbility(new ColorlessManaAbility()); // {T}: Put a +1/+1 counter on target colorless creature that entered the battlefield this turn. Ability ability = new SimpleActivatedAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/r/RunAwayTogether.java b/Mage.Sets/src/mage/cards/r/RunAwayTogether.java index 1c5857d2be3..d5107d33568 100644 --- a/Mage.Sets/src/mage/cards/r/RunAwayTogether.java +++ b/Mage.Sets/src/mage/cards/r/RunAwayTogether.java @@ -5,10 +5,11 @@ import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import java.util.Objects; import java.util.UUID; @@ -39,9 +40,9 @@ public final class RunAwayTogether extends CardImpl { } } -class RunAwayTogetherTarget extends TargetCreaturePermanent { +class RunAwayTogetherTarget extends TargetPermanent { - private static final FilterCreaturePermanent filter + private static final FilterPermanent filter = new FilterCreaturePermanent("creatures controlled by different players"); RunAwayTogetherTarget() { diff --git a/Mage.Sets/src/mage/cards/r/RunnersBane.java b/Mage.Sets/src/mage/cards/r/RunnersBane.java index 3de7e89bb96..03b3372293f 100644 --- a/Mage.Sets/src/mage/cards/r/RunnersBane.java +++ b/Mage.Sets/src/mage/cards/r/RunnersBane.java @@ -37,7 +37,7 @@ public final class RunnersBane extends CardImpl { // Enchant creature with power 3 or less - TargetPermanent auraTarget = new TargetCreaturePermanent(filter); + TargetPermanent auraTarget = new TargetPermanent(filter); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.UnboostCreature)); Ability ability = new EnchantAbility(auraTarget); diff --git a/Mage.Sets/src/mage/cards/r/RushingTideZubera.java b/Mage.Sets/src/mage/cards/r/RushingTideZubera.java index 5e47d1b2895..059844fd1f5 100644 --- a/Mage.Sets/src/mage/cards/r/RushingTideZubera.java +++ b/Mage.Sets/src/mage/cards/r/RushingTideZubera.java @@ -1,23 +1,21 @@ - package mage.cards.r; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.condition.Condition; -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.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.Optional; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class RushingTideZubera extends CardImpl { @@ -31,9 +29,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 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); + this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(3)).withInterveningIf(RushingTideZuberaCondition.instance)); } private RushingTideZubera(final RushingTideZubera card) { @@ -46,14 +42,19 @@ public final class RushingTideZubera extends CardImpl { } } -class RushingTideZuberaCondition implements Condition { +enum RushingTideZuberaCondition implements Condition { + instance; @Override public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent == null) { - permanent = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD); - } - return permanent.getDamage() > 3; + return Optional + .ofNullable(source.getSourcePermanentOrLKI(game)) + .map(Permanent::getDamage) + .orElse(0) >= 4; + } + + @Override + public String toString() { + return "4 or more damage was dealt to it this turn"; } } diff --git a/Mage.Sets/src/mage/cards/r/RuthlessInstincts.java b/Mage.Sets/src/mage/cards/r/RuthlessInstincts.java index f71007635d8..5f8044691ef 100644 --- a/Mage.Sets/src/mage/cards/r/RuthlessInstincts.java +++ b/Mage.Sets/src/mage/cards/r/RuthlessInstincts.java @@ -18,6 +18,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.AttackingPredicate; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -48,7 +49,7 @@ public final class RuthlessInstincts extends CardImpl { effect = new UntapTargetEffect(); effect.setText("Untap it"); this.getSpellAbility().addEffect(effect); - Target target = new TargetCreaturePermanent(filter); + Target target = new TargetPermanent(filter); this.getSpellAbility().addTarget(target); // * Target attacking creature gets +2/+2 and gains trample until end of turn. effect = new BoostTargetEffect(2,2,Duration.EndOfTurn); @@ -57,7 +58,7 @@ public final class RuthlessInstincts extends CardImpl { effect = new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn); effect.setText("and gains trample until end of turn"); mode.addEffect(effect); - mode.addTarget(new TargetCreaturePermanent(filterAttacking)); + mode.addTarget(new TargetPermanent(filterAttacking)); this.getSpellAbility().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/r/RuthlessPredation.java b/Mage.Sets/src/mage/cards/r/RuthlessPredation.java index 16e460c17d2..fcbb3bf8a07 100644 --- a/Mage.Sets/src/mage/cards/r/RuthlessPredation.java +++ b/Mage.Sets/src/mage/cards/r/RuthlessPredation.java @@ -11,9 +11,12 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.filter.StaticFilters; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * * @author @stwalsh4118 @@ -33,7 +36,7 @@ public final class RuthlessPredation extends CardImpl { "(Each deals damage equal to its power to the other.)"); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - Target target = new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL); + Target target = new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL); this.getSpellAbility().addTarget(target); } diff --git a/Mage.Sets/src/mage/cards/s/SabertoothOutrider.java b/Mage.Sets/src/mage/cards/s/SabertoothOutrider.java index 3a1b47c49f9..6fed07a0aa6 100644 --- a/Mage.Sets/src/mage/cards/s/SabertoothOutrider.java +++ b/Mage.Sets/src/mage/cards/s/SabertoothOutrider.java @@ -1,28 +1,28 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.FormidableCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; +import mage.constants.SubType; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class SabertoothOutrider extends CardImpl { public SabertoothOutrider(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.HUMAN); this.subtype.add(SubType.WARRIOR); this.power = new MageInt(4); @@ -32,12 +32,9 @@ public final class SabertoothOutrider extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // Formidable — Whenever Sabertooth Outrider attacks, if creatures you control have total power 8 or greater, Sabertooth Outrider gains first strike until end of turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), false), - FormidableCondition.instance, - "Formidable — Whenever {this} attacks, if creatures you control have total power 8 or greater, {this} gains first strike until end of turn." - )); - + this.addAbility(new AttacksTriggeredAbility(new GainAbilitySourceEffect( + FirstStrikeAbility.getInstance(), Duration.EndOfTurn + )).withInterveningIf(FormidableCondition.instance).setAbilityWord(AbilityWord.FORMIDABLE)); } private SabertoothOutrider(final SabertoothOutrider card) { diff --git a/Mage.Sets/src/mage/cards/s/SacredWhiteDeer.java b/Mage.Sets/src/mage/cards/s/SacredWhiteDeer.java index d0d81b66d3e..a40e0766d37 100644 --- a/Mage.Sets/src/mage/cards/s/SacredWhiteDeer.java +++ b/Mage.Sets/src/mage/cards/s/SacredWhiteDeer.java @@ -1,34 +1,29 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; +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.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.GainLifeEffect; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.TargetController; -import mage.constants.Zone; -import mage.filter.FilterPermanent; +import mage.constants.SubType; +import mage.filter.common.FilterControlledPlaneswalkerPermanent; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class SacredWhiteDeer extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("you control a Yanggu planeswalker"); - - static { - filter.add(TargetController.YOU.getControllerPredicate()); - filter.add(CardType.PLANESWALKER.getPredicate()); - filter.add(SubType.YANGGU.getPredicate()); - } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPlaneswalkerPermanent(SubType.YANGGU, "you control a Yanggu planeswalker") + ); public SacredWhiteDeer(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); @@ -38,11 +33,8 @@ public final class SacredWhiteDeer extends CardImpl { this.toughness = new MageInt(2); // {3}{G}, {T}: You gain 4 life. Activate this ability only if you control a Yanggu planeswalker. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, - new GainLifeEffect(4), - new ManaCostsImpl<>("{3}{G}"), - new PermanentsOnTheBattlefieldCondition(filter) + Ability ability = new ActivateIfConditionActivatedAbility( + new GainLifeEffect(4), new ManaCostsImpl<>("{3}{G}"), condition ); ability.addCost(new TapSourceCost()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/s/SaddlebackLagac.java b/Mage.Sets/src/mage/cards/s/SaddlebackLagac.java index 2e1c3128667..d0d615ebdff 100644 --- a/Mage.Sets/src/mage/cards/s/SaddlebackLagac.java +++ b/Mage.Sets/src/mage/cards/s/SaddlebackLagac.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; @@ -14,8 +12,9 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class SaddlebackLagac extends CardImpl { @@ -27,16 +26,15 @@ public final class SaddlebackLagac extends CardImpl { } public SaddlebackLagac(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.LIZARD); this.power = new MageInt(3); this.toughness = new MageInt(1); // When Saddleback Lagac enters the battlefield, support 2. Ability ability = new EntersBattlefieldTriggeredAbility(new SupportEffect(this, 2, true), false); - ability.addTarget(new TargetCreaturePermanent(0, 2, FILTER, false)); + ability.addTarget(new TargetCreaturePermanent(0, 2)); this.addAbility(ability); - } private SaddlebackLagac(final SaddlebackLagac card) { diff --git a/Mage.Sets/src/mage/cards/s/SalvationSwan.java b/Mage.Sets/src/mage/cards/s/SalvationSwan.java index 18ede9d824b..9b5b56c967d 100644 --- a/Mage.Sets/src/mage/cards/s/SalvationSwan.java +++ b/Mage.Sets/src/mage/cards/s/SalvationSwan.java @@ -19,6 +19,7 @@ import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.Zone; import mage.counters.CounterType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.Predicates; @@ -26,7 +27,7 @@ import mage.filter.predicate.mageobject.AbilityPredicate; import mage.game.ExileZone; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.targetpointer.FixedTargets; import mage.util.CardUtil; @@ -39,8 +40,8 @@ public final class SalvationSwan extends CardImpl { static final String VALUE_PREFIX = "SalvationSwanExile"; - private static final FilterControlledPermanent filterBird = new FilterControlledPermanent(SubType.BIRD, "Bird you control"); - private static final FilterControlledCreaturePermanent filterWithoutFlying = new FilterControlledCreaturePermanent("creature you control without flying"); + private static final FilterPermanent filterBird = new FilterControlledPermanent(SubType.BIRD, "Bird you control"); + private static final FilterPermanent filterWithoutFlying = new FilterControlledCreaturePermanent("creature you control without flying"); static { filterWithoutFlying.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); @@ -64,7 +65,7 @@ public final class SalvationSwan extends CardImpl { Ability ability = new EntersBattlefieldThisOrAnotherTriggeredAbility( new SalvationSwanTargetEffect(), filterBird, false, false ); - ability.addTarget(new TargetControlledCreaturePermanent(0, 1, filterWithoutFlying, false)); + ability.addTarget(new TargetPermanent(0, 1, filterWithoutFlying)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SamiShipsEngineer.java b/Mage.Sets/src/mage/cards/s/SamiShipsEngineer.java new file mode 100644 index 00000000000..18e9fda5562 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SamiShipsEngineer.java @@ -0,0 +1,63 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; +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.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.permanent.token.RobotToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SamiShipsEngineer extends CardImpl { + + private static final FilterPermanent filter + = new FilterControlledCreaturePermanent("you control two or more tapped creatures"); + + static { + filter.add(TappedPredicate.TAPPED); + } + + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); + private static final Hint hint = new ValueHint( + "Tapped creatures you control", new PermanentsOnBattlefieldCount(filter) + ); + + public SamiShipsEngineer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{W}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ARTIFICER); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // At the beginning of your end step, if you control two or more tapped creatures, create a tapped 2/2 colorless Robot artifact creature token. + this.addAbility(new BeginningOfEndStepTriggeredAbility( + new CreateTokenEffect(new RobotToken(), 1, true) + ).withInterveningIf(condition).addHint(hint)); + } + + private SamiShipsEngineer(final SamiShipsEngineer card) { + super(card); + } + + @Override + public SamiShipsEngineer copy() { + return new SamiShipsEngineer(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SamutVoiceOfDissent.java b/Mage.Sets/src/mage/cards/s/SamutVoiceOfDissent.java index f3439375be3..965ab22d815 100644 --- a/Mage.Sets/src/mage/cards/s/SamutVoiceOfDissent.java +++ b/Mage.Sets/src/mage/cards/s/SamutVoiceOfDissent.java @@ -24,6 +24,7 @@ import mage.constants.Zone; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -65,7 +66,7 @@ public final class SamutVoiceOfDissent extends CardImpl { //W, Tap: Untap another target creature. Ability ability = new SimpleActivatedAbility(new UntapTargetEffect(), new ManaCostsImpl<>("{W}")); - ability.addTarget(new TargetCreaturePermanent(filter2)); + ability.addTarget(new TargetPermanent(filter2)); ability.addCost(new TapSourceCost()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/s/SanctuaryRaptor.java b/Mage.Sets/src/mage/cards/s/SanctuaryRaptor.java index d42dffaa0b3..864f67a28d2 100644 --- a/Mage.Sets/src/mage/cards/s/SanctuaryRaptor.java +++ b/Mage.Sets/src/mage/cards/s/SanctuaryRaptor.java @@ -5,7 +5,6 @@ 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.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; @@ -30,16 +29,14 @@ import java.util.UUID; */ public final class SanctuaryRaptor extends CardImpl { - private static final FilterPermanent filter = new FilterControlledPermanent(); + private static final FilterPermanent filter = new FilterControlledPermanent("you control three or more tokens"); static { filter.add(TokenPredicate.TRUE); } - private static final Condition condition - = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 2); - private static final Hint hint - = new ValueHint("Tokens you control", new PermanentsOnBattlefieldCount(filter)); + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 2); + private static final Hint hint = new ValueHint("Tokens you control", new PermanentsOnBattlefieldCount(filter)); public SanctuaryRaptor(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}"); @@ -52,13 +49,12 @@ public final class SanctuaryRaptor extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Whenever Sanctuary Raptor attacks, if you control three or more tokens, Sanctuary Raptor gets +2/+0 and gains first strike until end of turn. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility( - new BoostSourceEffect(2, 0, Duration.EndOfTurn), false - ), condition, "Whenever {this} attacks, if you control three or more tokens, " + - "{this} gets +2/+0 and gains first strike until end of turn." - ); - ability.addEffect(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn)); + Ability ability = new AttacksTriggeredAbility(new BoostSourceEffect( + 2, 0, Duration.EndOfTurn + ).setText("{this} gets +2/+0")).withInterveningIf(condition); + ability.addEffect(new GainAbilitySourceEffect( + FirstStrikeAbility.getInstance(), Duration.EndOfTurn + ).setText("and gains first strike until end of turn")); this.addAbility(ability.addHint(hint)); } diff --git a/Mage.Sets/src/mage/cards/s/SanctumOfEternity.java b/Mage.Sets/src/mage/cards/s/SanctumOfEternity.java index 337759ea92b..1368f9d8c9a 100644 --- a/Mage.Sets/src/mage/cards/s/SanctumOfEternity.java +++ b/Mage.Sets/src/mage/cards/s/SanctumOfEternity.java @@ -6,13 +6,11 @@ import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.ReturnToHandTargetEffect; -import mage.abilities.hint.common.MyTurnHint; import mage.abilities.mana.ColorlessManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.TargetController; -import mage.constants.Zone; import mage.filter.FilterPermanent; import mage.filter.predicate.mageobject.CommanderPredicate; import mage.target.TargetPermanent; @@ -39,13 +37,12 @@ public final class SanctumOfEternity extends CardImpl { // {2}, {T}: Return target commander you own from the battlefield to your hand. Activate this ability only during your turn. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new ReturnToHandTargetEffect() - .setText("return target commander you own from the battlefield to your hand"), + new ReturnToHandTargetEffect() + .setText("return target commander you own from the battlefield to your hand"), new GenericManaCost(2), MyTurnCondition.instance ); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetPermanent(filter)); - ability.addHint(MyTurnHint.instance); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SandScout.java b/Mage.Sets/src/mage/cards/s/SandScout.java index 85f28effe3b..8011c5c3f82 100644 --- a/Mage.Sets/src/mage/cards/s/SandScout.java +++ b/Mage.Sets/src/mage/cards/s/SandScout.java @@ -5,7 +5,6 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.PutCardIntoGraveFromAnywhereAllTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.OpponentControlsMoreCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; import mage.cards.CardImpl; @@ -31,7 +30,7 @@ public final class SandScout extends CardImpl { filter.add(SubType.DESERT.getPredicate()); } - private static final Condition condition = new OpponentControlsMoreCondition(StaticFilters.FILTER_LAND); + private static final Condition condition = new OpponentControlsMoreCondition(StaticFilters.FILTER_LANDS); public SandScout(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); @@ -42,11 +41,7 @@ public final class SandScout extends CardImpl { this.toughness = new MageInt(2); // When Sand Scout enters the battlefield, if an opponent controls more lands than you, search your library for a Desert card, put it onto the battlefield tapped, then shuffle. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility( - new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter), true)), - condition, "When {this} enters, if an opponent controls more lands than you, " + - "search your library for a Desert card, put it onto the battlefield tapped, then shuffle." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter), true)).withInterveningIf(condition)); // Whenever one or more land cards are put into your graveyard from anywhere, create a 1/1 red, green, and white Sand Warrior creature token. This ability triggers only once each turn. this.addAbility(new PutCardIntoGraveFromAnywhereAllTriggeredAbility( diff --git a/Mage.Sets/src/mage/cards/s/SandStrangler.java b/Mage.Sets/src/mage/cards/s/SandStrangler.java index f6244134b8a..e3531ccdda5 100644 --- a/Mage.Sets/src/mage/cards/s/SandStrangler.java +++ b/Mage.Sets/src/mage/cards/s/SandStrangler.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.DesertControlledOrGraveyardCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -27,11 +26,8 @@ public final class SandStrangler extends CardImpl { this.toughness = new MageInt(3); // When Sand Strangler enters the battlefield, if you control a Desert or there is a Desert card in your graveyard, you may have Sand Strangler deal 3 damage to target creature. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(3), true), - DesertControlledOrGraveyardCondition.instance, "When {this} enters, " + - "if you control a Desert or there is a Desert card in your graveyard, " + - "you may have {this} deal 3 damage to target creature."); + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(3), true) + .withInterveningIf(DesertControlledOrGraveyardCondition.instance); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability.addHint(DesertControlledOrGraveyardCondition.getHint())); } diff --git a/Mage.Sets/src/mage/cards/s/Sandsower.java b/Mage.Sets/src/mage/cards/s/Sandsower.java index 6f66eef7c64..be864f27821 100644 --- a/Mage.Sets/src/mage/cards/s/Sandsower.java +++ b/Mage.Sets/src/mage/cards/s/Sandsower.java @@ -1,7 +1,5 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -11,33 +9,25 @@ 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.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.filter.StaticFilters; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author Loki */ public final class Sandsower extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); - - static { - filter.add(TappedPredicate.UNTAPPED); - } - public Sandsower(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.SPIRIT); this.power = new MageInt(1); this.toughness = new MageInt(3); // Tap three untapped creatures you control: Tap target creature. - Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new TapTargetCost(new TargetControlledCreaturePermanent(3, 3, filter, true))); + Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new TapTargetCost(3, StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURES)); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SandstalkerMoloch.java b/Mage.Sets/src/mage/cards/s/SandstalkerMoloch.java index c8ee8f4d377..a86566afa01 100644 --- a/Mage.Sets/src/mage/cards/s/SandstalkerMoloch.java +++ b/Mage.Sets/src/mage/cards/s/SandstalkerMoloch.java @@ -4,7 +4,7 @@ import mage.MageInt; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; import mage.abilities.keyword.FlashAbility; import mage.cards.CardImpl; @@ -39,17 +39,10 @@ public final class SandstalkerMoloch extends CardImpl { this.addAbility(FlashAbility.getInstance()); // When Sandstalker Moloch enters the battlefield, if an opponent cast a blue and/or black spell this turn, look at the top four cards of your library. You may reveal a permanent 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 ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility( - new LookLibraryAndPickControllerEffect( - 4, 1, StaticFilters.FILTER_CARD_A_PERMANENT, - PutCards.HAND, PutCards.BOTTOM_RANDOM - ) - ), SandstalkerMolochWatcher::checkPlayer, "When {this} enters, " + - "if an opponent cast a blue and/or black spell this turn, look at the top four cards " + - "of your library. You may reveal a permanent card from among them and put it into your hand. " + - "Put the rest on the bottom of your library in a random order." - ), new SandstalkerMolochWatcher()); + this.addAbility(new EntersBattlefieldTriggeredAbility(new LookLibraryAndPickControllerEffect( + 4, 1, StaticFilters.FILTER_CARD_A_PERMANENT, + PutCards.HAND, PutCards.BOTTOM_RANDOM + )).withInterveningIf(SandstalkerMolochCondition.instance), new SandstalkerMolochWatcher()); } private SandstalkerMoloch(final SandstalkerMoloch card) { @@ -62,6 +55,20 @@ public final class SandstalkerMoloch extends CardImpl { } } +enum SandstalkerMolochCondition implements Condition { + instance; + + @Override + public boolean apply(Game game, Ability source) { + return SandstalkerMolochWatcher.checkPlayer(game, source); + } + + @Override + public String toString() { + return "an opponent cast a blue and/or black spell this turn"; + } +} + class SandstalkerMolochWatcher extends Watcher { private final Set players = new HashSet<>(); diff --git a/Mage.Sets/src/mage/cards/s/SanguineSpy.java b/Mage.Sets/src/mage/cards/s/SanguineSpy.java index 799e7640e67..d6d98268789 100644 --- a/Mage.Sets/src/mage/cards/s/SanguineSpy.java +++ b/Mage.Sets/src/mage/cards/s/SanguineSpy.java @@ -2,19 +2,18 @@ package mage.cards.s; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.DifferentManaValuesInGraveCondition; import mage.abilities.costs.common.PayLifeCost; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.keyword.SurveilEffect; import mage.abilities.hint.common.DifferentManaValuesInGraveHint; import mage.abilities.keyword.LifelinkAbility; import mage.abilities.keyword.MenaceAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -48,12 +47,9 @@ public final class SanguineSpy extends CardImpl { this.addAbility(ability); // At the beginning of your end step, if there are five or more mana values among cards in your graveyard, you may pay 2 life. If you do, draw a card. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new PayLifeCost(2)) - ), DifferentManaValuesInGraveCondition.FIVE, "At the beginning of your end step, if there are " + - "five or more mana values among cards in your graveyard, you may pay 2 life. If you do, draw a card." - ).addHint(DifferentManaValuesInGraveHint.instance)); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new PayLifeCost(2)) + ).withInterveningIf(DifferentManaValuesInGraveCondition.FIVE).addHint(DifferentManaValuesInGraveHint.instance)); } private SanguineSpy(final SanguineSpy card) { diff --git a/Mage.Sets/src/mage/cards/s/SapphireCharm.java b/Mage.Sets/src/mage/cards/s/SapphireCharm.java index e62200aa6d5..25139ec272a 100644 --- a/Mage.Sets/src/mage/cards/s/SapphireCharm.java +++ b/Mage.Sets/src/mage/cards/s/SapphireCharm.java @@ -15,9 +15,12 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.TargetPlayer; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author fireshoes @@ -41,7 +44,7 @@ public final class SapphireCharm extends CardImpl { // or target creature an opponent controls phases out. mode = new Mode(new PhaseOutTargetEffect()); - mode.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + mode.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.getSpellAbility().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/s/SapseepForest.java b/Mage.Sets/src/mage/cards/s/SapseepForest.java index e2e276aa3ab..da3cafae68b 100644 --- a/Mage.Sets/src/mage/cards/s/SapseepForest.java +++ b/Mage.Sets/src/mage/cards/s/SapseepForest.java @@ -1,27 +1,26 @@ - package mage.cards.s; -import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTappedAbility; +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.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.mana.GreenManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.ComparisonType; -import mage.constants.Zone; +import mage.constants.SubType; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class SapseepForest extends CardImpl { @@ -32,8 +31,10 @@ public final class SapseepForest extends CardImpl { filter.add(new ColorPredicate(ObjectColor.GREEN)); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1); + public SapseepForest(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.LAND},""); + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); this.subtype.add(SubType.FOREST); // ({tap}: Add {G}.) @@ -43,13 +44,9 @@ public final class SapseepForest extends CardImpl { this.addAbility(new EntersBattlefieldTappedAbility()); // {G}, {tap}: You gain 1 life. Activate this ability only if you control two or more green permanents. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, - new GainLifeEffect(1), - new ManaCostsImpl<>("{G}"), - new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1)); + Ability ability = new ActivateIfConditionActivatedAbility(new GainLifeEffect(1), new ManaCostsImpl<>("{G}"), condition); ability.addCost(new TapSourceCost()); this.addAbility(ability); - } private SapseepForest(final SapseepForest card) { diff --git a/Mage.Sets/src/mage/cards/s/Sarcomancy.java b/Mage.Sets/src/mage/cards/s/Sarcomancy.java index e9d4b223a3e..5e5125e4d15 100644 --- a/Mage.Sets/src/mage/cards/s/Sarcomancy.java +++ b/Mage.Sets/src/mage/cards/s/Sarcomancy.java @@ -1,36 +1,39 @@ - package mage.cards.s; -import java.util.UUID; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.DamageControllerEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.FilterPermanent; import mage.game.permanent.token.ZombieToken; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class Sarcomancy extends CardImpl { - - public Sarcomancy(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{B}"); + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterPermanent(SubType.ZOMBIE, "there are no Zombies on the battlefield"), + ComparisonType.EQUAL_TO, 0, false + ); + + public Sarcomancy(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{B}"); // When Sarcomancy enters the battlefield, create a 2/2 black Zombie creature token. - this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ZombieToken(), 1), false)); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ZombieToken()))); + // At the beginning of your upkeep, if there are no Zombies on the battlefield, Sarcomancy deals 1 damage to you. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new DamageControllerEffect(1)), - new PermanentsOnTheBattlefieldCondition(new FilterPermanent(SubType.ZOMBIE, "Zombies"), ComparisonType.EQUAL_TO, 0, false), - "At the beginning of your upkeep, if there are no Zombies on the battlefield, {this} deals 1 damage to you.")); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DamageControllerEffect(1)).withInterveningIf(condition)); } private Sarcomancy(final Sarcomancy card) { diff --git a/Mage.Sets/src/mage/cards/s/SarevoksTome.java b/Mage.Sets/src/mage/cards/s/SarevoksTome.java index 75389d857b2..efde6300ace 100644 --- a/Mage.Sets/src/mage/cards/s/SarevoksTome.java +++ b/Mage.Sets/src/mage/cards/s/SarevoksTome.java @@ -40,7 +40,6 @@ public final class SarevoksTome extends CardImpl { // {T}: Add {C}. If you have the initiative, add {C}{C} instead. this.addAbility(new SimpleManaAbility( - Zone.BATTLEFIELD, new ConditionalManaEffect( new BasicManaEffect(Mana.ColorlessMana(2)), new BasicManaEffect(Mana.ColorlessMana(1)), @@ -51,8 +50,7 @@ public final class SarevoksTome extends CardImpl { // {3}, {T}: Exile cards from the top of your library until you exile a nonland card. You may cast that card without paying its mana cost. Activate only if you've completed a dungeon. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new SarevoksTomeEffect(), - new GenericManaCost(3), CompletedDungeonCondition.instance + new SarevoksTomeEffect(), new GenericManaCost(3), CompletedDungeonCondition.instance ); ability.addCost(new TapSourceCost()); this.addAbility(ability.addHint(CompletedDungeonCondition.getHint()), new CompletedDungeonWatcher()); diff --git a/Mage.Sets/src/mage/cards/s/SarulfRealmEater.java b/Mage.Sets/src/mage/cards/s/SarulfRealmEater.java index 739780fb50b..e54c2d68929 100644 --- a/Mage.Sets/src/mage/cards/s/SarulfRealmEater.java +++ b/Mage.Sets/src/mage/cards/s/SarulfRealmEater.java @@ -1,30 +1,28 @@ package mage.cards.s; import mage.MageInt; -import mage.MageItem; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.PutIntoGraveFromBattlefieldAllTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.SourceHasCounterCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; import mage.constants.*; import mage.counters.CounterType; import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.filter.common.FilterNonlandPermanent; -import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import java.util.Objects; +import java.util.HashSet; +import java.util.List; import java.util.UUID; /** @@ -32,12 +30,6 @@ import java.util.UUID; */ public final class SarulfRealmEater extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("a permanent an opponent controls"); - - static { - filter.add(TargetController.OPPONENT.getControllerPredicate()); - } - private static final Condition condition = new SourceHasCounterCondition(CounterType.P1P1); public SarulfRealmEater(UUID ownerId, CardSetInfo setInfo) { @@ -50,18 +42,12 @@ public final class SarulfRealmEater extends CardImpl { // Whenever a permanent an opponent controls is put into a graveyard from the battlefield, put a +1/+1 counter on Sarulf, Realm Eater. this.addAbility(new PutIntoGraveFromBattlefieldAllTriggeredAbility( - new AddCountersSourceEffect(CounterType.P1P1.createInstance()), - false, filter, false, false + new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false, + StaticFilters.FILTER_OPPONENTS_PERMANENT, false, false )); // At the beginning of your upkeep, if Sarulf has one or more +1/+1 counters on it, you may remove all of them. If you do, exile each other nonland permanent with converted mana cost less than or equal to the number of counters removed this way. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility( - new SarulfRealmEaterEffect(), true - ), condition, "At the beginning of your upkeep, if {this} has one or more +1/+1 counters on it, " + - "you may remove all of them. If you do, exile each other nonland permanent with mana value " + - "less than or equal to the number of counters removed this way." - )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SarulfRealmEaterEffect(), true).withInterveningIf(condition)); } private SarulfRealmEater(final SarulfRealmEater card) { @@ -78,6 +64,8 @@ class SarulfRealmEaterEffect extends OneShotEffect { SarulfRealmEaterEffect() { super(Outcome.Benefit); + staticText = "remove all of them. If you do, exile each other nonland permanent with mana value " + + "less than or equal to the number of counters removed this way"; } private SarulfRealmEaterEffect(final SarulfRealmEaterEffect effect) { @@ -100,16 +88,10 @@ class SarulfRealmEaterEffect extends OneShotEffect { FilterPermanent filter = new FilterNonlandPermanent(); filter.add(new ManaValuePredicate(ComparisonType.OR_LESS, removedThisWay)); filter.add(AnotherPredicate.instance); - Cards cards = new CardsImpl(); - game.getBattlefield() - .getActivePermanents( - filter, source.getControllerId(), - source, game - ) - .stream() - .filter(Objects::nonNull) - .map(MageItem::getId) - .forEach(cards::add); - return player.moveCards(cards, Zone.EXILED, source, game); + List permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game); + if (!permanents.isEmpty()) { + player.moveCards(new HashSet<>(permanents), Zone.EXILED, source, game); + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/s/SaruliGatekeepers.java b/Mage.Sets/src/mage/cards/s/SaruliGatekeepers.java index eb63c640225..d48f592f4a1 100644 --- a/Mage.Sets/src/mage/cards/s/SaruliGatekeepers.java +++ b/Mage.Sets/src/mage/cards/s/SaruliGatekeepers.java @@ -2,35 +2,21 @@ package mage.cards.s; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.condition.Condition; -import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.YouControlTwoOrMoreGatesCondition; import mage.abilities.effects.common.GainLifeEffect; -import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.common.GatesYouControlHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.ComparisonType; import mage.constants.SubType; -import mage.filter.common.FilterControlledPermanent; import java.util.UUID; /** * @author LevelX2 */ - - public final class SaruliGatekeepers extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent(); - - static { - filter.add(SubType.GATE.getPredicate()); - } - - private static final Condition gatesCondition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1); - public SaruliGatekeepers(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); this.subtype.add(SubType.ELF); @@ -40,11 +26,8 @@ public final class SaruliGatekeepers extends CardImpl { this.toughness = new MageInt(4); // When Saruli Gatekeepers enters the battlefield, if you control two or more Gates, gain 7 life. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new GainLifeEffect(7)), - gatesCondition, - "When {this} enters, if you control two or more Gates, you gain 7 life.") - .addHint(new ConditionHint(gatesCondition, "You control two or more Gates"))); + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(7)) + .withInterveningIf(YouControlTwoOrMoreGatesCondition.instance).addHint(GatesYouControlHint.instance)); } private SaruliGatekeepers(final SaruliGatekeepers card) { diff --git a/Mage.Sets/src/mage/cards/s/SatyaAetherfluxGenius.java b/Mage.Sets/src/mage/cards/s/SatyaAetherfluxGenius.java index f0e2d33d364..cf7c2f0b135 100644 --- a/Mage.Sets/src/mage/cards/s/SatyaAetherfluxGenius.java +++ b/Mage.Sets/src/mage/cards/s/SatyaAetherfluxGenius.java @@ -23,7 +23,7 @@ import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.permanent.TokenPredicate; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.targetpointer.FixedTargets; import java.util.List; @@ -61,7 +61,7 @@ public final class SatyaAetherfluxGenius extends CardImpl { // Whenever Satya, Aetherflux Genius attacks, create a tapped and attacking token that's a copy of up to one other target nontoken creature you control. You get {E}{E}. At the beginning of the next end step, sacrifice that token unless you pay an amount of {E} equal to its mana value. Ability ability = new AttacksTriggeredAbility(new SatyaAetherfluxGeniusEffect()); - ability.addTarget(new TargetControlledCreaturePermanent(0, 1, filter, false)); + ability.addTarget(new TargetPermanent(0, 1, filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SatyrFiredancer.java b/Mage.Sets/src/mage/cards/s/SatyrFiredancer.java index 95ad9e5b92d..894acc8f25e 100644 --- a/Mage.Sets/src/mage/cards/s/SatyrFiredancer.java +++ b/Mage.Sets/src/mage/cards/s/SatyrFiredancer.java @@ -19,6 +19,7 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetadjustment.TargetAdjuster; import mage.target.targetpointer.FixedTarget; @@ -136,7 +137,7 @@ enum SatyrFiredancerAdjuster implements TargetAdjuster { if (opponent != null) { FilterCreaturePermanent filter = new FilterCreaturePermanent("creature controlled by " + opponent.getLogName()); filter.add(new ControllerIdPredicate(opponent.getId())); - ability.getTargets().add(new TargetCreaturePermanent(filter)); + ability.getTargets().add(new TargetPermanent(filter)); } } } diff --git a/Mage.Sets/src/mage/cards/s/SavageAlliance.java b/Mage.Sets/src/mage/cards/s/SavageAlliance.java index e63f2b86dd5..5f262f47e58 100644 --- a/Mage.Sets/src/mage/cards/s/SavageAlliance.java +++ b/Mage.Sets/src/mage/cards/s/SavageAlliance.java @@ -22,6 +22,7 @@ import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.TargetPlayer; import mage.target.common.TargetCreaturePermanent; @@ -59,7 +60,7 @@ public final class SavageAlliance extends CardImpl { Effect effect = new DamageTargetEffect(2); effect.setText("{this} deals 2 damage to target creature"); Mode mode = new Mode(effect); - mode.addTarget(new TargetCreaturePermanent(filterCreature).withChooseHint("deals 2 damage to")); + mode.addTarget(new TargetPermanent(filterCreature).withChooseHint("deals 2 damage to")); this.getSpellAbility().addMode(mode); // Savage Alliance deals 1 damage to each creature target opponent controls. diff --git a/Mage.Sets/src/mage/cards/s/SavageGorger.java b/Mage.Sets/src/mage/cards/s/SavageGorger.java index 39ddc7c630f..8dd50f9c39c 100644 --- a/Mage.Sets/src/mage/cards/s/SavageGorger.java +++ b/Mage.Sets/src/mage/cards/s/SavageGorger.java @@ -1,12 +1,11 @@ package mage.cards.s; import mage.MageInt; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.common.OpponentsLostLifeCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.hint.common.OpponentsLostLifeHint; import mage.abilities.keyword.FlyingAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -31,12 +30,8 @@ public final class SavageGorger extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // At the beginning of your upkeep, if an opponent lost life this turn, put a +1/+1 counter on Savage Gorger. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility(new AddCountersSourceEffect( - CounterType.P1P1.createInstance()) - ), OpponentsLostLifeCondition.instance, "At the beginning of your end step, " + - "if an opponent lost life this turn, put a +1/+1 counter on {this}." - ).addHint(OpponentsLostLifeHint.instance)); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance())) + .withInterveningIf(OpponentsLostLifeCondition.instance).addHint(OpponentsLostLifeHint.instance)); } private SavageGorger(final SavageGorger card) { diff --git a/Mage.Sets/src/mage/cards/s/SavagePunch.java b/Mage.Sets/src/mage/cards/s/SavagePunch.java index d20283338f1..c9105cbb8a8 100644 --- a/Mage.Sets/src/mage/cards/s/SavagePunch.java +++ b/Mage.Sets/src/mage/cards/s/SavagePunch.java @@ -13,11 +13,14 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.filter.StaticFilters; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author LevelX2 */ @@ -39,7 +42,7 @@ public final class SavagePunch extends CardImpl { effect.setText("
Target creature you control fights target creature you don't control"); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - Target target = new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL); + Target target = new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL); this.getSpellAbility().addTarget(target); } diff --git a/Mage.Sets/src/mage/cards/s/SavageSmash.java b/Mage.Sets/src/mage/cards/s/SavageSmash.java index 80892289ee5..0ceb8408337 100644 --- a/Mage.Sets/src/mage/cards/s/SavageSmash.java +++ b/Mage.Sets/src/mage/cards/s/SavageSmash.java @@ -7,11 +7,14 @@ 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 mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author TheElk801 */ @@ -27,7 +30,7 @@ public final class SavageSmash extends CardImpl { " (Each deals damage equal to its power to the other.)") ); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); } private SavageSmash(final SavageSmash card) { diff --git a/Mage.Sets/src/mage/cards/s/SavageStomp.java b/Mage.Sets/src/mage/cards/s/SavageStomp.java index a054c9082f0..b1c8fed2f58 100644 --- a/Mage.Sets/src/mage/cards/s/SavageStomp.java +++ b/Mage.Sets/src/mage/cards/s/SavageStomp.java @@ -16,11 +16,14 @@ import mage.counters.CounterType; import mage.filter.FilterPermanent; import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author TheElk801 */ @@ -47,7 +50,7 @@ public final class SavageStomp extends CardImpl { "(Each deals damage equal to its power to the other.)"); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); } private SavageStomp(final SavageStomp card) { diff --git a/Mage.Sets/src/mage/cards/s/SavingGrasp.java b/Mage.Sets/src/mage/cards/s/SavingGrasp.java index 0c6ff824a9a..dffd345b392 100644 --- a/Mage.Sets/src/mage/cards/s/SavingGrasp.java +++ b/Mage.Sets/src/mage/cards/s/SavingGrasp.java @@ -8,6 +8,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -27,7 +28,7 @@ public final class SavingGrasp extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}"); // Return target creature you own to your hand. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new ReturnToHandTargetEffect().setText("return target creature you own to your hand")); // Flashback {W} this.addAbility(new FlashbackAbility(this, new ManaCostsImpl<>("{W}"))); diff --git a/Mage.Sets/src/mage/cards/s/ScabClanBerserker.java b/Mage.Sets/src/mage/cards/s/ScabClanBerserker.java index 52d19755c10..408833a25e4 100644 --- a/Mage.Sets/src/mage/cards/s/ScabClanBerserker.java +++ b/Mage.Sets/src/mage/cards/s/ScabClanBerserker.java @@ -1,33 +1,28 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.condition.common.RenownedSourceCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.RenownAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SetTargetPointer; import mage.constants.SubType; import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.stack.Spell; -import mage.target.targetpointer.FixedTarget; +import mage.filter.StaticFilters; + +import java.util.UUID; /** - * * @author fireshoes */ public final class ScabClanBerserker extends CardImpl { public ScabClanBerserker(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.HUMAN); this.subtype.add(SubType.BERSERKER); this.power = new MageInt(2); @@ -35,15 +30,16 @@ public final class ScabClanBerserker extends CardImpl { // Haste this.addAbility(HasteAbility.getInstance()); - + // Renown 1 this.addAbility(new RenownAbility(1)); - + // Whenever an opponent casts a noncreature spell, if Scab-Clan Berserker is renowned, Scab-Clan Berserker deals 2 damage to that player. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new ScabClanBerserkerTriggeredAbility(), - RenownedSourceCondition.instance, - "Whenever an opponent casts a noncreature spell, if Scab-Clan Berserker is renowned, Scab-Clan Berserker deals 2 damage to that player")); + this.addAbility(new SpellCastOpponentTriggeredAbility( + Zone.BATTLEFIELD, + new DamageTargetEffect(2, true, "that player"), + StaticFilters.FILTER_SPELL_A_NON_CREATURE, false, SetTargetPointer.PLAYER + ).withInterveningIf(RenownedSourceCondition.THIS)); } private ScabClanBerserker(final ScabClanBerserker card) { @@ -55,45 +51,3 @@ public final class ScabClanBerserker extends CardImpl { return new ScabClanBerserker(this); } } - -class ScabClanBerserkerTriggeredAbility extends TriggeredAbilityImpl { - - - public ScabClanBerserkerTriggeredAbility() { - super(Zone.BATTLEFIELD, new DamageTargetEffect(2, true, "that player")); - } - - - private ScabClanBerserkerTriggeredAbility(final ScabClanBerserkerTriggeredAbility abiltity) { - super(abiltity); - } - - @Override - public ScabClanBerserkerTriggeredAbility copy() { - return new ScabClanBerserkerTriggeredAbility(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 (game.getOpponents(controllerId).contains(event.getPlayerId())) { - Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell != null && !spell.isCreature(game)){ - for (Effect effect : this.getEffects()) { - effect.setTargetPointer(new FixedTarget(event.getPlayerId())); - } - return true; - } - } - return false; - } - - @Override - public String getRule() { - return "Whenever an opponent casts a noncreature spell, if Scab-Clan Berserker is renowned, Scab-Clan Berserker deals 2 damage to that player"; - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/ScabClanGiant.java b/Mage.Sets/src/mage/cards/s/ScabClanGiant.java index 7c85ea2260e..4781aa08854 100644 --- a/Mage.Sets/src/mage/cards/s/ScabClanGiant.java +++ b/Mage.Sets/src/mage/cards/s/ScabClanGiant.java @@ -11,10 +11,13 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * @author LevelX2 */ @@ -31,7 +34,7 @@ public final class ScabClanGiant extends CardImpl { // When Scab-Clan Giant enters the battlefield, it fights target creature an opponent controls chosen at random. Ability ability = new EntersBattlefieldTriggeredAbility(new FightTargetSourceEffect() .setText("it fights target creature an opponent controls chosen at random")); - Target target = new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE); + Target target = new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE); target.setRandom(true); ability.addTarget(target); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/s/ScaldingTongs.java b/Mage.Sets/src/mage/cards/s/ScaldingTongs.java index 9327ff8b01e..3e5edbf3a57 100644 --- a/Mage.Sets/src/mage/cards/s/ScaldingTongs.java +++ b/Mage.Sets/src/mage/cards/s/ScaldingTongs.java @@ -1,35 +1,32 @@ - package mage.cards.s; -import java.util.UUID; -import mage.abilities.TriggeredAbility; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.Ability; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInHandCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; import mage.target.common.TargetOpponentOrPlaneswalker; +import java.util.UUID; + /** * @author fireshoes */ public final class ScaldingTongs extends CardImpl { + private static final Condition condition = new CardsInHandCondition(ComparisonType.FEWER_THAN, 4); + public ScaldingTongs(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); // At the beginning of your upkeep, if you have three or fewer cards in hand, Scalding Tongs deals 1 damage to target opponent. - TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new DamageTargetEffect(1)); + Ability ability = new BeginningOfUpkeepTriggeredAbility(new DamageTargetEffect(1)).withInterveningIf(condition); ability.addTarget(new TargetOpponentOrPlaneswalker()); - CardsInHandCondition condition = new CardsInHandCondition(ComparisonType.FEWER_THAN, 4); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - ability, condition, - "At the beginning of your upkeep, if you have three or fewer cards in hand, " - + "{this} deals 1 damage to target opponent or planeswalker." - )); + this.addAbility(ability); } private ScaldingTongs(final ScaldingTongs card) { diff --git a/Mage.Sets/src/mage/cards/s/ScalelordReckoner.java b/Mage.Sets/src/mage/cards/s/ScalelordReckoner.java index 3ff98c16e20..feba0f44bb2 100644 --- a/Mage.Sets/src/mage/cards/s/ScalelordReckoner.java +++ b/Mage.Sets/src/mage/cards/s/ScalelordReckoner.java @@ -1,6 +1,7 @@ package mage.cards.s; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.BecomesTargetAnyTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.FlyingAbility; @@ -9,22 +10,23 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SetTargetPointer; import mage.constants.SubType; +import mage.filter.FilterPermanent; import mage.filter.StaticFilters; import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterNonlandPermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.game.events.GameEvent; import mage.target.TargetPermanent; +import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster; import java.util.UUID; /** - * * @author spjspj */ public final class ScalelordReckoner extends CardImpl { + private static final FilterPermanent filterDragon = new FilterControlledPermanent(SubType.DRAGON, "a Dragon you control"); + private static final FilterPermanent filterTarget = new FilterNonlandPermanent("nonland permanent that player controls"); + public ScalelordReckoner(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); @@ -36,7 +38,10 @@ public final class ScalelordReckoner extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Whenever a Dragon you control becomes the target of a spell or ability an opponent controls, destroy target nonland permanent that player controls. - this.addAbility(new ScalelordReckonerTriggeredAbility()); + Ability ability = new BecomesTargetAnyTriggeredAbility(new DestroyTargetEffect(), filterDragon, StaticFilters.FILTER_SPELL_OR_ABILITY_OPPONENTS, SetTargetPointer.PLAYER, false); + ability.addTarget(new TargetPermanent(filterTarget)); + ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster()); + this.addAbility(ability); } private ScalelordReckoner(final ScalelordReckoner card) { @@ -48,39 +53,3 @@ public final class ScalelordReckoner extends CardImpl { return new ScalelordReckoner(this); } } - -class ScalelordReckonerTriggeredAbility extends BecomesTargetAnyTriggeredAbility { - - private static final FilterControlledPermanent filter = new FilterControlledPermanent("a Dragon you control"); - - static { - filter.add(SubType.DRAGON.getPredicate()); - } - - ScalelordReckonerTriggeredAbility() { - super(new DestroyTargetEffect().setText("destroy target nonland permanent that player controls"), - filter, StaticFilters.FILTER_SPELL_OR_ABILITY_OPPONENTS, SetTargetPointer.NONE, false); - } - - private ScalelordReckonerTriggeredAbility(final ScalelordReckonerTriggeredAbility ability) { - super(ability); - } - - @Override - public ScalelordReckonerTriggeredAbility copy() { - return new ScalelordReckonerTriggeredAbility(this); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (!super.checkTrigger(event, game)) { - return false; - } - FilterNonlandPermanent targetFilter = new FilterNonlandPermanent("nonland permanent that player controls"); - targetFilter.add(new ControllerIdPredicate(event.getPlayerId())); - this.getTargets().clear(); - this.addTarget(new TargetPermanent(targetFilter)); - return true; - } - -} diff --git a/Mage.Sets/src/mage/cards/s/Scapegoat.java b/Mage.Sets/src/mage/cards/s/Scapegoat.java index dc129403607..1cb7a414ed5 100644 --- a/Mage.Sets/src/mage/cards/s/Scapegoat.java +++ b/Mage.Sets/src/mage/cards/s/Scapegoat.java @@ -1,19 +1,16 @@ - package mage.cards.s; -import java.util.UUID; import mage.abilities.costs.common.SacrificeTargetCost; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; -import mage.filter.common.FilterControlledCreaturePermanent; import mage.target.common.TargetControlledCreaturePermanent; +import java.util.UUID; + /** - * * @author emerald000 */ public final class Scapegoat extends CardImpl { @@ -25,10 +22,8 @@ public final class Scapegoat extends CardImpl { this.getSpellAbility().addCost(new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_CREATURE)); // Return any number of target creatures you control to their owner's hand. - Effect effect = new ReturnToHandTargetEffect(); - effect.setText("Return any number of target creatures you control to their owner's hand"); - this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, new FilterControlledCreaturePermanent(), false)); + this.getSpellAbility().addEffect(new ReturnToHandTargetEffect().setText("Return any number of target creatures you control to their owner's hand")); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE)); } private Scapegoat(final Scapegoat card) { diff --git a/Mage.Sets/src/mage/cards/s/ScepterOfFugue.java b/Mage.Sets/src/mage/cards/s/ScepterOfFugue.java index d5505d4b008..a5ca068724f 100644 --- a/Mage.Sets/src/mage/cards/s/ScepterOfFugue.java +++ b/Mage.Sets/src/mage/cards/s/ScepterOfFugue.java @@ -6,11 +6,9 @@ import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.discard.DiscardTargetEffect; -import mage.abilities.hint.common.MyTurnHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; import mage.target.TargetPlayer; import java.util.UUID; @@ -23,12 +21,12 @@ public final class ScepterOfFugue extends CardImpl { public ScepterOfFugue(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{B}{B}"); - // {1}{B}, {T}: Target player discards a card. Activate this ability only during your turn. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new DiscardTargetEffect(1), new ManaCostsImpl<>("{1}{B}"), MyTurnCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new DiscardTargetEffect(1), new ManaCostsImpl<>("{1}{B}"), MyTurnCondition.instance + ); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetPlayer()); - ability.addHint(MyTurnHint.instance); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/Schismotivate.java b/Mage.Sets/src/mage/cards/s/Schismotivate.java index da6a4158968..f5236523498 100644 --- a/Mage.Sets/src/mage/cards/s/Schismotivate.java +++ b/Mage.Sets/src/mage/cards/s/Schismotivate.java @@ -1,44 +1,31 @@ - package mage.cards.s; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.effects.ContinuousEffectImpl; +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.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.other.AnotherTargetPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.SecondTargetPointer; + +import java.util.UUID; /** - * * @author fireshoes */ public final class Schismotivate extends CardImpl { public Schismotivate(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}{R}"); // Target creature gets +4/+0 until end of turn. Another target creature gets -4/-0 until end of turn. - this.getSpellAbility().addEffect(new SchismotivateEffect()); - - FilterCreaturePermanent filter1 = new FilterCreaturePermanent("creature (gets +4/+0 until end of turn)"); - TargetCreaturePermanent target1 = new TargetCreaturePermanent(filter1); - target1.setTargetTag(1); - this.getSpellAbility().addTarget(target1); - - FilterCreaturePermanent filter2 = new FilterCreaturePermanent("another creature (gets -4/-0 until end of turn)"); - filter2.add(new AnotherTargetPredicate(2)); - TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter2); - target2.setTargetTag(2); - this.getSpellAbility().addTarget(target2); + this.getSpellAbility().addEffect(new BoostTargetEffect(4, 0)); + this.getSpellAbility().addEffect(new BoostTargetEffect(-4, 0) + .setTargetPointer(new SecondTargetPointer()) + .setText("Another target creature gets -4/-0 until end of turn")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent().withChooseHint("+4/+0").setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2).withChooseHint("-4/-0").setTargetTag(2)); } private Schismotivate(final Schismotivate card) { @@ -50,33 +37,3 @@ public final class Schismotivate extends CardImpl { return new Schismotivate(this); } } - -class SchismotivateEffect extends ContinuousEffectImpl { - - SchismotivateEffect() { - super(Duration.EndOfTurn, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature); - this.staticText = "Target creature gets +4/+0 until end of turn. Another target creature gets -4/-0 until end of turn"; - } - - private SchismotivateEffect(final SchismotivateEffect effect) { - super(effect); - } - - @Override - public SchismotivateEffect copy() { - return new SchismotivateEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getFirstTarget()); - if (permanent != null) { - permanent.addPower(4); - } - permanent = game.getPermanent(source.getTargets().get(1).getFirstTarget()); - if (permanent != null) { - permanent.addPower(-4); - } - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/s/ScholarOfStars.java b/Mage.Sets/src/mage/cards/s/ScholarOfStars.java index 7b1a533be61..db4d8dea6e2 100644 --- a/Mage.Sets/src/mage/cards/s/ScholarOfStars.java +++ b/Mage.Sets/src/mage/cards/s/ScholarOfStars.java @@ -1,24 +1,26 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; -import mage.constants.SubType; +import mage.abilities.hint.common.ArtifactYouControlHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.StaticFilters; +import mage.constants.SubType; +import mage.filter.common.FilterControlledArtifactPermanent; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class ScholarOfStars extends CardImpl { + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(new FilterControlledArtifactPermanent("you control an artifact")); + public ScholarOfStars(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); @@ -28,11 +30,8 @@ public final class ScholarOfStars extends CardImpl { this.toughness = new MageInt(2); // When Scholar of Stars enters the battlefield, if you control an artifact, draw a card. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1), false), - new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT), - "When {this} enters, if you control an artifact, draw a card." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)) + .withInterveningIf(condition).addHint(ArtifactYouControlHint.instance)); } private ScholarOfStars(final ScholarOfStars card) { diff --git a/Mage.Sets/src/mage/cards/s/ScionOfVituGhazi.java b/Mage.Sets/src/mage/cards/s/ScionOfVituGhazi.java index 264c1a9efec..b0d117b8a67 100644 --- a/Mage.Sets/src/mage/cards/s/ScionOfVituGhazi.java +++ b/Mage.Sets/src/mage/cards/s/ScionOfVituGhazi.java @@ -1,12 +1,9 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromHandSourcePermanentCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.PopulateEffect; import mage.cards.CardImpl; @@ -16,25 +13,25 @@ import mage.constants.SubType; import mage.game.permanent.token.BirdToken; import mage.watchers.common.CastFromHandWatcher; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class ScionOfVituGhazi extends CardImpl { public ScionOfVituGhazi(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); this.subtype.add(SubType.ELEMENTAL); this.power = new MageInt(4); this.toughness = new MageInt(4); //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 ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new BirdToken())) + .withInterveningIf(CastFromHandSourcePermanentCondition.instance); ability.addEffect(new PopulateEffect("then")); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, CastFromHandSourcePermanentCondition.instance, - "When {this} enters, if you cast it from your hand, create a 1/1 white Bird creature token with flying, then populate."), - new CastFromHandWatcher()); + this.addAbility(ability, new CastFromHandWatcher()); } private ScionOfVituGhazi(final ScionOfVituGhazi card) { diff --git a/Mage.Sets/src/mage/cards/s/ScorchRider.java b/Mage.Sets/src/mage/cards/s/ScorchRider.java index 06e8e6f2abd..466645927df 100644 --- a/Mage.Sets/src/mage/cards/s/ScorchRider.java +++ b/Mage.Sets/src/mage/cards/s/ScorchRider.java @@ -3,7 +3,6 @@ package mage.cards.s; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.KickerAbility; @@ -32,12 +31,9 @@ public final class ScorchRider extends CardImpl { this.addAbility(new KickerAbility("{1}{R}")); // When Scorch Rider enters the battlefield, if it was kicked, it gains haste until end of turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new GainAbilitySourceEffect( - HasteAbility.getInstance(), Duration.EndOfTurn - )), KickedCondition.ONCE, "When {this} enters, " + - "if it was kicked, it gains haste until end of turn." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainAbilitySourceEffect( + HasteAbility.getInstance(), Duration.EndOfTurn + ).setText("it gains haste until end of turn")).withInterveningIf(KickedCondition.ONCE)); } private ScorchRider(final ScorchRider card) { diff --git a/Mage.Sets/src/mage/cards/s/ScorchingLava.java b/Mage.Sets/src/mage/cards/s/ScorchingLava.java index 3f732919af5..dd3143ad363 100644 --- a/Mage.Sets/src/mage/cards/s/ScorchingLava.java +++ b/Mage.Sets/src/mage/cards/s/ScorchingLava.java @@ -1,27 +1,21 @@ package mage.cards.s; -import java.util.UUID; -import mage.MageObjectReference; -import mage.abilities.Ability; import mage.abilities.condition.LockedInCondition; import mage.abilities.condition.common.KickedCondition; import mage.abilities.decorator.ConditionalContinuousRuleModifyingEffect; import mage.abilities.decorator.ConditionalOneShotEffect; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.ExileTargetIfDiesEffect; -import mage.abilities.effects.common.replacement.DiesReplacementEffect; import mage.abilities.effects.common.ruleModifying.CantRegenerateTargetEffect; import mage.abilities.keyword.KickerAbility; 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.common.TargetAnyTarget; +import java.util.UUID; + /** * * @author LoneFox @@ -37,8 +31,7 @@ public final class ScorchingLava extends CardImpl { // 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, "If Scorching Lava was kicked, " - + "\n" + "that creature "), + new CantRegenerateTargetEffect(Duration.EndOfTurn, "If {this} was kicked, that creature"), new LockedInCondition(KickedCondition.ONCE))); this.getSpellAbility().addEffect(new ConditionalOneShotEffect( new ExileTargetIfDiesEffect(), @@ -56,28 +49,3 @@ public final class ScorchingLava extends CardImpl { return new ScorchingLava(this); } } - -class ScorchingLavaEffect extends OneShotEffect { - - ScorchingLavaEffect() { - super(Outcome.Exile); - } - - private ScorchingLavaEffect(final ScorchingLavaEffect effect) { - super(effect); - } - - @Override - public ScorchingLavaEffect copy() { - return new ScorchingLavaEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent targetCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (targetCreature != null) { - game.addEffect(new DiesReplacementEffect(new MageObjectReference(targetCreature, game), Duration.EndOfTurn), source); - } - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/s/ScourgeOfTheSkyclaves.java b/Mage.Sets/src/mage/cards/s/ScourgeOfTheSkyclaves.java index f2af217e91f..79851881a51 100644 --- a/Mage.Sets/src/mage/cards/s/ScourgeOfTheSkyclaves.java +++ b/Mage.Sets/src/mage/cards/s/ScourgeOfTheSkyclaves.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; @@ -13,7 +12,10 @@ import mage.abilities.effects.common.continuous.SetBasePowerToughnessSourceEffec import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; import mage.game.Game; import mage.players.Player; @@ -36,10 +38,7 @@ public final class ScourgeOfTheSkyclaves extends CardImpl { this.addAbility(new KickerAbility("{4}{B}")); // When you cast this spell, if it was kicked, each player loses half their life, rounded up. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new CastSourceTriggeredAbility(new ScourgeOfTheSkyclavesEffect()), KickedCondition.ONCE, - "When you cast this spell, if it was kicked, each player loses half their life, rounded up." - )); + this.addAbility(new CastSourceTriggeredAbility(new ScourgeOfTheSkyclavesEffect()).withInterveningIf(KickedCondition.ONCE)); // Scourge of the Skyclaves's power and toughness are each equal to 20 minus the highest life total among players. this.addAbility(new SimpleStaticAbility( @@ -89,6 +88,7 @@ class ScourgeOfTheSkyclavesEffect extends OneShotEffect { ScourgeOfTheSkyclavesEffect() { super(Outcome.Benefit); + staticText = "each player loses half their life, rounded up"; } private ScourgeOfTheSkyclavesEffect(final ScourgeOfTheSkyclavesEffect effect) { diff --git a/Mage.Sets/src/mage/cards/s/ScourgeOfTheThrone.java b/Mage.Sets/src/mage/cards/s/ScourgeOfTheThrone.java index 6cec7f8d873..856ef512c5b 100644 --- a/Mage.Sets/src/mage/cards/s/ScourgeOfTheThrone.java +++ b/Mage.Sets/src/mage/cards/s/ScourgeOfTheThrone.java @@ -1,11 +1,9 @@ - package mage.cards.s; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.AttacksFirstTimeTriggeredAbility; import mage.abilities.condition.common.SourceAttackingPlayerWithMostLifeCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.AdditionalCombatPhaseEffect; import mage.abilities.effects.common.UntapAllControllerEffect; import mage.abilities.keyword.DethroneAbility; @@ -32,24 +30,19 @@ public final class ScourgeOfTheThrone extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); + // Dethrone (Whenever this creature attacks the player with the most life or tied for most life, put a +1/+1 counter on it.) this.addAbility(new DethroneAbility()); + // Whenever Scourge of the Throne attacks for the first time each turn, if it's attacking the player with the most life or tied for most life, untap all attacking creatures. After this phase, there is an additional combat phase. - TriggeredAbility ability = new AttacksFirstTimeTriggeredAbility( + Ability ability = new AttacksFirstTimeTriggeredAbility( new UntapAllControllerEffect( StaticFilters.FILTER_ATTACKING_CREATURES, "untap all attacking creatures" ), false - ); + ).withInterveningIf(SourceAttackingPlayerWithMostLifeCondition.instance); ability.addEffect(new AdditionalCombatPhaseEffect()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - ability, - SourceAttackingPlayerWithMostLifeCondition.instance, - "Whenever {this} attacks for the first time each turn, " - + "if it's attacking the player with the most life or tied for most life, " - + "untap all attacking creatures. After this phase, " - + "there is an additional combat phase." - )); + this.addAbility(ability); } private ScourgeOfTheThrone(final ScourgeOfTheThrone card) { @@ -60,4 +53,4 @@ public final class ScourgeOfTheThrone extends CardImpl { public ScourgeOfTheThrone copy() { return new ScourgeOfTheThrone(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/s/Scourglass.java b/Mage.Sets/src/mage/cards/s/Scourglass.java index e107d607581..1622b023215 100644 --- a/Mage.Sets/src/mage/cards/s/Scourglass.java +++ b/Mage.Sets/src/mage/cards/s/Scourglass.java @@ -1,23 +1,20 @@ - package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DestroyAllEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.PhaseStep; -import mage.constants.Zone; import mage.filter.FilterPermanent; import mage.filter.predicate.Predicates; +import java.util.UUID; + /** - * * @author Plopman */ public final class Scourglass extends CardImpl { @@ -25,15 +22,17 @@ public final class Scourglass extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("permanents except for artifacts and lands"); static { - filter.add(Predicates.not(Predicates.or(CardType.ARTIFACT.getPredicate(), CardType.LAND.getPredicate()))); + filter.add(Predicates.not(CardType.ARTIFACT.getPredicate())); + filter.add(Predicates.not(CardType.LAND.getPredicate())); } public Scourglass(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}{W}{W}"); // {T}, Sacrifice Scourglass: Destroy all permanents except for artifacts and lands. Activate this ability only during your upkeep. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, - new DestroyAllEffect(filter), new TapSourceCost(), new IsStepCondition(PhaseStep.UPKEEP)); + Ability ability = new ActivateIfConditionActivatedAbility( + new DestroyAllEffect(filter), new TapSourceCost(), IsStepCondition.getMyUpkeep() + ); ability.addCost(new SacrificeSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/ScoutingHawk.java b/Mage.Sets/src/mage/cards/s/ScoutingHawk.java index a718a1aca2d..e77d45c12f3 100644 --- a/Mage.Sets/src/mage/cards/s/ScoutingHawk.java +++ b/Mage.Sets/src/mage/cards/s/ScoutingHawk.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.OpponentControlsMoreCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -30,7 +29,7 @@ public final class ScoutingHawk extends CardImpl { filter.add(SubType.PLAINS.getPredicate()); } - private static final Condition condition = new OpponentControlsMoreCondition(StaticFilters.FILTER_LAND); + private static final Condition condition = new OpponentControlsMoreCondition(StaticFilters.FILTER_LANDS); public ScoutingHawk(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); @@ -43,11 +42,9 @@ public final class ScoutingHawk extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Keen Sight — When Scouting Hawk enters the battlefield, if an opponent controls more lands than you, search your library for a basic Plains card, put it onto the battlefield tapped, then shuffle. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility( - new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter), true)), - condition, "When {this} enters, if an opponent controls more lands than you, " + - "search your library for a basic Plains card, put it onto the battlefield tapped, then shuffle." - ).withFlavorWord("Keen Sight")); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter), true) + ).withInterveningIf(condition).withFlavorWord("Keen Sight")); } private ScoutingHawk(final ScoutingHawk card) { diff --git a/Mage.Sets/src/mage/cards/s/Scrapshooter.java b/Mage.Sets/src/mage/cards/s/Scrapshooter.java index ff8ecce344d..e222374435e 100644 --- a/Mage.Sets/src/mage/cards/s/Scrapshooter.java +++ b/Mage.Sets/src/mage/cards/s/Scrapshooter.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.GiftWasPromisedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.GiftAbility; import mage.abilities.keyword.ReachAbility; @@ -47,11 +46,7 @@ public final class Scrapshooter extends CardImpl { this.addAbility(ReachAbility.getInstance()); // When Scrapshooter enters, if the gift was promised, destroy target artifact or enchantment an opponent controls. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()), - GiftWasPromisedCondition.TRUE, "When {this} enters, if the gift was promised, " + - "destroy target artifact or enchantment an opponent controls." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()).withInterveningIf(GiftWasPromisedCondition.TRUE); ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/ScreamingNemesis.java b/Mage.Sets/src/mage/cards/s/ScreamingNemesis.java index dcc1e1e2f98..af499a01b4a 100644 --- a/Mage.Sets/src/mage/cards/s/ScreamingNemesis.java +++ b/Mage.Sets/src/mage/cards/s/ScreamingNemesis.java @@ -17,7 +17,7 @@ import mage.filter.predicate.mageobject.AnotherPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.common.TargetAnyTarget; +import mage.target.common.TargetPermanentOrPlayer; import mage.target.targetpointer.FixedTarget; import java.util.UUID; @@ -45,7 +45,7 @@ public final class ScreamingNemesis extends CardImpl { // Whenever Screaming Nemesis is dealt damage, it deals that much damage to any other target. If a player is dealt damage this way, they can't gain life for the rest of the game. Ability ability = new DealtDamageToSourceTriggeredAbility(new ScreamingNemesisEffect(), false); - ability.addTarget(new TargetAnyTarget(filter)); + ability.addTarget(new TargetPermanentOrPlayer(filter)); this.addAbility(ability); } @@ -98,4 +98,4 @@ class ScreamingNemesisEffect extends OneShotEffect { } return false; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/s/ScreechingSilcaw.java b/Mage.Sets/src/mage/cards/s/ScreechingSilcaw.java index a65526d9ab0..298bf6f41aa 100644 --- a/Mage.Sets/src/mage/cards/s/ScreechingSilcaw.java +++ b/Mage.Sets/src/mage/cards/s/ScreechingSilcaw.java @@ -1,10 +1,8 @@ package mage.cards.s; import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.condition.common.MetalcraftCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.MillCardsTargetEffect; import mage.abilities.hint.common.MetalcraftHint; import mage.abilities.keyword.FlyingAbility; @@ -31,15 +29,9 @@ public final class ScreechingSilcaw extends CardImpl { this.addAbility(FlyingAbility.getInstance()); //"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 MillCardsTargetEffect(4), false, true - ), MetalcraftCondition.instance, "Whenever {this} " + - "deals combat damage to a player, if you control three or more artifacts, that player mills four cards." - ); - conditional.setAbilityWord(AbilityWord.METALCRAFT); - conditional.addHint(MetalcraftHint.instance); - this.addAbility(conditional); + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility( + new MillCardsTargetEffect(4), false, true + ).withInterveningIf(MetalcraftCondition.instance).setAbilityWord(AbilityWord.METALCRAFT).addHint(MetalcraftHint.instance)); } private ScreechingSilcaw(final ScreechingSilcaw card) { diff --git a/Mage.Sets/src/mage/cards/s/ScrollOfOrigins.java b/Mage.Sets/src/mage/cards/s/ScrollOfOrigins.java index 17d4a194423..ba99bbbd763 100644 --- a/Mage.Sets/src/mage/cards/s/ScrollOfOrigins.java +++ b/Mage.Sets/src/mage/cards/s/ScrollOfOrigins.java @@ -1,32 +1,36 @@ package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInHandCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; -import mage.constants.Zone; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class ScrollOfOrigins extends CardImpl { + private static final Condition condition = new CardsInHandCondition(ComparisonType.MORE_THAN, 6); + public ScrollOfOrigins(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); // {2}, {tap}: Draw a card if you have seven or more cards in hand. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), new GenericManaCost(2), - new CardsInHandCondition(ComparisonType.MORE_THAN, 6), - "{2}, {T}: Draw a card if you have seven or more cards in hand."); - ability.addCost(new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(new ConditionalOneShotEffect( + new DrawCardSourceControllerEffect(1), condition, + "draw a card if you have seven or more cards in hand" + ), new GenericManaCost(2)); + ability.addCost(new TapSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/ScroungingBandar.java b/Mage.Sets/src/mage/cards/s/ScroungingBandar.java index 6d9fb216110..108102b4edd 100644 --- a/Mage.Sets/src/mage/cards/s/ScroungingBandar.java +++ b/Mage.Sets/src/mage/cards/s/ScroungingBandar.java @@ -17,8 +17,11 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * * @author Styxo @@ -38,7 +41,7 @@ public final class ScroungingBandar extends CardImpl { // At the beginning of you upkeep, you may move any number of +1/+1 counters from Scrounging Bandar onto another target creature. Ability ability = new BeginningOfUpkeepTriggeredAbility(new ScroungingBandarEffect(), true); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/ScrybRanger.java b/Mage.Sets/src/mage/cards/s/ScrybRanger.java index 8f55de220dd..7ed87770afb 100644 --- a/Mage.Sets/src/mage/cards/s/ScrybRanger.java +++ b/Mage.Sets/src/mage/cards/s/ScrybRanger.java @@ -1,7 +1,5 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; import mage.abilities.Ability; @@ -15,13 +13,13 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.common.FilterControlledLandPermanent; import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author Plopman */ public final class ScrybRanger extends CardImpl { @@ -42,12 +40,17 @@ public final class ScrybRanger extends CardImpl { // Flash this.addAbility(FlashAbility.getInstance()); + // Flying this.addAbility(FlyingAbility.getInstance()); + // protection from blue this.addAbility(ProtectionAbility.from(ObjectColor.BLUE)); + // Return a Forest you control to its owner's hand: Untap target creature. Activate this ability only once each turn. - Ability ability = new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, new UntapTargetEffect(), new ReturnToHandChosenControlledPermanentCost(new TargetControlledPermanent(filterForest))); + Ability ability = new LimitedTimesPerTurnActivatedAbility( + new UntapTargetEffect(), new ReturnToHandChosenControlledPermanentCost(new TargetControlledPermanent(filterForest)) + ); ability.addTarget(new TargetCreaturePermanent(1)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/ScuttlingButler.java b/Mage.Sets/src/mage/cards/s/ScuttlingButler.java index ac709ef1e0a..b0016c9c068 100644 --- a/Mage.Sets/src/mage/cards/s/ScuttlingButler.java +++ b/Mage.Sets/src/mage/cards/s/ScuttlingButler.java @@ -1,32 +1,38 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; import mage.abilities.keyword.DoubleStrikeAbility; -import mage.constants.*; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.Duration; +import mage.constants.SubType; import mage.filter.FilterPermanent; import mage.filter.predicate.mageobject.MulticoloredPredicate; +import java.util.UUID; + /** - * * @author weirddan455 */ public final class ScuttlingButler extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("multicolored permanents"); + private static final FilterPermanent filter = new FilterPermanent("you control two or more multicolored permanents"); static { filter.add(MulticoloredPredicate.instance); } private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1); + private static final Hint hint = new ValueHint("Multicolored permanents you control", new PermanentsOnBattlefieldCount(filter)); public ScuttlingButler(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}"); @@ -36,11 +42,9 @@ public final class ScuttlingButler extends CardImpl { this.toughness = new MageInt(1); // At the beginning of combat on your turn, if you control two or more multicolored permanents, Scuttling Butler gains double strike until end of turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility(new GainAbilitySourceEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn)), - condition, - "At the beginning of combat on your turn, if you control two or more multicolored permanents, {this} gains double strike until end of turn." - )); + this.addAbility(new BeginningOfCombatTriggeredAbility(new GainAbilitySourceEffect( + DoubleStrikeAbility.getInstance(), Duration.EndOfTurn + )).withInterveningIf(condition)); } private ScuttlingButler(final ScuttlingButler card) { diff --git a/Mage.Sets/src/mage/cards/s/SeaGateWreckage.java b/Mage.Sets/src/mage/cards/s/SeaGateWreckage.java index bf4568f0ac9..d9460612177 100644 --- a/Mage.Sets/src/mage/cards/s/SeaGateWreckage.java +++ b/Mage.Sets/src/mage/cards/s/SeaGateWreckage.java @@ -1,34 +1,33 @@ - package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.condition.common.HellbentCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.mana.ColorlessManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; + +import java.util.UUID; /** - * * @author fireshoes */ public final class SeaGateWreckage extends CardImpl { public SeaGateWreckage(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.LAND},""); + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); // {T}: Add {C}. this.addAbility(new ColorlessManaAbility()); - + // {2}{C}, {T}: Draw a card. Activate this ability only if you have no cards in hand. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), - new ManaCostsImpl<>("{2}{C}"), HellbentCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new DrawCardSourceControllerEffect(1), new ManaCostsImpl<>("{2}{C}"), HellbentCondition.instance + ); ability.addCost(new TapSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SeaTroll.java b/Mage.Sets/src/mage/cards/s/SeaTroll.java index 84843e7340a..5234a2f2a4f 100644 --- a/Mage.Sets/src/mage/cards/s/SeaTroll.java +++ b/Mage.Sets/src/mage/cards/s/SeaTroll.java @@ -5,14 +5,13 @@ import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.condition.Condition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.RegenerateSourceEffect; 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.permanent.Permanent; @@ -23,20 +22,21 @@ import java.util.Set; import java.util.UUID; /** - * * @author noahg */ public final class SeaTroll extends CardImpl { public SeaTroll(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); - + this.subtype.add(SubType.TROLL); this.power = new MageInt(2); this.toughness = new MageInt(1); // {U}: Regenerate Sea Troll. Activate this ability only if Sea Troll blocked or was blocked by a blue creature this turn. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ManaCostsImpl<>("{U}"), new SeaTrollCondition()); + Ability ability = new ActivateIfConditionActivatedAbility( + new RegenerateSourceEffect(), new ManaCostsImpl<>("{U}"), SeaTrollCondition.instance + ); ability.addWatcher(new SeaTrollWatcher()); this.addAbility(ability); } @@ -56,7 +56,7 @@ class SeaTrollWatcher extends Watcher { private final Set blockedOrBlockedByBlueThisTurnCreatures; public SeaTrollWatcher() { - super( WatcherScope.GAME); + super(WatcherScope.GAME); blockedOrBlockedByBlueThisTurnCreatures = new HashSet<>(); } @@ -65,10 +65,10 @@ class SeaTrollWatcher extends Watcher { if (event.getType() == GameEvent.EventType.BLOCKER_DECLARED) { MageObjectReference blocker = new MageObjectReference(event.getSourceId(), game); MageObjectReference attacker = new MageObjectReference(event.getTargetId(), game); - if (blocker.getPermanentOrLKIBattlefield(game).getColor(game).isBlue()){ + if (blocker.getPermanentOrLKIBattlefield(game).getColor(game).isBlue()) { blockedOrBlockedByBlueThisTurnCreatures.add(attacker); } - if (attacker.getPermanentOrLKIBattlefield(game).getColor(game).isBlue()){ + if (attacker.getPermanentOrLKIBattlefield(game).getColor(game).isBlue()) { blockedOrBlockedByBlueThisTurnCreatures.add(blocker); } } @@ -80,17 +80,18 @@ class SeaTrollWatcher extends Watcher { blockedOrBlockedByBlueThisTurnCreatures.clear(); } - public boolean blockedOrBlockedByBlueCreatureThisTurn(MageObjectReference creature){ + public boolean blockedOrBlockedByBlueCreatureThisTurn(MageObjectReference creature) { return blockedOrBlockedByBlueThisTurnCreatures.contains(creature); } } -class SeaTrollCondition implements Condition { +enum SeaTrollCondition implements Condition { + instance; @Override public boolean apply(Game game, Ability source) { Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); - if (sourcePermanent != null){ + if (sourcePermanent != null) { SeaTrollWatcher watcher = game.getState().getWatcher(SeaTrollWatcher.class); if (watcher != null) { return watcher.blockedOrBlockedByBlueCreatureThisTurn(new MageObjectReference(sourcePermanent, game)); @@ -103,4 +104,4 @@ class SeaTrollCondition implements Condition { public String toString() { return "{this} blocked or was blocked by a blue creature this turn"; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/s/SealOfDoom.java b/Mage.Sets/src/mage/cards/s/SealOfDoom.java index 64ca2f487eb..be3544f7a0b 100644 --- a/Mage.Sets/src/mage/cards/s/SealOfDoom.java +++ b/Mage.Sets/src/mage/cards/s/SealOfDoom.java @@ -10,8 +10,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * @author Loki */ @@ -21,7 +24,7 @@ public final class SealOfDoom extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{B}"); Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(true), new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + ability.addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SearingLight.java b/Mage.Sets/src/mage/cards/s/SearingLight.java index b1758315024..08bd54f8a41 100644 --- a/Mage.Sets/src/mage/cards/s/SearingLight.java +++ b/Mage.Sets/src/mage/cards/s/SearingLight.java @@ -9,6 +9,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.common.FilterAttackingOrBlockingCreature; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -27,7 +28,7 @@ public final class SearingLight extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{W}"); // Destroying target attacking or blocking creature with power 2 or less. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); } diff --git a/Mage.Sets/src/mage/cards/s/SecondChance.java b/Mage.Sets/src/mage/cards/s/SecondChance.java index 5fd611b2534..5d142722089 100644 --- a/Mage.Sets/src/mage/cards/s/SecondChance.java +++ b/Mage.Sets/src/mage/cards/s/SecondChance.java @@ -1,11 +1,10 @@ package mage.cards.s; -import mage.abilities.TriggeredAbility; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.Ability; import mage.abilities.condition.common.FatefulHourCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.effects.common.turn.AddExtraTurnControllerEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -13,19 +12,17 @@ import mage.constants.CardType; import java.util.UUID; /** - * * @author Plopman */ public final class SecondChance extends CardImpl { public SecondChance(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); // At the beginning of your upkeep, if you have 5 or less life, sacrifice Second Chance and take an extra turn after this one. - TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceEffect()); - ability.addEffect(new AddExtraTurnControllerEffect()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, FatefulHourCondition.instance, - "At the beginning of your upkeep, if you have 5 or less life, sacrifice {this} and take an extra turn after this one")); + Ability ability = new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceEffect()).withInterveningIf(FatefulHourCondition.instance); + ability.addEffect(new AddExtraTurnControllerEffect().concatBy("and")); + this.addAbility(ability); } private SecondChance(final SecondChance card) { @@ -36,6 +33,6 @@ public final class SecondChance extends CardImpl { public SecondChance copy() { return new SecondChance(this); } - + } diff --git a/Mage.Sets/src/mage/cards/s/Secretkeeper.java b/Mage.Sets/src/mage/cards/s/Secretkeeper.java index 6ab1105526c..9d3552fc942 100644 --- a/Mage.Sets/src/mage/cards/s/Secretkeeper.java +++ b/Mage.Sets/src/mage/cards/s/Secretkeeper.java @@ -34,7 +34,7 @@ public final class Secretkeeper extends CardImpl { Ability ability = new SimpleStaticAbility(new ConditionalContinuousEffect( new BoostSourceEffect(2,2, Duration.WhileOnBattlefield), MoreCardsInHandThanOpponentsCondition.instance, - "As long as you have more cards in hand than each opponent, Secretkeeper gets +2/+2")); + "As long as you have more cards in hand than each opponent, {this} gets +2/+2")); ability.addEffect(new ConditionalContinuousEffect( new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.WhileOnBattlefield), MoreCardsInHandThanOpponentsCondition.instance, diff --git a/Mage.Sets/src/mage/cards/s/SedraxisAlchemist.java b/Mage.Sets/src/mage/cards/s/SedraxisAlchemist.java index d6f0ddcb1ec..4fc68da827e 100644 --- a/Mage.Sets/src/mage/cards/s/SedraxisAlchemist.java +++ b/Mage.Sets/src/mage/cards/s/SedraxisAlchemist.java @@ -1,38 +1,38 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandTargetEffect; 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.mageobject.ColorPredicate; import mage.target.common.TargetNonlandPermanent; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class SedraxisAlchemist extends CardImpl { - - private static final FilterControlledPermanent filter = new FilterControlledPermanent("blue permanent"); + + private static final FilterPermanent filter = new FilterControlledPermanent("you control a blue permanent"); static { filter.add(new ColorPredicate(ObjectColor.BLUE)); } - - private static final String rule = "When {this} enters, if you control a blue permanent, return target nonland permanent to its owner's hand."; + + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); public SedraxisAlchemist(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.ZOMBIE); this.subtype.add(SubType.WIZARD); @@ -40,10 +40,9 @@ public final class SedraxisAlchemist extends CardImpl { this.toughness = new MageInt(2); // When Sedraxis Alchemist enters the battlefield, if you control a blue permanent, return target nonland permanent to its owner's hand. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), false); + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), false).withInterveningIf(condition); ability.addTarget(new TargetNonlandPermanent()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new PermanentsOnTheBattlefieldCondition(filter), rule)); - + this.addAbility(ability); } private SedraxisAlchemist(final SedraxisAlchemist card) { diff --git a/Mage.Sets/src/mage/cards/s/SeeRed.java b/Mage.Sets/src/mage/cards/s/SeeRed.java index f0aa47dddde..23b5194723f 100644 --- a/Mage.Sets/src/mage/cards/s/SeeRed.java +++ b/Mage.Sets/src/mage/cards/s/SeeRed.java @@ -1,14 +1,10 @@ - package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.effects.common.continuous.BoostEnchantedEffect; @@ -16,24 +12,28 @@ import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.hint.common.RaidHint; import mage.abilities.keyword.EnchantAbility; import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AttachmentType; import mage.constants.CardType; -import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.SubType; -import mage.constants.Zone; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.watchers.common.PlayerAttackedWatcher; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class SeeRed extends CardImpl { + private static final Condition condition = new InvertCondition( + RaidCondition.instance, "you didn't attack with a creature this turn" + ); + public SeeRed(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}"); @@ -43,24 +43,18 @@ public final class SeeRed extends CardImpl { TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // Enchanted creature gets +2/+1 and has first strike. - ability = new SimpleStaticAbility(new BoostEnchantedEffect(2, 1, Duration.WhileOnBattlefield)); - Effect effect = new GainAbilityAttachedEffect(FirstStrikeAbility.getInstance(), AttachmentType.AURA); - effect.setText("and has first strike"); - ability.addEffect(effect); + Ability ability = new SimpleStaticAbility(new BoostEnchantedEffect(2, 1)); + ability.addEffect(new GainAbilityAttachedEffect( + FirstStrikeAbility.getInstance(), AttachmentType.AURA + ).setText("and has first strike")); this.addAbility(ability); // At the beginning of your end step, if you didn't attack with a creature this turn, sacrifice See Red. - ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility(new SacrificeSourceEffect()), - new InvertCondition(RaidCondition.instance), - "At the beginning of your end step, if you didn't attack with a creature this turn, sacrifice {this}." - ); - ability.addHint(RaidHint.instance); - this.addAbility(ability, new PlayerAttackedWatcher()); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new SacrificeSourceEffect()) + .withInterveningIf(condition).addHint(RaidHint.instance), new PlayerAttackedWatcher()); } private SeeRed(final SeeRed card) { diff --git a/Mage.Sets/src/mage/cards/s/SeekerOfInsight.java b/Mage.Sets/src/mage/cards/s/SeekerOfInsight.java index 55be104f1ba..5a5b24a3247 100644 --- a/Mage.Sets/src/mage/cards/s/SeekerOfInsight.java +++ b/Mage.Sets/src/mage/cards/s/SeekerOfInsight.java @@ -1,8 +1,5 @@ - package mage.cards.s; -import java.util.List; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; @@ -13,13 +10,12 @@ 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.stack.Spell; import mage.watchers.common.SpellsCastWatcher; +import java.util.UUID; + /** - * * @author anonymous */ public final class SeekerOfInsight extends CardImpl { @@ -33,12 +29,9 @@ public final class SeekerOfInsight extends CardImpl { this.toughness = new MageInt(3); // {T}: Draw a card, then discard a card. Activate this ability only if you've cast a noncreature spell this turn. - this.addAbility( - new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, - new DrawDiscardControllerEffect(), - new TapSourceCost(), - new CastNonCreatureSpellCondition())); + this.addAbility(new ActivateIfConditionActivatedAbility( + new DrawDiscardControllerEffect(), new TapSourceCost(), SeekerOfInsightCondition.instance + )); } private SeekerOfInsight(final SeekerOfInsight card) { @@ -51,22 +44,17 @@ public final class SeekerOfInsight extends CardImpl { } } -class CastNonCreatureSpellCondition implements Condition { +enum SeekerOfInsightCondition implements Condition { + instance; @Override public boolean apply(Game game, Ability source) { - SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class); - if (watcher != null) { - List spellsCast = watcher.getSpellsCastThisTurn(source.getControllerId()); - if (spellsCast != null) { - for (Spell spell : spellsCast) { - if (!spell.isCreature(game)) { - return true; - } - } - } - } - return false; + return game + .getState() + .getWatcher(SpellsCastWatcher.class) + .getSpellsCastThisTurn(source.getControllerId()) + .stream() + .anyMatch(spell -> !spell.isCreature(game)); } @Override diff --git a/Mage.Sets/src/mage/cards/s/SeismicShift.java b/Mage.Sets/src/mage/cards/s/SeismicShift.java index be1b13ab3b4..d97740b83f6 100644 --- a/Mage.Sets/src/mage/cards/s/SeismicShift.java +++ b/Mage.Sets/src/mage/cards/s/SeismicShift.java @@ -1,20 +1,18 @@ - package mage.cards.s; -import java.util.UUID; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.combat.CantBlockTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.filter.StaticFilters; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetLandPermanent; import mage.target.targetpointer.SecondTargetPointer; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class SeismicShift extends CardImpl { @@ -28,7 +26,7 @@ public final class SeismicShift extends CardImpl { this.getSpellAbility().addEffect(new CantBlockTargetEffect(Duration.EndOfTurn) .setText("Up to two target creatures can't block this turn") .setTargetPointer(new SecondTargetPointer())); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 2, StaticFilters.FILTER_PERMANENT_CREATURES, false)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 2)); } private SeismicShift(final SeismicShift card) { diff --git a/Mage.Sets/src/mage/cards/s/SeizeTheSoul.java b/Mage.Sets/src/mage/cards/s/SeizeTheSoul.java index bffe087601a..d417ef78e77 100644 --- a/Mage.Sets/src/mage/cards/s/SeizeTheSoul.java +++ b/Mage.Sets/src/mage/cards/s/SeizeTheSoul.java @@ -12,6 +12,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; import mage.game.permanent.token.SpiritWhiteToken; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -34,13 +35,13 @@ public final class SeizeTheSoul extends CardImpl { // Destroy target nonwhite, nonblack creature. Put a 1/1 white Spirit creature token with flying onto the battlefield. this.getSpellAbility().addEffect(new DestroyTargetEffect()); this.getSpellAbility().addEffect(new CreateTokenEffect(new SpiritWhiteToken())); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // Haunt // When the creature Seize the Soul haunts dies, destroy target nonwhite, nonblack creature. Put a 1/1 white Spirit creature token with flying onto the battlefield. Ability ability = new HauntAbility(this, new DestroyTargetEffect()); ability.addEffect(new CreateTokenEffect(new SpiritWhiteToken())); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SelectForInspection.java b/Mage.Sets/src/mage/cards/s/SelectForInspection.java index d5d7e8a0a81..350aaf21852 100644 --- a/Mage.Sets/src/mage/cards/s/SelectForInspection.java +++ b/Mage.Sets/src/mage/cards/s/SelectForInspection.java @@ -9,6 +9,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -28,7 +29,7 @@ public final class SelectForInspection extends CardImpl { // Return target tapped creature to its owner's hand. Scry 1. this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new ScryEffect(1)); } diff --git a/Mage.Sets/src/mage/cards/s/SelesnyaCharm.java b/Mage.Sets/src/mage/cards/s/SelesnyaCharm.java index 2c996db5cc3..5e497797990 100644 --- a/Mage.Sets/src/mage/cards/s/SelesnyaCharm.java +++ b/Mage.Sets/src/mage/cards/s/SelesnyaCharm.java @@ -17,6 +17,7 @@ import mage.constants.Duration; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; import mage.game.permanent.token.KnightToken; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -46,7 +47,7 @@ public final class SelesnyaCharm extends CardImpl { // or exile target creature with power 5 or greater; Mode mode = new Mode(new ExileTargetEffect()); - mode.addTarget(new TargetCreaturePermanent(filter)); + mode.addTarget(new TargetPermanent(filter)); this.getSpellAbility().addMode(mode); // or create a 2/2 white Knight creature token with vigilance. diff --git a/Mage.Sets/src/mage/cards/s/SelesnyaEvangel.java b/Mage.Sets/src/mage/cards/s/SelesnyaEvangel.java index 228442bf655..759efd76f6e 100644 --- a/Mage.Sets/src/mage/cards/s/SelesnyaEvangel.java +++ b/Mage.Sets/src/mage/cards/s/SelesnyaEvangel.java @@ -1,7 +1,5 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -13,26 +11,18 @@ 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.permanent.TappedPredicate; +import mage.filter.StaticFilters; import mage.game.permanent.token.SaprolingToken; -import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; /** - * * @author Loki */ public final class SelesnyaEvangel extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); - - static { - filter.add(TappedPredicate.UNTAPPED); - } - public SelesnyaEvangel(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{W}"); this.subtype.add(SubType.ELF); this.subtype.add(SubType.SHAMAN); @@ -42,7 +32,7 @@ public final class SelesnyaEvangel extends CardImpl { // {1}, {tap}, Tap an untapped creature you control: Create a 1/1 green Saproling creature token. Ability ability = new SimpleActivatedAbility(new CreateTokenEffect(new SaprolingToken()), new GenericManaCost(1)); ability.addCost(new TapSourceCost()); - ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, true))); + ability.addCost(new TapTargetCost(StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SelfDestruct.java b/Mage.Sets/src/mage/cards/s/SelfDestruct.java index fb3b01e108f..8e57a76ef4c 100644 --- a/Mage.Sets/src/mage/cards/s/SelfDestruct.java +++ b/Mage.Sets/src/mage/cards/s/SelfDestruct.java @@ -11,8 +11,8 @@ import mage.filter.predicate.other.AnotherTargetPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.common.TargetAnyTarget; import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetPermanentOrPlayer; import mage.target.targetpointer.EachTargetPointer; import java.util.List; @@ -36,7 +36,7 @@ public final class SelfDestruct extends CardImpl { // Target creature you control deals X damage to any other target and X damage to itself, where X is its power. this.getSpellAbility().addEffect(new SelfDestructEffect()); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent().setTargetTag(1)); - this.getSpellAbility().addTarget(new TargetAnyTarget(filter).setTargetTag(2)); + this.getSpellAbility().addTarget(new TargetPermanentOrPlayer(filter).setTargetTag(2)); } private SelfDestruct(final SelfDestruct card) { diff --git a/Mage.Sets/src/mage/cards/s/SelkieHedgeMage.java b/Mage.Sets/src/mage/cards/s/SelkieHedgeMage.java index ff49fea0ee2..49b6fc221ef 100644 --- a/Mage.Sets/src/mage/cards/s/SelkieHedgeMage.java +++ b/Mage.Sets/src/mage/cards/s/SelkieHedgeMage.java @@ -1,12 +1,11 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; @@ -14,29 +13,33 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.common.FilterLandPermanent; import mage.filter.predicate.permanent.TappedPredicate; import mage.target.TargetPermanent; +import java.util.UUID; + /** * @author jeffwadsworth */ public final class SelkieHedgeMage extends CardImpl { - private static final FilterLandPermanent filter = new FilterLandPermanent("Forests"); - private static final FilterLandPermanent filter2 = new FilterLandPermanent("Islands"); - private static final FilterCreaturePermanent filter3 = new FilterCreaturePermanent("tapped creature"); + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPermanent(SubType.FOREST, "you control two or more Forests"), + ComparisonType.MORE_THAN, 1 + ); + private static final Condition condition2 = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPermanent(SubType.ISLAND, "you control two or more Islands"), + ComparisonType.MORE_THAN, 1 + ); + private static final FilterPermanent filter = new FilterCreaturePermanent("tapped creature"); static { - filter.add(SubType.FOREST.getPredicate()); - filter2.add(SubType.ISLAND.getPredicate()); - filter3.add(TappedPredicate.TAPPED); + filter.add(TappedPredicate.TAPPED); } - private static final String rule1 = "When {this} enters, if you control two or more Forests, you may gain 3 life."; - private static final String rule2 = "When {this} enters, if you control two or more Islands, you may return target tapped creature to its owner's hand."; - public SelkieHedgeMage(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G/U}"); this.subtype.add(SubType.MERFOLK); @@ -48,14 +51,12 @@ public final class SelkieHedgeMage extends CardImpl { this.toughness = new MageInt(2); // When Selkie Hedge-Mage enters the battlefield, if you control two or more Forests, you may gain 3 life. - Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3), true), new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1), rule1); - this.addAbility(ability); + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3), true).withInterveningIf(condition)); // When Selkie Hedge-Mage enters the battlefield, if you control two or more Islands, you may return target tapped creature to its owner's hand. - Ability ability2 = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true), new PermanentsOnTheBattlefieldCondition(filter2, ComparisonType.MORE_THAN, 1), rule2); - ability2.addTarget(new TargetPermanent(filter3)); - this.addAbility(ability2); - + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true).withInterveningIf(condition2); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); } private SelkieHedgeMage(final SelkieHedgeMage card) { diff --git a/Mage.Sets/src/mage/cards/s/SentinelsMark.java b/Mage.Sets/src/mage/cards/s/SentinelsMark.java index 6598b4ceaa6..faaaa248f20 100644 --- a/Mage.Sets/src/mage/cards/s/SentinelsMark.java +++ b/Mage.Sets/src/mage/cards/s/SentinelsMark.java @@ -4,7 +4,6 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.AddendumCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.continuous.BoostEnchantedEffect; import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; @@ -37,23 +36,19 @@ public final class SentinelsMark extends CardImpl { TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // Enchanted creature gets +1/+2 and has vigilance. - ability = new SimpleStaticAbility(new BoostEnchantedEffect(1, 2)); + Ability ability = new SimpleStaticAbility(new BoostEnchantedEffect(1, 2)); ability.addEffect(new GainAbilityAttachedEffect( VigilanceAbility.getInstance(), AttachmentType.AURA ).setText("and has vigilance")); this.addAbility(ability); // Addendum — When Sentinel's Mark enters the battlefield, if you cast it during your main phase, enchanted creature gains lifelink until end of turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new GainAbilityAttachedEffect( - LifelinkAbility.getInstance(), AttachmentType.AURA, Duration.EndOfTurn - )), AddendumCondition.instance, "
Addendum — When {this} enters, " + - "if you cast it during your main phase, enchanted creature gains lifelink until end of turn." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainAbilityAttachedEffect( + LifelinkAbility.getInstance(), AttachmentType.AURA, Duration.EndOfTurn + )).withInterveningIf(AddendumCondition.instance).setAbilityWord(AbilityWord.ADDENDUM)); } private SentinelsMark(final SentinelsMark card) { diff --git a/Mage.Sets/src/mage/cards/s/SenuKeenEyedProtector.java b/Mage.Sets/src/mage/cards/s/SenuKeenEyedProtector.java index 9d2dde61317..33f7e4756e8 100644 --- a/Mage.Sets/src/mage/cards/s/SenuKeenEyedProtector.java +++ b/Mage.Sets/src/mage/cards/s/SenuKeenEyedProtector.java @@ -7,7 +7,6 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.SourceInExileCondition; import mage.abilities.costs.common.ExileSourceCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.keyword.ScryEffect; @@ -17,8 +16,7 @@ import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.FilterPermanent; -import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -30,13 +28,6 @@ import java.util.UUID; */ public final class SenuKeenEyedProtector extends CardImpl { - private static final FilterPermanent filter = - new FilterControlledCreaturePermanent("a legendary creature you control"); - - static { - filter.add(SuperType.LEGENDARY.getPredicate()); - } - public SenuKeenEyedProtector(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); @@ -53,24 +44,15 @@ public final class SenuKeenEyedProtector extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // {T}, Exile Senu, Keen-Eyed Protector: You gain 2 life and scry 2. - Ability ability = new SimpleActivatedAbility( - new GainLifeEffect(2), - new TapSourceCost() - ); + Ability ability = new SimpleActivatedAbility(new GainLifeEffect(2), new TapSourceCost()); ability.addCost(new ExileSourceCost()); ability.addEffect(new ScryEffect(2).concatBy("and")); this.addAbility(ability); // When a legendary creature you control attacks and isn't blocked, if Senu is exiled, put it onto the battlefield attacking. - this.addAbility( - new ConditionalInterveningIfTriggeredAbility( - new AttacksAndIsNotBlockedAllTriggeredAbility( - Zone.EXILED, new SenuKeenEyedProtectorEffect(), filter - ), SourceInExileCondition.instance, - "When a legendary creature you control attacks and isn't blocked, " - + "if {this} is exiled, put it onto the battlefield attacking" - ) - ); + this.addAbility(new AttacksAndIsNotBlockedAllTriggeredAbility( + Zone.EXILED, new SenuKeenEyedProtectorEffect(), StaticFilters.FILTER_CONTROLLED_CREATURE_LEGENDARY + ).withInterveningIf(SourceInExileCondition.instance).setTriggerPhrase("When a legendary creature you control attacks and isn't blocked, ")); } private SenuKeenEyedProtector(final SenuKeenEyedProtector card) { @@ -113,5 +95,4 @@ class SenuKeenEyedProtectorEffect extends OneShotEffect { } return true; } - -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/s/SepulchralPrimordial.java b/Mage.Sets/src/mage/cards/s/SepulchralPrimordial.java index 40f47af3a78..412d01515fa 100644 --- a/Mage.Sets/src/mage/cards/s/SepulchralPrimordial.java +++ b/Mage.Sets/src/mage/cards/s/SepulchralPrimordial.java @@ -62,7 +62,7 @@ public final class SepulchralPrimordial extends CardImpl { class SepulchralPrimordialEffect extends OneShotEffect { SepulchralPrimordialEffect() { - super(Outcome.PutCreatureInPlay); + super(Outcome.GainControl); this.staticText = "for each opponent, you may put up to one target creature card from that player's graveyard onto the battlefield under your control"; } diff --git a/Mage.Sets/src/mage/cards/s/SerendibSorcerer.java b/Mage.Sets/src/mage/cards/s/SerendibSorcerer.java index 32afdb747a2..e52caae46cd 100644 --- a/Mage.Sets/src/mage/cards/s/SerendibSorcerer.java +++ b/Mage.Sets/src/mage/cards/s/SerendibSorcerer.java @@ -15,6 +15,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,7 +39,7 @@ public final class SerendibSorcerer extends CardImpl { // {tap}: Target creature other than Serendib Sorcerer becomes 0/2 until end of turn. Ability ability = new SimpleActivatedAbility(new SetBasePowerToughnessTargetEffect(0, 2, Duration.EndOfTurn), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SereneMaster.java b/Mage.Sets/src/mage/cards/s/SereneMaster.java index 380d30a4f0d..6ad0063c779 100644 --- a/Mage.Sets/src/mage/cards/s/SereneMaster.java +++ b/Mage.Sets/src/mage/cards/s/SereneMaster.java @@ -18,6 +18,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.BlockingOrBlockedBySourcePredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; @@ -44,7 +45,7 @@ public final class SereneMaster extends CardImpl { // Whenever Serene Master blocks, exchange its power and the power of target creature it's blocking until end of combat. Ability ability = new BlocksSourceTriggeredAbility(new SereneMasterEffect()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/Serenity.java b/Mage.Sets/src/mage/cards/s/Serenity.java index ae237a58487..74a96e6cc80 100644 --- a/Mage.Sets/src/mage/cards/s/Serenity.java +++ b/Mage.Sets/src/mage/cards/s/Serenity.java @@ -1,31 +1,26 @@ - package mage.cards.s; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.common.OnEventTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DestroyAllEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; -import mage.game.events.GameEvent.EventType; + +import java.util.UUID; /** - * * @author Quercitron */ public final class Serenity extends CardImpl { public Serenity(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}"); - + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}"); // At the beginning of your upkeep, destroy all artifacts and enchantments. They can't be regenerated. - Effect effect = new DestroyAllEffect(StaticFilters.FILTER_PERMANENT_ARTIFACTS_AND_ENCHANTMENTS, true); - Ability ability = new OnEventTriggeredAbility(EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", effect, false); - this.addAbility(ability); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DestroyAllEffect( + StaticFilters.FILTER_PERMANENT_ARTIFACTS_AND_ENCHANTMENTS, true + ))); } private Serenity(final Serenity card) { diff --git a/Mage.Sets/src/mage/cards/s/SergeantAtArms.java b/Mage.Sets/src/mage/cards/s/SergeantAtArms.java index 2ef8849f74a..22ce6abd788 100644 --- a/Mage.Sets/src/mage/cards/s/SergeantAtArms.java +++ b/Mage.Sets/src/mage/cards/s/SergeantAtArms.java @@ -1,11 +1,8 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -14,8 +11,9 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.game.permanent.token.SoldierToken; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class SergeantAtArms extends CardImpl { @@ -32,9 +30,8 @@ public final class SergeantAtArms extends CardImpl { this.addAbility(new KickerAbility("{2}{W}")); // When Sergeant-at-Arms enters the battlefield, if it was kicked, create two 1/1 white soldier creature tokens. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new SoldierToken(), 2)), KickedCondition.ONCE, - "When {this} enters, if it was kicked, create two 1/1 white Soldier creature tokens.")); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new SoldierToken(), 2)) + .withInterveningIf(KickedCondition.ONCE)); } private SergeantAtArms(final SergeantAtArms card) { diff --git a/Mage.Sets/src/mage/cards/s/SerpentAssassin.java b/Mage.Sets/src/mage/cards/s/SerpentAssassin.java index 18d32d8794f..f8f668249c2 100644 --- a/Mage.Sets/src/mage/cards/s/SerpentAssassin.java +++ b/Mage.Sets/src/mage/cards/s/SerpentAssassin.java @@ -10,8 +10,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author fireshoes @@ -27,7 +30,7 @@ public final class SerpentAssassin extends CardImpl { // When Serpent Assassin enters the battlefield, you may destroy target nonblack creature. Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), true); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + ability.addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SerpentineSpike.java b/Mage.Sets/src/mage/cards/s/SerpentineSpike.java index 62841f30aad..b1eedebb8a7 100644 --- a/Mage.Sets/src/mage/cards/s/SerpentineSpike.java +++ b/Mage.Sets/src/mage/cards/s/SerpentineSpike.java @@ -1,9 +1,6 @@ - package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.replacement.DealtDamageToCreatureBySourceDies; import mage.abilities.keyword.DevoidAbility; @@ -12,19 +9,29 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.other.AnotherTargetPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.watchers.common.DamagedByWatcher; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class SerpentineSpike extends CardImpl { + private static final FilterPermanent filter = new FilterCreaturePermanent("another creature"); + + static { + filter.add(new AnotherTargetPredicate(3)); + } + public SerpentineSpike(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{5}{R}{R}"); @@ -33,26 +40,12 @@ public final class SerpentineSpike extends CardImpl { // Serpentine Spike deals 2 damage to target creature, 3 damage to another target creature, and 4 damage to a third target creature. If a creature dealt damage this way would die this turn, exile it instead. this.getSpellAbility().addEffect(new SerpentineSpikeEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent().withChooseHint("2 damage").setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2).withChooseHint("3 damage").setTargetTag(2)); + this.getSpellAbility().addTarget(new TargetPermanent(filter).withChooseHint("4 damage").setTargetTag(3)); - TargetCreaturePermanent target = new TargetCreaturePermanent(new FilterCreaturePermanent("creature (2 damage)")); - target.setTargetTag(1); - this.getSpellAbility().addTarget(target); - - FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature (3 damage)"); - filter.add(new AnotherTargetPredicate(2)); - target = new TargetCreaturePermanent(filter); - target.setTargetTag(2); - this.getSpellAbility().addTarget(target); - - filter = new FilterCreaturePermanent("another target creature (4 damage)"); - filter.add(new AnotherTargetPredicate(3)); - target = new TargetCreaturePermanent(filter); - target.setTargetTag(3); - this.getSpellAbility().addTarget(target); - - Effect effect = new DealtDamageToCreatureBySourceDies(this, Duration.EndOfTurn); - effect.setText("If a creature dealt damage this way would die this turn, exile it instead"); - this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addEffect(new DealtDamageToCreatureBySourceDies(this, Duration.EndOfTurn) + .setText("If a creature dealt damage this way would die this turn, exile it instead")); this.getSpellAbility().addWatcher(new DamagedByWatcher(false)); } diff --git a/Mage.Sets/src/mage/cards/s/SerraAdvocate.java b/Mage.Sets/src/mage/cards/s/SerraAdvocate.java index fedb8c4d002..9a3291dade6 100644 --- a/Mage.Sets/src/mage/cards/s/SerraAdvocate.java +++ b/Mage.Sets/src/mage/cards/s/SerraAdvocate.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterAttackingOrBlockingCreature; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -34,7 +35,7 @@ public final class SerraAdvocate extends CardImpl { // {tap}: Target attacking or blocking creature gets +2/+2 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(2, 2, Duration.EndOfTurn), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(new FilterAttackingOrBlockingCreature())); + ability.addTarget(new TargetPermanent(new FilterAttackingOrBlockingCreature())); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/ServantOfTheStinger.java b/Mage.Sets/src/mage/cards/s/ServantOfTheStinger.java index ce1d397992b..ebd6817ab4f 100644 --- a/Mage.Sets/src/mage/cards/s/ServantOfTheStinger.java +++ b/Mage.Sets/src/mage/cards/s/ServantOfTheStinger.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.condition.common.CommittedCrimeCondition; import mage.abilities.costs.common.SacrificeSourceCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; import mage.abilities.keyword.DeathtouchAbility; @@ -34,16 +33,9 @@ public final class ServantOfTheStinger extends CardImpl { this.addAbility(DeathtouchAbility.getInstance()); // Whenever Servant of the Stinger deals combat damage to a player, if you've committed a crime this turn, you may sacrifice Servant of the Stinger. If you do, search your library for a card, put it into your hand, then shuffle. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new DealsCombatDamageToAPlayerTriggeredAbility( - new DoIfCostPaid( - new SearchLibraryPutInHandEffect(new TargetCardInLibrary(), false), - new SacrificeSourceCost() - ), false - ), CommittedCrimeCondition.instance, "Whenever {this} deals combat damage to a player, " + - "if you've committed a crime this turn, you may sacrifice {this}. If you do, " + - "search your library for a card, put it into your hand, then shuffle." - ).addHint(CommittedCrimeCondition.getHint()), new CommittedCrimeWatcher()); + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DoIfCostPaid( + new SearchLibraryPutInHandEffect(new TargetCardInLibrary(), false), new SacrificeSourceCost() + )).withInterveningIf(CommittedCrimeCondition.instance).addHint(CommittedCrimeCondition.getHint()), new CommittedCrimeWatcher()); } private ServantOfTheStinger(final ServantOfTheStinger card) { diff --git a/Mage.Sets/src/mage/cards/s/SetessanTactics.java b/Mage.Sets/src/mage/cards/s/SetessanTactics.java index 9a2ab8bb6f9..63e244f25a1 100644 --- a/Mage.Sets/src/mage/cards/s/SetessanTactics.java +++ b/Mage.Sets/src/mage/cards/s/SetessanTactics.java @@ -15,6 +15,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -42,7 +43,7 @@ public final class SetessanTactics extends CardImpl { effect.setText("Until end of turn, any number of target creatures each get +1/+1"); this.getSpellAbility().addEffect(effect); Ability gainedAbility = new SimpleActivatedAbility(new FightTargetSourceEffect(), new TapSourceCost()); - gainedAbility.addTarget(new TargetCreaturePermanent(filter)); + gainedAbility.addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new GainAbilityTargetEffect(gainedAbility, Duration.EndOfTurn, "and gain \"{T}: This creature fights another target creature.\"")); } diff --git a/Mage.Sets/src/mage/cards/s/SettlementBlacksmith.java b/Mage.Sets/src/mage/cards/s/SettlementBlacksmith.java index 08e8d1b21a9..49d8c5862d6 100644 --- a/Mage.Sets/src/mage/cards/s/SettlementBlacksmith.java +++ b/Mage.Sets/src/mage/cards/s/SettlementBlacksmith.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.hint.ConditionHint; import mage.abilities.hint.Hint; @@ -21,8 +20,10 @@ import java.util.UUID; */ public final class SettlementBlacksmith extends CardImpl { - private static final Condition condition = new PermanentsOnTheBattlefieldCondition(new FilterControlledPermanent(SubType.EQUIPMENT)); - private static final Hint hint = new ConditionHint(condition, "You control an Equipment"); + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPermanent(SubType.EQUIPMENT, "you control an Equipment") + ); + private static final Hint hint = new ConditionHint(condition); public SettlementBlacksmith(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); @@ -33,10 +34,8 @@ public final class SettlementBlacksmith extends CardImpl { this.toughness = new MageInt(3); // When Settlement Blacksmith enters the battlefield, if you control an Equipment, draw a card. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)), - condition, "When {this} enters, if you control an Equipment, draw a card." - ).addHint(hint)); + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)) + .withInterveningIf(condition).addHint(hint)); } private SettlementBlacksmith(final SettlementBlacksmith card) { diff --git a/Mage.Sets/src/mage/cards/s/SeverSoul.java b/Mage.Sets/src/mage/cards/s/SeverSoul.java index 2bb08849296..80c1a99f6ea 100644 --- a/Mage.Sets/src/mage/cards/s/SeverSoul.java +++ b/Mage.Sets/src/mage/cards/s/SeverSoul.java @@ -12,8 +12,11 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author dustinconrad @@ -24,7 +27,7 @@ public final class SeverSoul extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{B}{B}"); // Destroy target nonblack creature. It can't be regenerated. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); // You gain life equal to its toughness. this.getSpellAbility().addEffect(new GainLifeEqualToToughnessEffect()); diff --git a/Mage.Sets/src/mage/cards/s/ShadowTheHedgehog.java b/Mage.Sets/src/mage/cards/s/ShadowTheHedgehog.java new file mode 100644 index 00000000000..cd92487b8a6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ShadowTheHedgehog.java @@ -0,0 +1,83 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.common.DiesThisOrAnotherTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledSpellsEffect; +import mage.abilities.keyword.FlashAbility; +import mage.abilities.keyword.HasteAbility; +import mage.abilities.keyword.SplitSecondAbility; +import mage.cards.Card; +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.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterNonlandCard; +import mage.filter.predicate.Predicate; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.game.Game; +import mage.game.stack.Spell; +import mage.watchers.common.ManaPaidSourceWatcher; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class ShadowTheHedgehog extends CardImpl { + + private static final FilterPermanent filter + = new FilterControlledCreaturePermanent("creature you control with flash or haste"); + private static final FilterNonlandCard filter2 = new FilterNonlandCard(); + + static { + filter.add(Predicates.or( + new AbilityPredicate(FlashAbility.class), + new AbilityPredicate(HasteAbility.class) + )); + filter2.add(ShadowTheHedgehogPredicate.instance); + } + + public ShadowTheHedgehog(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}{B}{R}{R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HEDGEHOG); + this.subtype.add(SubType.MERCENARY); + this.power = new MageInt(4); + this.toughness = new MageInt(2); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // Whenever Shadow the Hedgehog or another creature you control with flash or haste dies, draw a card. + this.addAbility(new DiesThisOrAnotherTriggeredAbility(new DrawCardSourceControllerEffect(1), false, filter)); + + // Chaos Control -- Each spell you cast has split second if mana from an artifact was spent to cast it. + this.addAbility(new SimpleStaticAbility(new GainAbilityControlledSpellsEffect(new SplitSecondAbility(), filter2) + .setText("each spell you cast has split second if mana from an artifact was spent to cast it")).withFlavorWord("Chaos Control")); + } + + private ShadowTheHedgehog(final ShadowTheHedgehog card) { + super(card); + } + + @Override + public ShadowTheHedgehog copy() { + return new ShadowTheHedgehog(this); + } +} + +enum ShadowTheHedgehogPredicate implements Predicate { + instance; + + @Override + public boolean apply(Card input, Game game) { + return input instanceof Spell && ManaPaidSourceWatcher.getArtifactPaid(input.getId(), game) > 0; + } +} diff --git a/Mage.Sets/src/mage/cards/s/ShadowbornDemon.java b/Mage.Sets/src/mage/cards/s/ShadowbornDemon.java index 6afac6d2232..b4550127ce1 100644 --- a/Mage.Sets/src/mage/cards/s/ShadowbornDemon.java +++ b/Mage.Sets/src/mage/cards/s/ShadowbornDemon.java @@ -1,16 +1,15 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.InvertCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.CardsInControllerGraveyardCondition; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.SacrificeControllerEffect; import mage.abilities.keyword.FlyingAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -18,13 +17,12 @@ import mage.constants.SubType; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; -import mage.game.Game; -import mage.players.Player; -import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class ShadowbornDemon extends CardImpl { @@ -35,6 +33,11 @@ public final class ShadowbornDemon extends CardImpl { filter.add(Predicates.not(SubType.DEMON.getPredicate())); } + private static final Condition condition = new InvertCondition( + new CardsInControllerGraveyardCondition(6, StaticFilters.FILTER_CARD_CREATURE), + "there are fewer than six creature cards in your graveyard" + ); + public ShadowbornDemon(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); this.subtype.add(SubType.DEMON); @@ -44,18 +47,16 @@ public final class ShadowbornDemon extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); + // When Shadowborn Demon enters the battlefield, destroy target non-Demon creature. Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), false); - Target target = new TargetCreaturePermanent(filter); - ability.addTarget(target); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // At the beginning of your upkeep, if there are fewer than six creature cards in your graveyard, sacrifice a creature. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new SacrificeControllerEffect(StaticFilters.FILTER_PERMANENT_CREATURE, 1, "")), - new InvertCondition(new CreatureCardsInControllerGraveyardCondition(6)), - "At the beginning of your upkeep, if there are fewer than six creature cards in your graveyard, sacrifice a creature")); - + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SacrificeControllerEffect( + StaticFilters.FILTER_PERMANENT_CREATURE, 1, "" + )).withInterveningIf(condition)); } private ShadowbornDemon(final ShadowbornDemon card) { @@ -67,21 +68,3 @@ public final class ShadowbornDemon extends CardImpl { return new ShadowbornDemon(this); } } - -class CreatureCardsInControllerGraveyardCondition implements Condition { - - private int value; - - public CreatureCardsInControllerGraveyardCondition(int value) { - this.value = value; - } - - @Override - public boolean apply(Game game, Ability source) { - Player p = game.getPlayer(source.getControllerId()); - if (p != null && p.getGraveyard().count(StaticFilters.FILTER_CARD_CREATURE, game) >= value) { - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/s/ShadowgrangeArchfiend.java b/Mage.Sets/src/mage/cards/s/ShadowgrangeArchfiend.java index b6d68eb9440..ede974a47e9 100644 --- a/Mage.Sets/src/mage/cards/s/ShadowgrangeArchfiend.java +++ b/Mage.Sets/src/mage/cards/s/ShadowgrangeArchfiend.java @@ -20,7 +20,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.ArrayList; import java.util.List; @@ -47,10 +47,14 @@ public final class ShadowgrangeArchfiend extends CardImpl { this.addAbility(madnessAbility); } - private ShadowgrangeArchfiend(final ShadowgrangeArchfiend card) { super(card); } + private ShadowgrangeArchfiend(final ShadowgrangeArchfiend card) { + super(card); + } @Override - public ShadowgrangeArchfiend copy() { return new ShadowgrangeArchfiend(this); } + public ShadowgrangeArchfiend copy() { + return new ShadowgrangeArchfiend(this); + } } class ShadowgrangeArchfiendEffect extends OneShotEffect { @@ -61,10 +65,14 @@ class ShadowgrangeArchfiendEffect extends OneShotEffect { "You gain life equal to the greatest power among creatures sacrificed this way"; } - private ShadowgrangeArchfiendEffect(final ShadowgrangeArchfiendEffect effect) { super(effect); } + private ShadowgrangeArchfiendEffect(final ShadowgrangeArchfiendEffect effect) { + super(effect); + } @Override - public ShadowgrangeArchfiendEffect copy() { return new ShadowgrangeArchfiendEffect(this); } + public ShadowgrangeArchfiendEffect copy() { + return new ShadowgrangeArchfiendEffect(this); + } @Override public boolean apply(Game game, Ability source) { @@ -77,10 +85,14 @@ class ShadowgrangeArchfiendEffect extends OneShotEffect { // Iterate through each opponent for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { - if (!controller.hasOpponent(playerId, game)) { continue; } + if (!controller.hasOpponent(playerId, game)) { + continue; + } Player opponent = game.getPlayer(playerId); - if (opponent == null) { continue; } + if (opponent == null) { + continue; + } int greatestPower = Integer.MIN_VALUE; int numberOfCreatures = 0; @@ -102,7 +114,7 @@ class ShadowgrangeArchfiendEffect extends OneShotEffect { FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent( "creature to sacrifice with power equal to " + greatestPower); filter.add(new PowerPredicate(ComparisonType.EQUAL_TO, greatestPower)); - Target target = new TargetControlledCreaturePermanent(filter); + Target target = new TargetPermanent(filter); if (opponent.choose(outcome, target, source, game)) { creatureToSacrifice = game.getPermanent(target.getFirstTarget()); } diff --git a/Mage.Sets/src/mage/cards/s/ShadowsOfThePast.java b/Mage.Sets/src/mage/cards/s/ShadowsOfThePast.java index 6d87bf22b93..dc0c740887f 100644 --- a/Mage.Sets/src/mage/cards/s/ShadowsOfThePast.java +++ b/Mage.Sets/src/mage/cards/s/ShadowsOfThePast.java @@ -1,27 +1,28 @@ package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInControllerGraveyardCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; -import mage.abilities.effects.Effect; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.LoseLifeOpponentsEffect; import mage.abilities.effects.keyword.ScryEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; import mage.filter.StaticFilters; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class ShadowsOfThePast extends CardImpl { + private static final Condition condition = new CardsInControllerGraveyardCondition(4, StaticFilters.FILTER_CARD_CREATURES); + public ShadowsOfThePast(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}"); @@ -29,11 +30,10 @@ public final class ShadowsOfThePast extends CardImpl { this.addAbility(new DiesCreatureTriggeredAbility(new ScryEffect(1), false)); // {4}{B}: Each opponent loses 2 life and you gain 2 life. Activate this ability only if there are four or more creature cards in your graveyard. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, - new LoseLifeOpponentsEffect(2), new ManaCostsImpl<>("{4}{B}"), new CardsInControllerGraveyardCondition(4, StaticFilters.FILTER_CARD_CREATURES)); - Effect effect = new GainLifeEffect(2); - effect.setText("and you gain 2 life"); - ability.addEffect(effect); + Ability ability = new ActivateIfConditionActivatedAbility( + new LoseLifeOpponentsEffect(2), new ManaCostsImpl<>("{4}{B}"), condition + ); + ability.addEffect(new GainLifeEffect(2).concatBy("and")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/ShaileDeanOfRadiance.java b/Mage.Sets/src/mage/cards/s/ShaileDeanOfRadiance.java index a825384c496..50e56b506c4 100644 --- a/Mage.Sets/src/mage/cards/s/ShaileDeanOfRadiance.java +++ b/Mage.Sets/src/mage/cards/s/ShaileDeanOfRadiance.java @@ -24,6 +24,7 @@ import mage.filter.predicate.Predicate; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.permanent.EnteredThisTurnPredicate; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -72,7 +73,7 @@ public final class ShaileDeanOfRadiance extends ModalDoubleFacedCard { // {T}: Put a +1/+1 counter on another target creature, then Embrose, Dean of Shadow deals 2 damage to that creature. Ability ability = new SimpleActivatedAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()), new TapSourceCost()); ability.addEffect(new DamageTargetEffect(2).concatBy(", then").setText("{this} deals 2 damage to that creature")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.getRightHalfCard().addAbility(ability); // Whenever a creature you control with a +1/+1 counter on it dies, draw a card. @@ -87,4 +88,4 @@ public final class ShaileDeanOfRadiance extends ModalDoubleFacedCard { public ShaileDeanOfRadiance copy() { return new ShaileDeanOfRadiance(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/s/ShamanOfForgottenWays.java b/Mage.Sets/src/mage/cards/s/ShamanOfForgottenWays.java index 0743bbb71b6..482e2c26527 100644 --- a/Mage.Sets/src/mage/cards/s/ShamanOfForgottenWays.java +++ b/Mage.Sets/src/mage/cards/s/ShamanOfForgottenWays.java @@ -1,14 +1,9 @@ - package mage.cards.s; -import java.util.UUID; import mage.ConditionalMana; import mage.MageInt; -import mage.MageObject; -import mage.Mana; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; -import mage.abilities.condition.Condition; import mage.abilities.condition.common.FormidableCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; @@ -20,40 +15,36 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AbilityWord; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.SubType; import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; -import mage.game.stack.Spell; import mage.players.Player; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class ShamanOfForgottenWays extends CardImpl { public ShamanOfForgottenWays(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.SHAMAN); - this.power = new MageInt( 2); + this.power = new MageInt(2); this.toughness = new MageInt(3); // {T}:Add two mana in any combination of colors. Spend this mana only to cast creature spells. this.addAbility(new ConditionalAnyColorManaAbility(2, new ShamanOfForgottenWaysManaBuilder())); - + // Formidable — {9}{G}{G},{T}:Each player's life total becomes the number of creatures they control. Activate the ability only if creatures you control have total power 8 or greater. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, - new ShamanOfForgottenWaysEffect(), - new ManaCostsImpl<>("{9}{G}{G}"), - FormidableCondition.instance); + new ShamanOfForgottenWaysEffect(), new ManaCostsImpl<>("{9}{G}{G}"), FormidableCondition.instance + ); ability.addCost(new TapSourceCost()); - ability.setAbilityWord(AbilityWord.FORMIDABLE); - this.addAbility(ability); + this.addAbility(ability.setAbilityWord(AbilityWord.FORMIDABLE)); } private ShamanOfForgottenWays(final ShamanOfForgottenWays card) { @@ -80,29 +71,29 @@ class ShamanOfForgottenWaysManaBuilder extends ConditionalManaBuilder { } class ShamanOfForgottenWaysEffect extends OneShotEffect { - + public ShamanOfForgottenWaysEffect() { super(Outcome.Benefit); this.staticText = "each player's life total becomes the number of creatures they control"; } - + private ShamanOfForgottenWaysEffect(final ShamanOfForgottenWaysEffect effect) { super(effect); } - + @Override public ShamanOfForgottenWaysEffect copy() { return new ShamanOfForgottenWaysEffect(this); } - + @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { FilterPermanent filter = new FilterCreaturePermanent(); - 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 numberCreatures = game.getBattlefield().getAllActivePermanents(filter, playerId, game).size(); player.setLife(numberCreatures, game, source); } diff --git a/Mage.Sets/src/mage/cards/s/ShamblingGoblin.java b/Mage.Sets/src/mage/cards/s/ShamblingGoblin.java index 4b6137c2fc8..1a474fb4edb 100644 --- a/Mage.Sets/src/mage/cards/s/ShamblingGoblin.java +++ b/Mage.Sets/src/mage/cards/s/ShamblingGoblin.java @@ -12,8 +12,11 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Duration; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -29,7 +32,7 @@ public final class ShamblingGoblin extends CardImpl { // When Shambling Goblin dies, target creature an opponent controls gets -1/-1 until end of turn. Ability ability = new DiesSourceTriggeredAbility(new BoostTargetEffect(-1,-1, Duration.EndOfTurn)); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/ShardOfTheNightbringer.java b/Mage.Sets/src/mage/cards/s/ShardOfTheNightbringer.java index 084e52c4b16..04e66dc53b7 100644 --- a/Mage.Sets/src/mage/cards/s/ShardOfTheNightbringer.java +++ b/Mage.Sets/src/mage/cards/s/ShardOfTheNightbringer.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromEverywhereSourceCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -34,12 +33,8 @@ public final class ShardOfTheNightbringer extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Drain Life -- When Shard of the Nightbringer enters the battlefield, if you cast it, target opponent loses half their life, rounded up. You gain life equal to the life lost this way. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new ShardOfTheNightbringerEffect()), - CastFromEverywhereSourceCondition.instance, "When {this} enters, " + - "if you cast it, target opponent loses half their life, rounded up. " + - "You gain life equal to the life lost this way." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new ShardOfTheNightbringerEffect()) + .withInterveningIf(CastFromEverywhereSourceCondition.instance); ability.addTarget(new TargetOpponent()); this.addAbility(ability.withFlavorWord("Drain Life")); } @@ -58,6 +53,7 @@ class ShardOfTheNightbringerEffect extends OneShotEffect { ShardOfTheNightbringerEffect() { super(Outcome.Benefit); + staticText = "target opponent loses half their life, rounded up. You gain life equal to the life lost this way"; } private ShardOfTheNightbringerEffect(final ShardOfTheNightbringerEffect effect) { diff --git a/Mage.Sets/src/mage/cards/s/ShardPhoenix.java b/Mage.Sets/src/mage/cards/s/ShardPhoenix.java index 8fe4588d762..664775afc9b 100644 --- a/Mage.Sets/src/mage/cards/s/ShardPhoenix.java +++ b/Mage.Sets/src/mage/cards/s/ShardPhoenix.java @@ -1,13 +1,11 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DamageAllEffect; import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect; import mage.abilities.keyword.FlyingAbility; @@ -15,18 +13,18 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.PhaseStep; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; +import java.util.UUID; + /** - * * @author fireshoes */ public final class ShardPhoenix extends CardImpl { - + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature without flying"); static { @@ -34,20 +32,22 @@ public final class ShardPhoenix extends CardImpl { } public ShardPhoenix(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}"); this.subtype.add(SubType.PHOENIX); this.power = new MageInt(2); this.toughness = new MageInt(2); // Flying this.addAbility(FlyingAbility.getInstance()); - + // Sacrifice Shard Phoenix: Shard Phoenix deals 2 damage to each creature without flying. this.addAbility(new SimpleActivatedAbility(new DamageAllEffect(2, "it", filter), new SacrificeSourceCost())); - + // {R}{R}{R}: Return Shard Phoenix from your graveyard to your hand. Activate this ability only during your upkeep. - this.addAbility(new ConditionalActivatedAbility(Zone.GRAVEYARD, - new ReturnSourceFromGraveyardToHandEffect(), new ManaCostsImpl<>("{R}{R}{R}"), new IsStepCondition(PhaseStep.UPKEEP), null)); + this.addAbility(new ActivateIfConditionActivatedAbility( + Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(), + new ManaCostsImpl<>("{R}{R}{R}"), IsStepCondition.getMyUpkeep() + )); } private ShardPhoenix(final ShardPhoenix card) { diff --git a/Mage.Sets/src/mage/cards/s/SharedDiscovery.java b/Mage.Sets/src/mage/cards/s/SharedDiscovery.java index c3d2d72d5d7..4f30bdc11ca 100644 --- a/Mage.Sets/src/mage/cards/s/SharedDiscovery.java +++ b/Mage.Sets/src/mage/cards/s/SharedDiscovery.java @@ -1,36 +1,27 @@ - package mage.cards.s; -import java.util.UUID; import mage.abilities.costs.common.TapTargetCost; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.filter.StaticFilters; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class SharedDiscovery extends CardImpl { - - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); - - static { - filter.add(TappedPredicate.UNTAPPED); - } public SharedDiscovery(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{U}"); - + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{U}"); // As an additional cost to cast Shared Discovery, tap four untapped creatures you control. + this.getSpellAbility().addCost(new TapTargetCost(4, StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURES)); + // Draw three cards. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(3)); - this.getSpellAbility().addCost(new TapTargetCost(new TargetControlledCreaturePermanent(4, 4, filter, true))); } private SharedDiscovery(final SharedDiscovery card) { diff --git a/Mage.Sets/src/mage/cards/s/SharkTyphoon.java b/Mage.Sets/src/mage/cards/s/SharkTyphoon.java index 97e6883c30a..5e853ee68c9 100644 --- a/Mage.Sets/src/mage/cards/s/SharkTyphoon.java +++ b/Mage.Sets/src/mage/cards/s/SharkTyphoon.java @@ -1,25 +1,20 @@ package mage.cards.s; import mage.abilities.Ability; +import mage.abilities.common.CycleTriggeredAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; -import mage.abilities.common.ZoneChangeTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.CyclingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SetTargetPointer; -import mage.constants.Zone; import mage.filter.StaticFilters; import mage.game.Game; -import mage.game.events.GameEvent; import mage.game.permanent.token.SharkToken; import mage.game.stack.Spell; -import mage.game.stack.StackObject; -import mage.util.CardUtil; import java.util.UUID; @@ -42,7 +37,7 @@ public final class SharkTyphoon extends CardImpl { this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{X}{1}{U}"))); // When you cycle Shark Typhoon, create an X/X blue Shark creature token with flying. - this.addAbility(new SharkTyphoonTriggeredAbility()); + this.addAbility(new CycleTriggeredAbility(new SharkTyphoonCycleEffect())); } private SharkTyphoon(final SharkTyphoon card) { @@ -82,42 +77,29 @@ class SharkTyphoonCastEffect extends OneShotEffect { } } -class SharkTyphoonTriggeredAbility extends ZoneChangeTriggeredAbility { +class SharkTyphoonCycleEffect extends OneShotEffect { - SharkTyphoonTriggeredAbility() { - super(Zone.ALL, null, "", false); + SharkTyphoonCycleEffect() { + super(Outcome.Benefit); + staticText = "create an X/X blue Shark creature token with flying"; } - private SharkTyphoonTriggeredAbility(SharkTyphoonTriggeredAbility ability) { - super(ability); + private SharkTyphoonCycleEffect(final SharkTyphoonCycleEffect effect) { + super(effect); } @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ACTIVATED_ABILITY; + public SharkTyphoonCycleEffect copy() { + return new SharkTyphoonCycleEffect(this); } @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (!event.getSourceId().equals(this.getSourceId())) { - return false; + public boolean apply(Game game, Ability source) { + Object xValueObject = getValue("cycleXValue"); + int xValue = 0; + if (xValueObject instanceof Integer) { + xValue = (int) xValueObject; } - StackObject object = game.getStack().getStackObject(event.getSourceId()); - if (object == null || !(object.getStackAbility() instanceof CyclingAbility)) { - return false; - } - this.getEffects().clear(); - this.addEffect(new CreateTokenEffect(new SharkToken(CardUtil.getSourceCostsTag(game, object.getStackAbility(), "X", 0)))); - return true; - } - - @Override - public SharkTyphoonTriggeredAbility copy() { - return new SharkTyphoonTriggeredAbility(this); - } - - @Override - public String getRule() { - return "When you cycle this card, create an X/X blue Shark creature token with flying."; + return new SharkToken(xValue).putOntoBattlefield(1, game, source, source.getControllerId()); } } diff --git a/Mage.Sets/src/mage/cards/s/ShatterskullCharger.java b/Mage.Sets/src/mage/cards/s/ShatterskullCharger.java index 626b8bac5a0..2ca8b1bde0f 100644 --- a/Mage.Sets/src/mage/cards/s/ShatterskullCharger.java +++ b/Mage.Sets/src/mage/cards/s/ShatterskullCharger.java @@ -1,18 +1,17 @@ package mage.cards.s; import mage.MageInt; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.KickedCondition; import mage.abilities.condition.common.SourceHasCounterCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.KickerAbility; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -26,8 +25,10 @@ import java.util.UUID; */ public final class ShatterskullCharger extends CardImpl { - private static final Condition condition - = new InvertCondition(new SourceHasCounterCondition(CounterType.P1P1, 1)); + private static final Condition condition = new InvertCondition( + new SourceHasCounterCondition(CounterType.P1P1), + "{this} doesn't have a +1/+1 counter on it" + ); public ShatterskullCharger(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{R}"); @@ -53,12 +54,8 @@ public final class ShatterskullCharger extends CardImpl { )); // At the beginning of your end step, if Shatterskull Charger doesn't have a +1/+1 counter on it, return it to its owner's hand. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - new ReturnToHandSourceEffect(true) - ), condition, "At the beginning of your end step, " + - "if {this} doesn't have a +1/+1 counter on it, return it to its owner's hand." - )); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new ReturnToHandSourceEffect(true) + .setText("return it to its owner's hand")).withInterveningIf(condition)); } private ShatterskullCharger(final ShatterskullCharger card) { diff --git a/Mage.Sets/src/mage/cards/s/ShaukusMinion.java b/Mage.Sets/src/mage/cards/s/ShaukusMinion.java index e5bf360d0ca..9fc8c2fdcec 100644 --- a/Mage.Sets/src/mage/cards/s/ShaukusMinion.java +++ b/Mage.Sets/src/mage/cards/s/ShaukusMinion.java @@ -16,6 +16,7 @@ import mage.constants.CardType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -41,7 +42,7 @@ public final class ShaukusMinion extends CardImpl { // {B}{R}, {tap}: Shauku's Minion deals 2 damage to target white creature. Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(2), new ManaCostsImpl<>("{B}{R}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SheerDrop.java b/Mage.Sets/src/mage/cards/s/SheerDrop.java index 105adfa8300..173031379d7 100644 --- a/Mage.Sets/src/mage/cards/s/SheerDrop.java +++ b/Mage.Sets/src/mage/cards/s/SheerDrop.java @@ -9,6 +9,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -28,7 +29,7 @@ public final class SheerDrop extends CardImpl { // Destroy target tapped creature. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // Awaken 3-{5}{W} (If you cast this spell for {5}{W}, also put three +1/+1 counters on target land you control and it becomes a 0/0 Elemental creature with haste. It's still a land.) this.addAbility(new AwakenAbility(this, 3, "{5}{W}")); diff --git a/Mage.Sets/src/mage/cards/s/ShellSkulkin.java b/Mage.Sets/src/mage/cards/s/ShellSkulkin.java index 216337992b3..ba563ac5e19 100644 --- a/Mage.Sets/src/mage/cards/s/ShellSkulkin.java +++ b/Mage.Sets/src/mage/cards/s/ShellSkulkin.java @@ -17,6 +17,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -36,7 +37,7 @@ public final class ShellSkulkin extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(2); Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(ShroudAbility.getInstance(), Duration.EndOfTurn), new GenericManaCost(3)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/ShelteredValley.java b/Mage.Sets/src/mage/cards/s/ShelteredValley.java index dce04980f72..1b545262731 100644 --- a/Mage.Sets/src/mage/cards/s/ShelteredValley.java +++ b/Mage.Sets/src/mage/cards/s/ShelteredValley.java @@ -1,53 +1,53 @@ - package mage.cards.s; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.common.SacrificeAllCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.EnterBattlefieldPayCostOrPutGraveyardEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.mana.ColorlessManaAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.Zone; import mage.filter.FilterPermanent; -import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledLandPermanent; import mage.filter.predicate.mageobject.NamePredicate; +import java.util.UUID; + /** - * * @author anonymous */ public final class ShelteredValley extends CardImpl { - private static final FilterPermanent filterShelteredValley = new FilterPermanent("permanent named Sheltered Valley"); + private static final FilterPermanent filter = new FilterPermanent("permanent named Sheltered Valley"); static { - filterShelteredValley.add(new NamePredicate("Sheltered Valley")); + filter.add(new NamePredicate("Sheltered Valley")); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledLandPermanent("you control three or fewer lands"), + ComparisonType.FEWER_THAN, 4 + ); + public ShelteredValley(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.LAND},""); + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); // If Sheltered Valley would enter the battlefield, instead sacrifice each other permanent named Sheltered Valley you control, then put Sheltered Valley onto the battlefield. - Effect effect = new EnterBattlefieldPayCostOrPutGraveyardEffect(new SacrificeAllCost(filterShelteredValley)); - effect.setText("If {this} would enter the battlefield, instead sacrifice each other permanent named {this} you control, then put {this} onto the battlefield."); - Ability ability = new SimpleStaticAbility(Zone.ALL, effect); - this.addAbility(ability); + this.addAbility(new SimpleStaticAbility( + Zone.ALL, new EnterBattlefieldPayCostOrPutGraveyardEffect(new SacrificeAllCost(filter)) + .setText("If {this} would enter, instead sacrifice each other permanent " + + "named Sheltered Valley you control, then put {this} onto the battlefield.") + )); // At the beginning of your upkeep, if you control three or fewer lands, you gain 1 life. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new GainLifeEffect(1)), - new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_LANDS, ComparisonType.FEWER_THAN, 4), - "At the beginning of your upkeep, if you control three or fewer lands, you gain 1 life." - )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new GainLifeEffect(1)).withInterveningIf(condition)); + // {tap}: Add {C}. this.addAbility(new ColorlessManaAbility()); } diff --git a/Mage.Sets/src/mage/cards/s/ShelteringAncient.java b/Mage.Sets/src/mage/cards/s/ShelteringAncient.java index a5c2d0743a8..7ecef3f4631 100644 --- a/Mage.Sets/src/mage/cards/s/ShelteringAncient.java +++ b/Mage.Sets/src/mage/cards/s/ShelteringAncient.java @@ -11,14 +11,13 @@ 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.common.FilterCreaturePermanent; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; -import mage.target.common.TargetCreaturePermanent; +import mage.target.common.TargetOpponentsCreaturePermanent; import java.util.UUID; @@ -52,12 +51,6 @@ public final class ShelteringAncient extends CardImpl { class ShelteringAncientCost extends CostImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); - - static { - filter.add(TargetController.OPPONENT.getControllerPredicate()); - } - ShelteringAncientCost() { this.text = "Put a +1/+1 counter on a creature an opponent controls"; } @@ -70,7 +63,8 @@ class ShelteringAncientCost extends CostImpl { public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) { Player controller = game.getPlayer(controllerId); if (controller != null) { - Target target = new TargetCreaturePermanent(1, 1, filter, true); + Target target = new TargetOpponentsCreaturePermanent(); + target.withNotTarget(true); if (target.choose(Outcome.BoostCreature, controllerId, source.getSourceId(), source, game)) { Permanent permanent = game.getPermanent(target.getFirstTarget()); if (permanent != null) { @@ -85,7 +79,7 @@ class ShelteringAncientCost extends CostImpl { @Override public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) { - return game.getBattlefield().contains(filter, source, game, 1); + return game.getBattlefield().contains(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE, source, game, 1); } @Override diff --git a/Mage.Sets/src/mage/cards/s/Sheoldred.java b/Mage.Sets/src/mage/cards/s/Sheoldred.java index 2f03cac8bcf..49f1aad0ef4 100644 --- a/Mage.Sets/src/mage/cards/s/Sheoldred.java +++ b/Mage.Sets/src/mage/cards/s/Sheoldred.java @@ -4,7 +4,7 @@ import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CardsInOpponentGraveyardCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.ExileAndReturnSourceEffect; import mage.abilities.effects.common.SacrificeOpponentsEffect; import mage.abilities.keyword.MenaceAbility; @@ -48,7 +48,7 @@ public final class Sheoldred extends CardImpl { // {4}{B}: Exile Sheoldred, then return it to the battlefield transformed under its owner's control. Activate only as a sorcery and only if an opponent has eight or more cards in their graveyard. this.addAbility(new TransformAbility()); - this.addAbility(new ConditionalActivatedAbility( + this.addAbility(new ActivateIfConditionActivatedAbility( new ExileAndReturnSourceEffect(PutCards.BATTLEFIELD_TRANSFORMED), new ManaCostsImpl<>("{4}{B}"), CardsInOpponentGraveyardCondition.EIGHT ).setTiming(TimingRule.SORCERY).addHint(CardsInOpponentGraveyardCondition.EIGHT.getHint())); diff --git a/Mage.Sets/src/mage/cards/s/ShieldBroker.java b/Mage.Sets/src/mage/cards/s/ShieldBroker.java index 57327cfb91b..b8589726155 100644 --- a/Mage.Sets/src/mage/cards/s/ShieldBroker.java +++ b/Mage.Sets/src/mage/cards/s/ShieldBroker.java @@ -17,6 +17,7 @@ import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CommanderPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -47,7 +48,7 @@ public class ShieldBroker extends CardImpl { gainControlEffect.setText("You gain control of that creature for as long as it has a shield counter on it. " + "(If it would be dealt damage or destroyed, remove a shield counter from it instead.)"); etbAbility.addEffect(gainControlEffect); - etbAbility.addTarget(new TargetCreaturePermanent(filter)); + etbAbility.addTarget(new TargetPermanent(filter)); this.addAbility(etbAbility); } diff --git a/Mage.Sets/src/mage/cards/s/ShiftingGrift.java b/Mage.Sets/src/mage/cards/s/ShiftingGrift.java index ac26c1d043b..b01634609ca 100644 --- a/Mage.Sets/src/mage/cards/s/ShiftingGrift.java +++ b/Mage.Sets/src/mage/cards/s/ShiftingGrift.java @@ -22,7 +22,6 @@ public final class ShiftingGrift extends CardImpl { public ShiftingGrift(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{U}{U}"); - // Spree this.addAbility(new SpreeAbility(this)); diff --git a/Mage.Sets/src/mage/cards/s/ShiftingWoodland.java b/Mage.Sets/src/mage/cards/s/ShiftingWoodland.java index b38ec519e59..666139b3a63 100644 --- a/Mage.Sets/src/mage/cards/s/ShiftingWoodland.java +++ b/Mage.Sets/src/mage/cards/s/ShiftingWoodland.java @@ -5,14 +5,13 @@ import mage.abilities.common.EntersBattlefieldTappedUnlessAbility; import mage.abilities.condition.common.DeliriumCondition; import mage.abilities.condition.common.YouControlPermanentCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.effects.OneShotEffect; import mage.abilities.mana.GreenManaAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.ModalDoubleFacedCard; import mage.constants.*; import mage.filter.FilterCard; import mage.filter.FilterPermanent; @@ -47,7 +46,7 @@ public final class ShiftingWoodland extends CardImpl { this.addAbility(new GreenManaAbility()); // Delirium -- {2}{G}{G}: Shifting Woodland becomes a copy of target permanent card in your graveyard until end of turn. Activate only if there are four or more card types among cards in your graveyard. - Ability ability = new ConditionalActivatedAbility( + Ability ability = new ActivateIfConditionActivatedAbility( new ShiftingWoodlandCopyEffect(), new ManaCostsImpl<>("{2}{G}{G}"), DeliriumCondition.instance @@ -97,4 +96,4 @@ class ShiftingWoodlandCopyEffect extends OneShotEffect { game.copyPermanent(Duration.EndOfTurn, blueprint, sourcePermanent.getId(), source, new EmptyCopyApplier()); return true; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/s/ShimianNightStalker.java b/Mage.Sets/src/mage/cards/s/ShimianNightStalker.java index 2dcf1f9f60c..8d841cf5656 100644 --- a/Mage.Sets/src/mage/cards/s/ShimianNightStalker.java +++ b/Mage.Sets/src/mage/cards/s/ShimianNightStalker.java @@ -43,7 +43,7 @@ public final class ShimianNightStalker extends CardImpl { // {B}, {T}: All damage that would be dealt to you this turn by target attacking creature is dealt to Shimian Night Stalker instead. Ability ability = new SimpleActivatedAbility(new ShimianNightStalkerRedirectDamageEffect(), new ManaCostsImpl<>("{B}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/ShimmerDragon.java b/Mage.Sets/src/mage/cards/s/ShimmerDragon.java index 9ae87af2f08..c081b3b5e3f 100644 --- a/Mage.Sets/src/mage/cards/s/ShimmerDragon.java +++ b/Mage.Sets/src/mage/cards/s/ShimmerDragon.java @@ -7,10 +7,9 @@ import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.common.TapTargetCost; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; -import mage.abilities.hint.ValueHint; +import mage.abilities.hint.common.ArtifactYouControlHint; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.HexproofAbility; import mage.cards.CardImpl; @@ -57,7 +56,7 @@ public final class ShimmerDragon extends CardImpl { new GainAbilitySourceEffect( HexproofAbility.getInstance(), Duration.WhileOnBattlefield ), condition, "as long as you control four or more artifacts, {this} has hexproof" - )).addHint(new ValueHint("Artifacts you control", new PermanentsOnBattlefieldCount(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT)))); + )).addHint(ArtifactYouControlHint.instance)); // Tap two untapped artifacts you control: Draw a card. this.addAbility(new SimpleActivatedAbility( diff --git a/Mage.Sets/src/mage/cards/s/ShinryuTranscendentRival.java b/Mage.Sets/src/mage/cards/s/ShinryuTranscendentRival.java index 8775979f768..712dfdb3e7d 100644 --- a/Mage.Sets/src/mage/cards/s/ShinryuTranscendentRival.java +++ b/Mage.Sets/src/mage/cards/s/ShinryuTranscendentRival.java @@ -16,6 +16,7 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPlayer; import mage.target.common.TargetOpponent; +import mage.util.CardUtil; import java.util.Optional; import java.util.UUID; @@ -86,6 +87,7 @@ class ShinryuTranscendentRivalEffect extends ReplacementEffectImpl { } game.informPlayers(permanent.getName() + ": " + controller.getLogName() + " has chosen " + opponent.getLogName()); game.getState().setValue(permanent.getId() + "_" + permanent.getZoneChangeCounter(game) + "_opponent", opponent.getId()); + permanent.addInfo("chosen opponent", CardUtil.addToolTipMarkTags("Chosen Opponent " + opponent.getLogName()), game); return false; } diff --git a/Mage.Sets/src/mage/cards/s/ShipwreckLooter.java b/Mage.Sets/src/mage/cards/s/ShipwreckLooter.java index 6554a283d52..ea1566702b3 100644 --- a/Mage.Sets/src/mage/cards/s/ShipwreckLooter.java +++ b/Mage.Sets/src/mage/cards/s/ShipwreckLooter.java @@ -1,10 +1,8 @@ package mage.cards.s; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawDiscardControllerEffect; import mage.abilities.hint.common.RaidHint; import mage.cards.CardImpl; @@ -30,12 +28,9 @@ public final class ShipwreckLooter extends CardImpl { this.toughness = new MageInt(1); // Raid - When Shipwreck Looter enters the battlefield,if you attacked this turn, you may draw a card. If you do, discard a card. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DrawDiscardControllerEffect(1, 1, true)), - RaidCondition.instance, "When {this} enters, if you attacked this turn, you may draw a card. If you do, discard a card."); - ability.setAbilityWord(AbilityWord.RAID); - ability.addHint(RaidHint.instance); - this.addAbility(ability, new PlayerAttackedWatcher()); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new DrawDiscardControllerEffect(1, 1, true) + ).withInterveningIf(RaidCondition.instance).setAbilityWord(AbilityWord.RAID).addHint(RaidHint.instance), new PlayerAttackedWatcher()); } private ShipwreckLooter(final ShipwreckLooter card) { diff --git a/Mage.Sets/src/mage/cards/s/ShipwreckSinger.java b/Mage.Sets/src/mage/cards/s/ShipwreckSinger.java index f2c1eb321b2..8db43f3430b 100644 --- a/Mage.Sets/src/mage/cards/s/ShipwreckSinger.java +++ b/Mage.Sets/src/mage/cards/s/ShipwreckSinger.java @@ -16,8 +16,11 @@ import mage.constants.SubType; import mage.constants.Duration; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -35,7 +38,7 @@ public final class ShipwreckSinger extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // {1}{U}: Target creature an opponent controls attacks this turn if able. Ability ability = new SimpleActivatedAbility(new AttacksIfAbleTargetEffect(Duration.EndOfTurn), new ManaCostsImpl<>("{1}{U}")); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); // {1}{B}, {T}: Attacking creatures get -1/-1 until end of turn. ability = new SimpleActivatedAbility(new BoostAllEffect(-1,-1, Duration.EndOfTurn, StaticFilters.FILTER_ATTACKING_CREATURES, false), new ManaCostsImpl<>("{1}{B}")); diff --git a/Mage.Sets/src/mage/cards/s/ShivanEmissary.java b/Mage.Sets/src/mage/cards/s/ShivanEmissary.java index 81b3324fd03..77c75594652 100644 --- a/Mage.Sets/src/mage/cards/s/ShivanEmissary.java +++ b/Mage.Sets/src/mage/cards/s/ShivanEmissary.java @@ -1,11 +1,9 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -13,17 +11,20 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; -/** - * - * @author LoneFox +import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + +/** + * @author LoneFox */ public final class ShivanEmissary extends CardImpl { public ShivanEmissary(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WIZARD); this.power = new MageInt(1); @@ -31,11 +32,11 @@ public final class ShivanEmissary extends CardImpl { // Kicker {1}{B} this.addAbility(new KickerAbility("{1}{B}")); + // When Shivan Emissary enters the battlefield, if it was kicked, destroy target nonblack creature. It can't be regenerated. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(true)); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.ONCE, - "When {this} enters, if it was kicked, destroy target nonblack creature. It can't be regenerated.")); + Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(true)).withInterveningIf(KickedCondition.ONCE); + ability.addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.addAbility(ability); } private ShivanEmissary(final ShivanEmissary card) { diff --git a/Mage.Sets/src/mage/cards/s/ShorelineSalvager.java b/Mage.Sets/src/mage/cards/s/ShorelineSalvager.java index 38ad087b989..9270605cec6 100644 --- a/Mage.Sets/src/mage/cards/s/ShorelineSalvager.java +++ b/Mage.Sets/src/mage/cards/s/ShorelineSalvager.java @@ -1,42 +1,38 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +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.constants.TargetController; -import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class ShorelineSalvager extends CardImpl { - private static final String rule = "Whenever Shoreline Salvager deals combat damage to a player, if you control an Island, you may draw a card."; - private static final FilterPermanent filter = new FilterPermanent("Island"); - - static { - filter.add(TargetController.YOU.getControllerPredicate()); - filter.add(SubType.ISLAND.getPredicate()); - } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPermanent(SubType.ISLAND, "you control an Island") + ); public ShorelineSalvager(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.SURRAKAR); this.power = new MageInt(3); this.toughness = new MageInt(3); // Whenever Shoreline Salvager deals combat damage to a player, if you control an Island, you may draw a card. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new DrawCardSourceControllerEffect(1), true), new PermanentsOnTheBattlefieldCondition(filter), rule)); + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility( + new DrawCardSourceControllerEffect(1), true + ).withInterveningIf(condition)); } private ShorelineSalvager(final ShorelineSalvager card) { diff --git a/Mage.Sets/src/mage/cards/s/Showstopper.java b/Mage.Sets/src/mage/cards/s/Showstopper.java index 8022d15ff01..23cad696a3b 100644 --- a/Mage.Sets/src/mage/cards/s/Showstopper.java +++ b/Mage.Sets/src/mage/cards/s/Showstopper.java @@ -12,8 +12,11 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.filter.StaticFilters; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -27,7 +30,7 @@ public final class Showstopper extends CardImpl { // 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 DiesSourceTriggeredAbility(new DamageTargetEffect(2, "it"), false); - Target target = new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE); + Target target = new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE); ability.addTarget(target); Effect effect = new GainAbilityControlledEffect(ability, Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURES); effect.setText("Until end of turn, creatures you control gain \"When this creature dies, it deals 2 damage to target creature an opponent controls.\""); diff --git a/Mage.Sets/src/mage/cards/s/ShreddingWinds.java b/Mage.Sets/src/mage/cards/s/ShreddingWinds.java index dc1ac4f1751..90d61a2adb1 100644 --- a/Mage.Sets/src/mage/cards/s/ShreddingWinds.java +++ b/Mage.Sets/src/mage/cards/s/ShreddingWinds.java @@ -10,6 +10,7 @@ import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -29,7 +30,7 @@ public final class ShreddingWinds extends CardImpl { // Shredding Winds deals 7 damage to target creature with flying. this.getSpellAbility().addEffect(new DamageTargetEffect(7)); - Target target = new TargetCreaturePermanent(filter); + Target target = new TargetPermanent(filter); this.getSpellAbility().addTarget(target); } diff --git a/Mage.Sets/src/mage/cards/s/ShriekingAffliction.java b/Mage.Sets/src/mage/cards/s/ShriekingAffliction.java index 48f03a95d9a..13988100edf 100644 --- a/Mage.Sets/src/mage/cards/s/ShriekingAffliction.java +++ b/Mage.Sets/src/mage/cards/s/ShriekingAffliction.java @@ -1,9 +1,9 @@ package mage.cards.s; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInHandCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.LoseLifeTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -19,18 +19,15 @@ import java.util.UUID; public final class ShriekingAffliction extends CardImpl { + private static final Condition condition = new CardsInHandCondition(ComparisonType.FEWER_THAN, 2, TargetController.ACTIVE); + public ShriekingAffliction(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{B}"); // At the beginning of each opponent's upkeep, if that player has one or fewer cards in hand, they lose 3 life. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility( - Zone.BATTLEFIELD, TargetController.OPPONENT, new LoseLifeTargetEffect(3), - false - ), - new CardsInHandCondition(ComparisonType.FEWER_THAN, 2, TargetController.ACTIVE), - "At the beginning of each opponent's upkeep, if that player has one or fewer cards in hand, they lose 3 life." - )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + Zone.BATTLEFIELD, TargetController.OPPONENT, new LoseLifeTargetEffect(3).setText("they lose 3 life"), false + ).withInterveningIf(condition)); } private ShriekingAffliction(final ShriekingAffliction card) { diff --git a/Mage.Sets/src/mage/cards/s/ShriekingGrotesque.java b/Mage.Sets/src/mage/cards/s/ShriekingGrotesque.java index 6838417befd..7a94f4e5de5 100644 --- a/Mage.Sets/src/mage/cards/s/ShriekingGrotesque.java +++ b/Mage.Sets/src/mage/cards/s/ShriekingGrotesque.java @@ -1,41 +1,37 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.ManaWasSpentCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.ColoredManaSymbol; import mage.target.TargetPlayer; -/** - * - * @author LoneFox +import java.util.UUID; +/** + * @author LoneFox */ public final class ShriekingGrotesque extends CardImpl { public ShriekingGrotesque(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.GARGOYLE); this.power = new MageInt(2); this.toughness = new MageInt(1); // Flying this.addAbility(FlyingAbility.getInstance()); + // When Shrieking Grotesque enters the battlefield, if {B} was spent to cast it, target player discards a card. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(1), false); + Ability ability = new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(1)).withInterveningIf(ManaWasSpentCondition.BLACK); ability.addTarget(new TargetPlayer()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, ManaWasSpentCondition.BLACK, - "When {this} enters, if {B} was spent to cast it, target player discards a card.")); + this.addAbility(ability); } private ShriekingGrotesque(final ShriekingGrotesque card) { diff --git a/Mage.Sets/src/mage/cards/s/Shriekmaw.java b/Mage.Sets/src/mage/cards/s/Shriekmaw.java index f8d144380a1..ac0eea14dcb 100644 --- a/Mage.Sets/src/mage/cards/s/Shriekmaw.java +++ b/Mage.Sets/src/mage/cards/s/Shriekmaw.java @@ -17,6 +17,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -44,7 +45,7 @@ public final class Shriekmaw extends CardImpl { // When Shriekmaw enters the battlefield, destroy target nonartifact, nonblack creature. Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(),false); - Target target = new TargetCreaturePermanent(filter); + Target target = new TargetPermanent(filter); ability.addTarget(target); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/s/ShrikeHarpy.java b/Mage.Sets/src/mage/cards/s/ShrikeHarpy.java index d42df20b9c5..56e650c90e5 100644 --- a/Mage.Sets/src/mage/cards/s/ShrikeHarpy.java +++ b/Mage.Sets/src/mage/cards/s/ShrikeHarpy.java @@ -1,12 +1,9 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TributeNotPaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SacrificeEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.TributeAbility; @@ -17,14 +14,15 @@ import mage.constants.SubType; import mage.filter.StaticFilters; import mage.target.common.TargetOpponent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class ShrikeHarpy extends CardImpl { public ShrikeHarpy(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.HARPY); this.power = new MageInt(2); @@ -37,10 +35,11 @@ public final class ShrikeHarpy extends CardImpl { this.addAbility(new TributeAbility(2)); // When Shrike Harpy enters the battlefield, if tribute wasn't paid, target opponent sacrifices a creature. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new SacrificeEffect(StaticFilters.FILTER_PERMANENT_A_CREATURE, 1, "target opponent"), false); + Ability ability = new EntersBattlefieldTriggeredAbility(new SacrificeEffect( + StaticFilters.FILTER_PERMANENT_A_CREATURE, 1, "target opponent" + )).withInterveningIf(TributeNotPaidCondition.instance); ability.addTarget(new TargetOpponent()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TributeNotPaidCondition.instance, - "When {this} enters, if tribute wasn't paid, target opponent sacrifices a creature.")); + this.addAbility(ability); } private ShrikeHarpy(final ShrikeHarpy card) { diff --git a/Mage.Sets/src/mage/cards/s/ShuFarmer.java b/Mage.Sets/src/mage/cards/s/ShuFarmer.java index d3302121269..2c216554c1f 100644 --- a/Mage.Sets/src/mage/cards/s/ShuFarmer.java +++ b/Mage.Sets/src/mage/cards/s/ShuFarmer.java @@ -1,9 +1,6 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.common.MyTurnBeforeAttackersDeclaredCondition; import mage.abilities.costs.common.TapSourceCost; @@ -12,24 +9,24 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; + +import java.util.UUID; /** - * * @author fireshoes */ public final class ShuFarmer extends CardImpl { public ShuFarmer(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.power = new MageInt(1); this.toughness = new MageInt(1); // {tap}: You gain 1 life. Activate this ability only during your turn, before attackers are declared. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new GainLifeEffect(1), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); - this.addAbility(ability); + this.addAbility(new ActivateIfConditionActivatedAbility( + new GainLifeEffect(1), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance + )); } private ShuFarmer(final ShuFarmer card) { diff --git a/Mage.Sets/src/mage/cards/s/SickAndTired.java b/Mage.Sets/src/mage/cards/s/SickAndTired.java index 84b789d74fd..d57f9a2e661 100644 --- a/Mage.Sets/src/mage/cards/s/SickAndTired.java +++ b/Mage.Sets/src/mage/cards/s/SickAndTired.java @@ -1,7 +1,5 @@ - package mage.cards.s; -import java.util.UUID; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -9,15 +7,15 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author Plopman */ public final class SickAndTired extends CardImpl { public SickAndTired(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{B}"); - + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{B}"); // Two target creatures each get -1/-1 until end of turn. this.getSpellAbility().addEffect(new BoostTargetEffect(-1, -1, Duration.EndOfTurn)); diff --git a/Mage.Sets/src/mage/cards/s/SickleDancer.java b/Mage.Sets/src/mage/cards/s/SickleDancer.java index ab3a5a2e01e..336cbb92189 100644 --- a/Mage.Sets/src/mage/cards/s/SickleDancer.java +++ b/Mage.Sets/src/mage/cards/s/SickleDancer.java @@ -1,32 +1,34 @@ - package mage.cards.s; -import java.util.UUID; 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.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.SubType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterTeamPermanent; import mage.filter.predicate.mageobject.AnotherPredicate; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class SickleDancer extends CardImpl { - private static final FilterTeamPermanent filter = new FilterTeamPermanent(SubType.WARRIOR, "Warrior creature"); + private static final FilterPermanent filter = new FilterTeamPermanent(SubType.WARRIOR, "your team controls another Warrior"); static { filter.add(AnotherPredicate.instance); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, false); + public SickleDancer(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); @@ -36,11 +38,7 @@ public final class SickleDancer extends CardImpl { this.toughness = new MageInt(2); // Whenever Sickle Dancer attacks, if your team controls another Warrior, Sickle Dancer gets +1/+1 until end of turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new BoostSourceEffect(1, 1, Duration.EndOfTurn), false), - new PermanentsOnTheBattlefieldCondition(filter), - "Whenever {this} attacks, if your team controls another Warrior, {this} gets +1/+1 until end of turn." - )); + this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect(1, 1, Duration.EndOfTurn)).withInterveningIf(condition)); } private SickleDancer(final SickleDancer card) { diff --git a/Mage.Sets/src/mage/cards/s/SidarJabari.java b/Mage.Sets/src/mage/cards/s/SidarJabari.java index 9f8a8296c23..6793de24bf4 100644 --- a/Mage.Sets/src/mage/cards/s/SidarJabari.java +++ b/Mage.Sets/src/mage/cards/s/SidarJabari.java @@ -14,6 +14,7 @@ import mage.constants.SubType; import mage.constants.SuperType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.DefendingPlayerControlsSourceAttackingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class SidarJabari extends CardImpl { // Whenever Sidar Jabari attacks, tap target creature defending player controls. Ability ability = new AttacksTriggeredAbility(new TapTargetEffect(), false); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SidarJabariOfZhalfir.java b/Mage.Sets/src/mage/cards/s/SidarJabariOfZhalfir.java index 4637e7c0c48..d9074173f7c 100644 --- a/Mage.Sets/src/mage/cards/s/SidarJabariOfZhalfir.java +++ b/Mage.Sets/src/mage/cards/s/SidarJabariOfZhalfir.java @@ -5,7 +5,6 @@ import mage.abilities.Ability; import mage.abilities.common.AttacksWithCreaturesTriggeredAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.condition.common.SourceOnBattlefieldOrCommandZoneCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawDiscardControllerEffect; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.keyword.FirstStrikeAbility; @@ -13,6 +12,8 @@ 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.FilterCreatureCard; import mage.filter.common.FilterCreaturePermanent; import mage.target.common.TargetCardInYourGraveyard; @@ -24,8 +25,8 @@ import java.util.UUID; */ public final class SidarJabariOfZhalfir extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.KNIGHT, "Knights"); - private static final FilterCreatureCard filter2 = new FilterCreatureCard("Knight creature card from your graveyard"); + private static final FilterPermanent filter = new FilterCreaturePermanent(SubType.KNIGHT, "Knights"); + private static final FilterCard filter2 = new FilterCreatureCard("Knight creature card from your graveyard"); static { filter2.add(SubType.KNIGHT.getPredicate()); @@ -40,15 +41,9 @@ public final class SidarJabariOfZhalfir extends CardImpl { // Eminence — Whenever you attack with one or more Knights, if Sidar Jabari of Zhalfir // is in the command zone or on the battlefield, draw a card, then discard a card. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new AttacksWithCreaturesTriggeredAbility( - Zone.ALL, new DrawDiscardControllerEffect(), 1, filter - ), SourceOnBattlefieldOrCommandZoneCondition.instance, - "Whenever you attack with one or more Knights, if {this} is in the command" + - " zone or on the battlefield, draw a card, then discard a card" - ); - ability.setAbilityWord(AbilityWord.EMINENCE); - this.addAbility(ability); + this.addAbility(new AttacksWithCreaturesTriggeredAbility( + Zone.ALL, new DrawDiscardControllerEffect(), 1, filter + ).withInterveningIf(SourceOnBattlefieldOrCommandZoneCondition.instance).setAbilityWord(AbilityWord.EMINENCE)); // Flying this.addAbility(FlyingAbility.getInstance()); @@ -58,7 +53,7 @@ public final class SidarJabariOfZhalfir extends CardImpl { // Whenever Sidar Jabari deals combat damage to a player, return target // Knight creature card from your graveyard to the battlefield. - ability = new DealsCombatDamageToAPlayerTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect(), false); + Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect()); ability.addTarget(new TargetCardInYourGraveyard(filter2)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SidequestPlayBlitzball.java b/Mage.Sets/src/mage/cards/s/SidequestPlayBlitzball.java index 394e1f3b6e4..8720da23746 100644 --- a/Mage.Sets/src/mage/cards/s/SidequestPlayBlitzball.java +++ b/Mage.Sets/src/mage/cards/s/SidequestPlayBlitzball.java @@ -48,7 +48,7 @@ public final class SidequestPlayBlitzball extends CardImpl { this.addAbility(new TransformAbility()); ability = new EndOfCombatTriggeredAbility( new TransformSourceEffect(), TargetController.YOU, false - ).withInterveningIf(SidequestPlayBlitzballCondition.instance); + ).withInterveningIf(SidequestPlayBlitzballCondition.instance).setTriggerPhrase("At the end of combat on your turn, "); ability.addEffect(new SidequestPlayBlitzballEffect()); this.addAbility(ability, new SidequestPlayBlitzballWatcher()); } diff --git a/Mage.Sets/src/mage/cards/s/SiegeGangLieutenant.java b/Mage.Sets/src/mage/cards/s/SiegeGangLieutenant.java index fafe03614a8..da67fce3a3d 100644 --- a/Mage.Sets/src/mage/cards/s/SiegeGangLieutenant.java +++ b/Mage.Sets/src/mage/cards/s/SiegeGangLieutenant.java @@ -67,6 +67,7 @@ class SiegeGangLieutenantEffect extends OneShotEffect { SiegeGangLieutenantEffect() { super(Outcome.Benefit); + staticText = "create two 1/1 red Goblin creature tokens. Those tokens gain haste until end of turn"; } private SiegeGangLieutenantEffect(final SiegeGangLieutenantEffect effect) { diff --git a/Mage.Sets/src/mage/cards/s/SiegeStriker.java b/Mage.Sets/src/mage/cards/s/SiegeStriker.java index b1c7b928e93..666755d2a1e 100644 --- a/Mage.Sets/src/mage/cards/s/SiegeStriker.java +++ b/Mage.Sets/src/mage/cards/s/SiegeStriker.java @@ -8,12 +8,14 @@ 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.permanent.TappedPredicate; +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.permanent.Permanent; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -34,10 +36,7 @@ public final class SiegeStriker extends CardImpl { 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 - )); - + this.addAbility(new AttacksTriggeredAbility(new SiegeStrikerEffect(), true)); } private SiegeStriker(final SiegeStriker card) { @@ -52,13 +51,6 @@ public final class SiegeStriker extends CardImpl { class SiegeStrikerEffect extends OneShotEffect { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("untapped creatures you control"); - - static { - filter.add(TargetController.YOU.getControllerPredicate()); - filter.add(TappedPredicate.UNTAPPED); - } - public SiegeStrikerEffect() { super(Outcome.GainLife); staticText = "you may tap any number of untapped creatures you control. " @@ -72,15 +64,13 @@ class SiegeStrikerEffect extends OneShotEffect { @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(), source, game) - && target.choose(Outcome.Tap, source.getControllerId(), source.getSourceId(), source, game)) { - for (UUID creatureId : target.getTargets()) { - Permanent creature = game.getPermanent(creatureId); - if (creature != null) { - creature.tap(source, game); - tappedAmount++; - } + TargetPermanent target = new TargetPermanent(0, Integer.MAX_VALUE, StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURES, true); + target.choose(Outcome.Tap, source.getControllerId(), source.getSourceId(), source, game); + for (UUID creatureId : target.getTargets()) { + Permanent creature = game.getPermanent(creatureId); + if (creature != null) { + creature.tap(source, game); + tappedAmount++; } } if (tappedAmount > 0) { diff --git a/Mage.Sets/src/mage/cards/s/SigardaChampionOfLight.java b/Mage.Sets/src/mage/cards/s/SigardaChampionOfLight.java index cf5c3ded1d3..ddbd314d2b4 100644 --- a/Mage.Sets/src/mage/cards/s/SigardaChampionOfLight.java +++ b/Mage.Sets/src/mage/cards/s/SigardaChampionOfLight.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.CovenCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.hint.common.CovenHint; @@ -53,12 +52,9 @@ public final class SigardaChampionOfLight extends CardImpl { // Coven — Whenever Sigarda attacks, if you control three or more creatures with different powers, // look at the top five cards of your library. You may reveal a Human creature 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 ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new LookLibraryAndPickControllerEffect(5, 1, filter2, PutCards.HAND, PutCards.BOTTOM_RANDOM)), CovenCondition.instance, "Whenever {this} attacks, " + - "if you control three or more creatures with different powers, look at the top five cards " + - "of your library. You may reveal a Human creature card from among them and put it into your hand. " + - "Put the rest on the bottom of your library in a random order." - ).addHint(CovenHint.instance).setAbilityWord(AbilityWord.COVEN)); + this.addAbility(new AttacksTriggeredAbility(new LookLibraryAndPickControllerEffect( + 5, 1, filter2, PutCards.HAND, PutCards.BOTTOM_RANDOM + )).withInterveningIf(CovenCondition.instance).addHint(CovenHint.instance).setAbilityWord(AbilityWord.COVEN)); } private SigardaChampionOfLight(final SigardaChampionOfLight card) { diff --git a/Mage.Sets/src/mage/cards/s/SigardianPriest.java b/Mage.Sets/src/mage/cards/s/SigardianPriest.java index 16ebf8d4d88..99fa919a016 100644 --- a/Mage.Sets/src/mage/cards/s/SigardianPriest.java +++ b/Mage.Sets/src/mage/cards/s/SigardianPriest.java @@ -1,7 +1,5 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -12,13 +10,13 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class SigardianPriest extends CardImpl { @@ -30,7 +28,7 @@ public final class SigardianPriest extends CardImpl { } public SigardianPriest(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.CLERIC); this.power = new MageInt(1); @@ -39,7 +37,7 @@ public final class SigardianPriest extends CardImpl { // {1}, {T}: Tap target non-Human creature. Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new GenericManaCost(1)); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(1, 1, filter, false)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SigardianSavior.java b/Mage.Sets/src/mage/cards/s/SigardianSavior.java index 2537c68fe14..f7329c6df72 100644 --- a/Mage.Sets/src/mage/cards/s/SigardianSavior.java +++ b/Mage.Sets/src/mage/cards/s/SigardianSavior.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromEverywhereSourceCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -42,12 +41,8 @@ public final class SigardianSavior extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When Sigardian Savior enters the battlefield, if you cast it, return up to two target creature cards with mana value 2 or less from your graveyard to the battlefield. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect()), - CastFromEverywhereSourceCondition.instance, "When {this} enters, " + - "if you cast it, return up to two target creature cards with mana value " + - "2 or less from your graveyard to the battlefield." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect()) + .withInterveningIf(CastFromEverywhereSourceCondition.instance); ability.addTarget(new TargetCardInYourGraveyard(0, 2, filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SigilOfSleep.java b/Mage.Sets/src/mage/cards/s/SigilOfSleep.java index 7856263da01..eac14995734 100644 --- a/Mage.Sets/src/mage/cards/s/SigilOfSleep.java +++ b/Mage.Sets/src/mage/cards/s/SigilOfSleep.java @@ -39,7 +39,7 @@ public final class SigilOfSleep extends CardImpl { // Whenever enchanted creature deals damage to a player, return target creature that player controls to its owner's hand. Effect effect = new ReturnToHandTargetEffect(); ability = new DealsDamageToAPlayerAttachedTriggeredAbility(effect, "enchanted", false, true, false); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SigilTracer.java b/Mage.Sets/src/mage/cards/s/SigilTracer.java index 3d1ca28e199..39be752fe18 100644 --- a/Mage.Sets/src/mage/cards/s/SigilTracer.java +++ b/Mage.Sets/src/mage/cards/s/SigilTracer.java @@ -1,7 +1,5 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -12,27 +10,27 @@ 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.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.permanent.TappedPredicate; import mage.target.TargetSpell; -import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; /** * @author Loki */ public final class SigilTracer extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Wizards you control"); + private static final FilterControlledPermanent filter = new FilterControlledCreaturePermanent(SubType.WIZARD, "untapped Wizards you control"); static { filter.add(TappedPredicate.UNTAPPED); - filter.add(SubType.WIZARD.getPredicate()); } public SigilTracer(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{U}"); this.subtype.add(SubType.MERFOLK); this.subtype.add(SubType.WIZARD); @@ -42,7 +40,7 @@ public final class SigilTracer extends CardImpl { // {1}{U}, Tap two untapped Wizards you control: Copy target instant or sorcery spell. You may choose new targets for the copy. Ability ability = new SimpleActivatedAbility(new CopyTargetStackObjectEffect(), new ManaCostsImpl<>("{1}{U}")); ability.addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_INSTANT_OR_SORCERY)); - ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(2, 2, filter, false))); + ability.addCost(new TapTargetCost(2, filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SignatureSlam.java b/Mage.Sets/src/mage/cards/s/SignatureSlam.java index 792a6f86a86..51fd55fb010 100644 --- a/Mage.Sets/src/mage/cards/s/SignatureSlam.java +++ b/Mage.Sets/src/mage/cards/s/SignatureSlam.java @@ -14,12 +14,15 @@ import mage.filter.predicate.permanent.ModifiedPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.SecondTargetPointer; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author Susucr */ @@ -32,7 +35,7 @@ public final class SignatureSlam extends CardImpl { this.getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance())); this.getSpellAbility().addEffect(new SignatureSlamEffect().setTargetPointer(new SecondTargetPointer())); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); } private SignatureSlam(final SignatureSlam card) { diff --git a/Mage.Sets/src/mage/cards/s/SilumgarAssassin.java b/Mage.Sets/src/mage/cards/s/SilumgarAssassin.java index b5df7d8bec5..4e5536ac131 100644 --- a/Mage.Sets/src/mage/cards/s/SilumgarAssassin.java +++ b/Mage.Sets/src/mage/cards/s/SilumgarAssassin.java @@ -19,6 +19,7 @@ import mage.constants.TargetController; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -49,7 +50,7 @@ public final class SilumgarAssassin extends CardImpl { // When Silumgar Assassin is turned face up, destroy target creature with power 3 or less an opponent controls. Ability ability = new TurnedFaceUpSourceTriggeredAbility(new DestroyTargetEffect(), false); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SilversmoteGhoul.java b/Mage.Sets/src/mage/cards/s/SilversmoteGhoul.java index e9402b91165..2201dc939d1 100644 --- a/Mage.Sets/src/mage/cards/s/SilversmoteGhoul.java +++ b/Mage.Sets/src/mage/cards/s/SilversmoteGhoul.java @@ -2,17 +2,16 @@ package mage.cards.s; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.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.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -26,7 +25,7 @@ import java.util.UUID; 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"); + private static final Hint hint = new ConditionHint(condition); public SilversmoteGhoul(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); @@ -37,12 +36,10 @@ public final class SilversmoteGhoul extends CardImpl { 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, TargetController.YOU, new ReturnSourceFromGraveyardToBattlefieldEffect(true), - false, null - ), 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." + this.addAbility(new BeginningOfEndStepTriggeredAbility( + Zone.GRAVEYARD, TargetController.YOU, + new ReturnSourceFromGraveyardToBattlefieldEffect(true), + false, condition ).addHint(hint), new PlayerGainedLifeWatcher()); // {1}{B}, Sacrifice Silversmote Ghoul: Draw a card. diff --git a/Mage.Sets/src/mage/cards/s/SimicBasilisk.java b/Mage.Sets/src/mage/cards/s/SimicBasilisk.java index 67e5997661d..1415f80933d 100644 --- a/Mage.Sets/src/mage/cards/s/SimicBasilisk.java +++ b/Mage.Sets/src/mage/cards/s/SimicBasilisk.java @@ -20,8 +20,11 @@ import mage.constants.SubType; import mage.constants.Duration; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_A_CREATURE_P1P1; + /** * * @author JotaPeRL @@ -46,7 +49,7 @@ public final class SimicBasilisk extends CardImpl { new DealsDamageToACreatureTriggeredAbility(effect, true, false, true), Duration.EndOfTurn) .setText("Until end of turn, target creature with a +1/+1 counter on it gains \"Whenever this creature deals combat damage to a creature, destroy that creature at end of combat.\""), new ManaCostsImpl<>("{1}{G}")); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_A_CREATURE_P1P1)); + ability.addTarget(new TargetPermanent(FILTER_A_CREATURE_P1P1)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SimicManipulator.java b/Mage.Sets/src/mage/cards/s/SimicManipulator.java index 74b39998a51..1283e6f49c7 100644 --- a/Mage.Sets/src/mage/cards/s/SimicManipulator.java +++ b/Mage.Sets/src/mage/cards/s/SimicManipulator.java @@ -13,6 +13,7 @@ import mage.cards.CardSetInfo; import mage.constants.*; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetadjustment.PowerTargetAdjuster; @@ -47,7 +48,7 @@ public final class SimicManipulator extends CardImpl { // {T}, Remove one or more +1/+1 counters from Simic Manipulator: Gain control of target creature with power less than or equal to the number of +1/+1 counters removed this way. Ability ability = new SimpleActivatedAbility(new GainControlTargetEffect(Duration.Custom, true), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); ability.addCost(new RemoveVariableCountersSourceCost(CounterType.P1P1, 1, "Remove one or more +1/+1 counters from {this}")); ability.setTargetAdjuster(new PowerTargetAdjuster(GetXValue.instance, ComparisonType.OR_LESS)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/s/SimulacrumSynthesizer.java b/Mage.Sets/src/mage/cards/s/SimulacrumSynthesizer.java index f3df357df07..fbba2ad929b 100644 --- a/Mage.Sets/src/mage/cards/s/SimulacrumSynthesizer.java +++ b/Mage.Sets/src/mage/cards/s/SimulacrumSynthesizer.java @@ -1,6 +1,6 @@ package mage.cards.s; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.keyword.ScryEffect; @@ -9,7 +9,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.FilterPermanent; -import mage.filter.common.FilterArtifactPermanent; +import mage.filter.common.FilterControlledArtifactPermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.game.permanent.token.KarnConstructToken; @@ -22,7 +22,7 @@ import java.util.UUID; public final class SimulacrumSynthesizer extends CardImpl { private static final FilterPermanent filter = - new FilterArtifactPermanent("another artifact with mana value 3 or greater"); + new FilterControlledArtifactPermanent("another artifact you control with mana value 3 or greater"); static { filter.add(AnotherPredicate.instance); @@ -36,9 +36,7 @@ public final class SimulacrumSynthesizer extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new ScryEffect(2))); // Whenever another artifact with mana value 3 or more you control enters, create a 0/0 colorless Construct artifact creature token with "This creature gets +1/+1 for each artifact you control." - this.addAbility(new EntersBattlefieldControlledTriggeredAbility( - new CreateTokenEffect(new KarnConstructToken()), filter - )); + this.addAbility(new EntersBattlefieldAllTriggeredAbility(new CreateTokenEffect(new KarnConstructToken()), filter)); } private SimulacrumSynthesizer(final SimulacrumSynthesizer card) { diff --git a/Mage.Sets/src/mage/cards/s/SinewDancer.java b/Mage.Sets/src/mage/cards/s/SinewDancer.java index 558edffe5b3..6b6b3854987 100644 --- a/Mage.Sets/src/mage/cards/s/SinewDancer.java +++ b/Mage.Sets/src/mage/cards/s/SinewDancer.java @@ -1,23 +1,22 @@ package mage.cards.s; -import java.util.UUID; - import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.CorruptedCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.TapTargetEffect; -import mage.constants.AbilityWord; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; -import mage.constants.Zone; +import mage.constants.SubType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * @author TheElk801 */ @@ -38,9 +37,8 @@ public final class SinewDancer extends CardImpl { this.addAbility(ability); // Corrupted -- {W}, {T}: Tap target creature. Activate only if an opponent has three or more poison counters. - ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, new TapTargetEffect(), - new ManaCostsImpl<>("{W}"), CorruptedCondition.instance + ability = new ActivateIfConditionActivatedAbility( + new TapTargetEffect(), new ManaCostsImpl<>("{W}"), CorruptedCondition.instance ); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent()); diff --git a/Mage.Sets/src/mage/cards/s/SirenOfTheFangedCoast.java b/Mage.Sets/src/mage/cards/s/SirenOfTheFangedCoast.java index fde54270672..32669c02d3b 100644 --- a/Mage.Sets/src/mage/cards/s/SirenOfTheFangedCoast.java +++ b/Mage.Sets/src/mage/cards/s/SirenOfTheFangedCoast.java @@ -1,30 +1,28 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TributeNotPaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.TributeAbility; 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.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class SirenOfTheFangedCoast extends CardImpl { public SirenOfTheFangedCoast(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}"); this.subtype.add(SubType.SIREN); this.power = new MageInt(1); @@ -32,13 +30,16 @@ public final class SirenOfTheFangedCoast extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); + // Tribute 3 this.addAbility(new TributeAbility(3)); + // When Siren of the Fanged Coast enters the battlefield, if tribute wasn't paid, gain control of target creature. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new GainControlTargetEffect(Duration.EndOfGame, true), false); + Ability ability = new EntersBattlefieldTriggeredAbility( + new GainControlTargetEffect(Duration.EndOfGame, true) + ).withInterveningIf(TributeNotPaidCondition.instance); ability.addTarget(new TargetCreaturePermanent()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TributeNotPaidCondition.instance, - "When {this} enters, if tribute wasn't paid, gain control of target creature.")); + this.addAbility(ability); } private SirenOfTheFangedCoast(final SirenOfTheFangedCoast card) { diff --git a/Mage.Sets/src/mage/cards/s/SithAssassin.java b/Mage.Sets/src/mage/cards/s/SithAssassin.java index 1397decf45f..84f38e04fa8 100644 --- a/Mage.Sets/src/mage/cards/s/SithAssassin.java +++ b/Mage.Sets/src/mage/cards/s/SithAssassin.java @@ -1,22 +1,25 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.HateCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.watchers.common.LifeLossOtherFromCombatWatcher; +import java.util.UUID; + +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** - * * @author Styxo */ public final class SithAssassin extends CardImpl { @@ -29,12 +32,9 @@ public final class SithAssassin extends CardImpl { this.toughness = new MageInt(2); // Hate — When Sith Assassin enters the battlefield, if opponent lost life from source other than combat damage this turn, you may destroy target nonblack creature. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), true), - HateCondition.instance, - "Hate — When {this} enters, if an opponent lost life from a source other than combat damage this turn, you may destroy target nonblack creature."); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); - this.addAbility(ability, new LifeLossOtherFromCombatWatcher()); + Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), true).withInterveningIf(HateCondition.instance); + ability.addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.addAbility(ability.setAbilityWord(AbilityWord.HATE), new LifeLossOtherFromCombatWatcher()); } private SithAssassin(final SithAssassin card) { diff --git a/Mage.Sets/src/mage/cards/s/SithInquisitor.java b/Mage.Sets/src/mage/cards/s/SithInquisitor.java index e48e1af2e19..0c2c3782520 100644 --- a/Mage.Sets/src/mage/cards/s/SithInquisitor.java +++ b/Mage.Sets/src/mage/cards/s/SithInquisitor.java @@ -1,40 +1,36 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.HateCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; import mage.target.TargetPlayer; import mage.watchers.common.LifeLossOtherFromCombatWatcher; +import java.util.UUID; + /** - * * @author Styxo */ public final class SithInquisitor extends CardImpl { public SithInquisitor(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.HUMAN); this.subtype.add(SubType.SITH); this.power = new MageInt(5); this.toughness = new MageInt(1); // Hate — When Sith Assassin enters the battlefield, if opponent lost life from source other than combat damage this turn, target player discard a card at random. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(1, true)), - HateCondition.instance, - "Hate — When {this} enters, if an opponent lost life from a source other then combat damage this turn, target player discard a card at random."); + Ability ability = new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(1, true)).withInterveningIf(HateCondition.instance); ability.addTarget(new TargetPlayer()); - this.addAbility(ability, new LifeLossOtherFromCombatWatcher()); + this.addAbility(ability.setAbilityWord(AbilityWord.HATE), new LifeLossOtherFromCombatWatcher()); } private SithInquisitor(final SithInquisitor card) { diff --git a/Mage.Sets/src/mage/cards/s/SithMagic.java b/Mage.Sets/src/mage/cards/s/SithMagic.java index 989072d96ca..90cb27d82ad 100644 --- a/Mage.Sets/src/mage/cards/s/SithMagic.java +++ b/Mage.Sets/src/mage/cards/s/SithMagic.java @@ -1,13 +1,9 @@ package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; -import mage.abilities.TriggeredAbility; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.condition.common.HateCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.ReplacementEffectImpl; @@ -15,14 +11,11 @@ import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.LifelinkAbility; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; 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.TargetController; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; @@ -34,8 +27,9 @@ import mage.target.targetpointer.FixedTarget; import mage.util.CardUtil; import mage.watchers.common.LifeLossOtherFromCombatWatcher; +import java.util.UUID; + /** - * * @author Styxo */ public final class SithMagic extends CardImpl { @@ -44,14 +38,10 @@ public final class SithMagic extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}{B}{R}"); // Hate — At the beggining of each combat, if opponent lost life from a source other than combat damage this turn, you may return target card from a graveyard to the battlefield under your control. It gains lifelink and haste. Exile it at the beginning of the next end step or if it would leave the battlefield. - TriggeredAbility triggeredAbility = new BeginningOfCombatTriggeredAbility(TargetController.ANY, new SithMagicEffect(), true); - triggeredAbility.addEffect(new SithMagicReplacementEffect()); - Ability ability = new ConditionalInterveningIfTriggeredAbility( - triggeredAbility, - HateCondition.instance, - "Hate — At the beggining of each combat, if opponent lost life from a source other than combat damage this turn, you may return target card from a graveyard to the battlefield under your control. It gains lifelink and haste. Exile it at the beginning of the next end step or if it would leave the battlefield."); + Ability ability = new BeginningOfCombatTriggeredAbility(TargetController.ANY, new SithMagicEffect(), true).withInterveningIf(HateCondition.instance); + ability.addEffect(new SithMagicReplacementEffect()); ability.addTarget(new TargetCardInGraveyard(StaticFilters.FILTER_CARD_CREATURE)); - this.addAbility(ability, new LifeLossOtherFromCombatWatcher()); + this.addAbility(ability.setAbilityWord(AbilityWord.HATE), new LifeLossOtherFromCombatWatcher()); } private SithMagic(final SithMagic card) { diff --git a/Mage.Sets/src/mage/cards/s/SithMarauder.java b/Mage.Sets/src/mage/cards/s/SithMarauder.java index 0f1f55859d7..1738795c9ff 100644 --- a/Mage.Sets/src/mage/cards/s/SithMarauder.java +++ b/Mage.Sets/src/mage/cards/s/SithMarauder.java @@ -1,22 +1,21 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.HateCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; import mage.target.common.TargetAnyTarget; import mage.watchers.common.LifeLossOtherFromCombatWatcher; +import java.util.UUID; + /** - * * @author Styxo */ public final class SithMarauder extends CardImpl { @@ -29,12 +28,9 @@ public final class SithMarauder extends CardImpl { this.toughness = new MageInt(4); // Hate — When Sith Marauder enters the battlefield, if an opponent lost life from a source other than combat damage this turn, Sith Marauder deals 3 damage to any target. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(3)), - HateCondition.instance, - "Hate — When {this} enters, if an opponent lost life from a source other than combat damage this turn, {this} deals 3 damage to any target"); + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(3)).withInterveningIf(HateCondition.instance); ability.addTarget(new TargetAnyTarget()); - this.addAbility(ability, new LifeLossOtherFromCombatWatcher()); + this.addAbility(ability.setAbilityWord(AbilityWord.HATE), new LifeLossOtherFromCombatWatcher()); } private SithMarauder(final SithMarauder card) { diff --git a/Mage.Sets/src/mage/cards/s/SithMindseer.java b/Mage.Sets/src/mage/cards/s/SithMindseer.java index 34791594942..7d3b67c3cf3 100644 --- a/Mage.Sets/src/mage/cards/s/SithMindseer.java +++ b/Mage.Sets/src/mage/cards/s/SithMindseer.java @@ -1,32 +1,28 @@ - package mage.cards.s; -import java.util.UUID; 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; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; import mage.target.common.TargetCreaturePermanent; import mage.watchers.common.LifeLossOtherFromCombatWatcher; +import java.util.UUID; + /** - * * @author Styxo */ public final class SithMindseer extends CardImpl { public SithMindseer(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{U}{B}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}{B}{R}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.SITH); this.power = new MageInt(3); @@ -34,16 +30,12 @@ public final class SithMindseer extends CardImpl { // 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 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 {this} enters, 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 ability = new EntersBattlefieldTriggeredAbility( + new GainControlTargetEffect(Duration.UntilSourceLeavesBattlefield, true) + .setText("gain control of target creature for as long as {this} remains on the battlefield") + ).withInterveningIf(HateCondition.instance); ability.addTarget(new TargetCreaturePermanent()); - this.addAbility(ability, new LifeLossOtherFromCombatWatcher()); + this.addAbility(ability.setAbilityWord(AbilityWord.HATE), new LifeLossOtherFromCombatWatcher()); } private SithMindseer(final SithMindseer card) { diff --git a/Mage.Sets/src/mage/cards/s/SithSorcerer.java b/Mage.Sets/src/mage/cards/s/SithSorcerer.java index 97fad762a32..1b21d145d04 100644 --- a/Mage.Sets/src/mage/cards/s/SithSorcerer.java +++ b/Mage.Sets/src/mage/cards/s/SithSorcerer.java @@ -1,28 +1,27 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.HateCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.keyword.ScryEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; import mage.watchers.common.LifeLossOtherFromCombatWatcher; +import java.util.UUID; + /** - * * @author Styxo */ public final class SithSorcerer extends CardImpl { public SithSorcerer(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.subtype.add(SubType.SITH); this.power = new MageInt(2); @@ -32,12 +31,8 @@ public final class SithSorcerer extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new ScryEffect(2))); // Hate — When Sith Sorcerer enters the battlefield, if an opponent lost life from a source other than combat damage this turn, draw a card. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1)), - HateCondition.instance, - "Hate — When {this} dies, if an opponent lost life from a source other than combat damage this turn, draw a card."); - this.addAbility(ability, new LifeLossOtherFromCombatWatcher()); - + this.addAbility(new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1)) + .withInterveningIf(HateCondition.instance).setAbilityWord(AbilityWord.HATE), new LifeLossOtherFromCombatWatcher()); } private SithSorcerer(final SithSorcerer card) { diff --git a/Mage.Sets/src/mage/cards/s/SithThoughtseeker.java b/Mage.Sets/src/mage/cards/s/SithThoughtseeker.java index 433960db82f..b1dbe0fa425 100644 --- a/Mage.Sets/src/mage/cards/s/SithThoughtseeker.java +++ b/Mage.Sets/src/mage/cards/s/SithThoughtseeker.java @@ -1,41 +1,34 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.condition.common.HateCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; 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 java.util.UUID; /** - * * @author Styxo */ public final class SithThoughtseeker extends CardImpl { public SithThoughtseeker(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.SITH); this.power = new MageInt(2); this.toughness = new MageInt(1); // Hate — {2}{U}: Draw a card. Activate this ability only if an opponent lost life from source other than combat damage this turn. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, - new DrawCardSourceControllerEffect(1), - new ManaCostsImpl<>("{2}{U}"), - HateCondition.instance); - ability.setAbilityWord(AbilityWord.HATE); - this.addAbility(ability); + this.addAbility(new ActivateIfConditionActivatedAbility( + new DrawCardSourceControllerEffect(1), new ManaCostsImpl<>("{2}{U}"), HateCondition.instance + ).setAbilityWord(AbilityWord.HATE)); } private SithThoughtseeker(final SithThoughtseeker card) { diff --git a/Mage.Sets/src/mage/cards/s/SkarrganFirebird.java b/Mage.Sets/src/mage/cards/s/SkarrganFirebird.java index dadce98393e..3397644e2bf 100644 --- a/Mage.Sets/src/mage/cards/s/SkarrganFirebird.java +++ b/Mage.Sets/src/mage/cards/s/SkarrganFirebird.java @@ -1,12 +1,10 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.condition.Condition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect; import mage.abilities.keyword.BloodthirstAbility; import mage.abilities.keyword.FlyingAbility; @@ -18,14 +16,15 @@ import mage.constants.Zone; import mage.game.Game; import mage.watchers.common.BloodthirstWatcher; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class SkarrganFirebird extends CardImpl { public SkarrganFirebird(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}{R}"); this.subtype.add(SubType.PHOENIX); this.power = new MageInt(3); @@ -33,15 +32,15 @@ public final class SkarrganFirebird extends CardImpl { // Bloodthirst 3 this.addAbility(new BloodthirstAbility(3)); + // Flying this.addAbility(FlyingAbility.getInstance()); + // {R}{R}{R}: Return Skarrgan Firebird from your graveyard to your hand. Activate this ability only if an opponent was dealt damage this turn. - this.addAbility(new ConditionalActivatedAbility( - Zone.GRAVEYARD, - new ReturnSourceFromGraveyardToHandEffect(), - new ManaCostsImpl<>("{R}{R}{R}"), - new OpponentWasDealtDamageCondition(), - null)); + this.addAbility(new ActivateIfConditionActivatedAbility( + Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(), + new ManaCostsImpl<>("{R}{R}{R}"), OpponentWasDealtDamageCondition.instance + )); } private SkarrganFirebird(final SkarrganFirebird card) { @@ -54,10 +53,8 @@ public final class SkarrganFirebird extends CardImpl { } } -class OpponentWasDealtDamageCondition implements Condition { - - public OpponentWasDealtDamageCondition() { - } +enum OpponentWasDealtDamageCondition implements Condition { + instance; @Override public boolean apply(Game game, Ability source) { @@ -67,6 +64,6 @@ class OpponentWasDealtDamageCondition implements Condition { @Override public String toString() { - return "if an opponent was dealt damage this turn"; + return "an opponent was dealt damage this turn"; } } diff --git a/Mage.Sets/src/mage/cards/s/SkarrganHellkite.java b/Mage.Sets/src/mage/cards/s/SkarrganHellkite.java index 0e312aca483..d25ce1933c4 100644 --- a/Mage.Sets/src/mage/cards/s/SkarrganHellkite.java +++ b/Mage.Sets/src/mage/cards/s/SkarrganHellkite.java @@ -2,9 +2,10 @@ package mage.cards.s; import mage.MageInt; import mage.abilities.Ability; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DamageMultiEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.RiotAbility; @@ -12,7 +13,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.counters.CounterType; import mage.target.common.TargetAnyTargetAmount; @@ -23,6 +23,8 @@ import java.util.UUID; */ public final class SkarrganHellkite extends CardImpl { + private static final Condition condition = new SourceHasCounterCondition(CounterType.P1P1); + public SkarrganHellkite(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}"); @@ -37,12 +39,9 @@ public final class SkarrganHellkite extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // {3}{R}: Skarrgan Hellkite deals 2 damage divided as you choose among one or two targets. Activate this ability only if Skarrgan Hellkite has a +1/+1 counter on it. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, new DamageMultiEffect(), - new ManaCostsImpl<>("{3}{R}"), new SourceHasCounterCondition(CounterType.P1P1), - "{3}{R}: {this} deals 2 damage divided as you choose among one or two targets. " + - "Activate only if {this} has a +1/+1 counter on it." - ); + Ability ability = new ActivateIfConditionActivatedAbility( + new DamageMultiEffect(), new ManaCostsImpl<>("{3}{R}"), condition + ).withConditionText("activate only if {this} has a +1/+1 counter on it"); ability.addTarget(new TargetAnyTargetAmount(2)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SkinInvasion.java b/Mage.Sets/src/mage/cards/s/SkinInvasion.java index 418c9d540bc..38647f13455 100644 --- a/Mage.Sets/src/mage/cards/s/SkinInvasion.java +++ b/Mage.Sets/src/mage/cards/s/SkinInvasion.java @@ -66,7 +66,7 @@ class SkinInvasionEffect extends OneShotEffect { SkinInvasionEffect() { super(Outcome.PutCardInPlay); - this.staticText = "return {this} to the battlefield transformed under your control"; + this.staticText = "return this card to the battlefield transformed under your control"; } private SkinInvasionEffect(final SkinInvasionEffect effect) { diff --git a/Mage.Sets/src/mage/cards/s/Skinthinner.java b/Mage.Sets/src/mage/cards/s/Skinthinner.java index dda8978f95e..43eebdb9d6d 100644 --- a/Mage.Sets/src/mage/cards/s/Skinthinner.java +++ b/Mage.Sets/src/mage/cards/s/Skinthinner.java @@ -12,8 +12,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author LoneFox @@ -30,7 +33,7 @@ public final class Skinthinner extends CardImpl { this.addAbility(new MorphAbility(this, new ManaCostsImpl<>("{3}{B}{B}"))); // When Skinthinner is turned face up, destroy target nonblack creature. It can't be regenerated. Ability ability = new TurnedFaceUpSourceTriggeredAbility(new DestroyTargetEffect(true)); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + ability.addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SkirkAlarmist.java b/Mage.Sets/src/mage/cards/s/SkirkAlarmist.java index 22acf7450c3..e389c7ec213 100644 --- a/Mage.Sets/src/mage/cards/s/SkirkAlarmist.java +++ b/Mage.Sets/src/mage/cards/s/SkirkAlarmist.java @@ -22,6 +22,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.card.FaceDownPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; @@ -52,7 +53,7 @@ public final class SkirkAlarmist extends CardImpl { // {tap}: Turn target face-down creature you control face up. At the beginning of the next end step, sacrifice it. Ability ability = new SimpleActivatedAbility(new TurnFaceUpTargetEffect(), new TapSourceCost()); ability.addEffect(new SkirkAlarmistEffect()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SkirsdagHighPriest.java b/Mage.Sets/src/mage/cards/s/SkirsdagHighPriest.java index b8df837ea25..7364d50e460 100644 --- a/Mage.Sets/src/mage/cards/s/SkirsdagHighPriest.java +++ b/Mage.Sets/src/mage/cards/s/SkirsdagHighPriest.java @@ -1,13 +1,11 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.common.MorbidCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapTargetCost; -import mage.abilities.decorator.ConditionalActivatedAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.hint.common.MorbidHint; import mage.cards.CardImpl; @@ -15,26 +13,18 @@ import mage.cards.CardSetInfo; import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.permanent.TappedPredicate; +import mage.filter.StaticFilters; import mage.game.permanent.token.DemonToken; -import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; /** - * * @author North */ public final class SkirsdagHighPriest extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); - - static { - filter.add(TappedPredicate.UNTAPPED); - } - public SkirsdagHighPriest(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); @@ -42,11 +32,11 @@ public final class SkirsdagHighPriest extends CardImpl { this.toughness = new MageInt(2); // Morbid — {tap}, Tap two untapped creatures you control: Create a 5/5 black Demon creature token with flying. Activate this ability only if a creature died this turn. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new DemonToken()), - new TapSourceCost(), MorbidCondition.instance); - ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(2, 2, filter, false))); - ability.setAbilityWord(AbilityWord.MORBID); - this.addAbility(ability.addHint(MorbidHint.instance)); + Ability ability = new ActivateIfConditionActivatedAbility( + new CreateTokenEffect(new DemonToken()), new TapSourceCost(), MorbidCondition.instance + ); + ability.addCost(new TapTargetCost(2, StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURES)); + this.addAbility(ability.setAbilityWord(AbilityWord.MORBID).addHint(MorbidHint.instance)); } private SkirsdagHighPriest(final SkirsdagHighPriest card) { diff --git a/Mage.Sets/src/mage/cards/s/SkitterbeamBattalion.java b/Mage.Sets/src/mage/cards/s/SkitterbeamBattalion.java index 97bcaebafba..e63232362d0 100644 --- a/Mage.Sets/src/mage/cards/s/SkitterbeamBattalion.java +++ b/Mage.Sets/src/mage/cards/s/SkitterbeamBattalion.java @@ -3,7 +3,6 @@ package mage.cards.s; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromEverywhereSourceCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.CreateTokenCopySourceEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.PrototypeAbility; @@ -37,11 +36,8 @@ public final class SkitterbeamBattalion extends CardImpl { this.addAbility(HasteAbility.getInstance()); // When Skitterbeam Battalion enters the battlefield, if you cast it, create two tokens that are copies of it. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new CreateTokenCopySourceEffect(2)), - CastFromEverywhereSourceCondition.instance, "When {this} enters, " + - "if you cast it, create two tokens that are copies of it." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenCopySourceEffect(2) + .setText("create two tokens that are copies of it")).withInterveningIf(CastFromEverywhereSourceCondition.instance)); } private SkitterbeamBattalion(final SkitterbeamBattalion card) { diff --git a/Mage.Sets/src/mage/cards/s/Skitterskin.java b/Mage.Sets/src/mage/cards/s/Skitterskin.java index 70676dd1b60..80e1d9f5ab8 100644 --- a/Mage.Sets/src/mage/cards/s/Skitterskin.java +++ b/Mage.Sets/src/mage/cards/s/Skitterskin.java @@ -1,11 +1,9 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.common.CantBlockAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.RegenerateSourceEffect; @@ -14,26 +12,29 @@ 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.FilterControlledCreaturePermanent; -import mage.filter.predicate.mageobject.ColorlessPredicate; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.predicate.mageobject.ColorlessPredicate; + +import java.util.UUID; /** - * * @author fireshoes */ public final class Skitterskin extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("you control another colorless creature"); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("you control another colorless creature"); static { filter.add(AnotherPredicate.instance); filter.add(ColorlessPredicate.instance); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); + public Skitterskin(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.ELDRAZI); this.subtype.add(SubType.DRONE); this.power = new MageInt(4); @@ -46,11 +47,9 @@ public final class Skitterskin extends CardImpl { this.addAbility(new CantBlockAbility()); // {1}{B}: Regenerate Skitterskin. Activate this ability only if you control another colorless creature. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new RegenerateSourceEffect(), - new ManaCostsImpl<>("{1}{B}"), - new PermanentsOnTheBattlefieldCondition(filter)); - this.addAbility(ability); + this.addAbility(new ActivateIfConditionActivatedAbility( + new RegenerateSourceEffect(), new ManaCostsImpl<>("{1}{B}"), condition + )); } private Skitterskin(final Skitterskin card) { diff --git a/Mage.Sets/src/mage/cards/s/Skizzik.java b/Mage.Sets/src/mage/cards/s/Skizzik.java index ba22598c761..608f964e689 100644 --- a/Mage.Sets/src/mage/cards/s/Skizzik.java +++ b/Mage.Sets/src/mage/cards/s/Skizzik.java @@ -1,14 +1,14 @@ package mage.cards.s; import mage.MageInt; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.KickerAbility; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -18,11 +18,12 @@ import mage.constants.TargetController; import java.util.UUID; /** - * * @author LevelX2 */ public final class Skizzik extends CardImpl { + private static final Condition condition = new InvertCondition(KickedCondition.ONCE, "{this} wasn't kicked"); + public Skizzik(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); this.subtype.add(SubType.ELEMENTAL); @@ -40,10 +41,8 @@ public final class Skizzik extends CardImpl { this.addAbility(HasteAbility.getInstance()); // At the beginning of the end step, if Skizzik wasn't kicked, sacrifice it. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility(TargetController.NEXT, new SacrificeSourceEffect(), false), - new InvertCondition(KickedCondition.ONCE), - "At the beginning of the end step, if {this} wasn't kicked, sacrifice it" + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.NEXT, new SacrificeSourceEffect().setText("sacrifice it"), false, condition )); } diff --git a/Mage.Sets/src/mage/cards/s/Skulduggery.java b/Mage.Sets/src/mage/cards/s/Skulduggery.java index 6241a7da838..a18dc256c48 100644 --- a/Mage.Sets/src/mage/cards/s/Skulduggery.java +++ b/Mage.Sets/src/mage/cards/s/Skulduggery.java @@ -14,10 +14,13 @@ import mage.constants.Outcome; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author TheElk801 @@ -30,7 +33,7 @@ public final class Skulduggery extends CardImpl { // Until end of turn, target creature you control gets +1/+1 and target creature an opponent controls gets -1/-1. this.getSpellAbility().addEffect(new SkulduggeryEffect()); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); } private Skulduggery(final Skulduggery card) { diff --git a/Mage.Sets/src/mage/cards/s/SkyHussar.java b/Mage.Sets/src/mage/cards/s/SkyHussar.java index 296144143f6..8a4f3b235dd 100644 --- a/Mage.Sets/src/mage/cards/s/SkyHussar.java +++ b/Mage.Sets/src/mage/cards/s/SkyHussar.java @@ -1,7 +1,5 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -14,26 +12,32 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; /** - * * @author emerald000 */ public final class SkyHussar extends CardImpl { - - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped white and/or blue creatures you control"); + + private static final FilterControlledPermanent filter = new FilterControlledCreaturePermanent("untapped white and/or blue creatures you control"); + static { - filter.add(Predicates.or(new ColorPredicate(ObjectColor.WHITE), new ColorPredicate(ObjectColor.BLUE))); + filter.add(Predicates.or( + new ColorPredicate(ObjectColor.WHITE), + new ColorPredicate(ObjectColor.BLUE) + )); filter.add(TappedPredicate.UNTAPPED); } public SkyHussar(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{U}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.KNIGHT); @@ -42,12 +46,17 @@ public final class SkyHussar extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); - + // When Sky Hussar enters the battlefield, untap all creatures you control. - this.addAbility(new EntersBattlefieldTriggeredAbility(new UntapAllControllerEffect(new FilterControlledCreaturePermanent(), "untap all creatures you control"), false)); + this.addAbility(new EntersBattlefieldTriggeredAbility(new UntapAllControllerEffect( + StaticFilters.FILTER_CONTROLLED_CREATURES, "untap all creatures you control" + ), false)); // Forecast - Tap two untapped white and/or blue creatures you control, Reveal Sky Hussar from your hand: Draw a card. - this.addAbility(new ForecastAbility(new DrawCardSourceControllerEffect(1), new TapTargetCost(new TargetControlledCreaturePermanent(2, 2, filter, true)))); + this.addAbility(new ForecastAbility( + new DrawCardSourceControllerEffect(1), + new TapTargetCost(2, filter) + )); } private SkyHussar(final SkyHussar card) { diff --git a/Mage.Sets/src/mage/cards/s/SkyWeaver.java b/Mage.Sets/src/mage/cards/s/SkyWeaver.java index d94cae2c327..1d745ca6288 100644 --- a/Mage.Sets/src/mage/cards/s/SkyWeaver.java +++ b/Mage.Sets/src/mage/cards/s/SkyWeaver.java @@ -18,6 +18,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -42,7 +43,7 @@ public final class SkyWeaver extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), new GenericManaCost(2)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SkyclaveRelic.java b/Mage.Sets/src/mage/cards/s/SkyclaveRelic.java index cd303bd17a3..bfa00aa64cd 100644 --- a/Mage.Sets/src/mage/cards/s/SkyclaveRelic.java +++ b/Mage.Sets/src/mage/cards/s/SkyclaveRelic.java @@ -2,7 +2,6 @@ package mage.cards.s; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.CreateTokenCopySourceEffect; import mage.abilities.keyword.IndestructibleAbility; import mage.abilities.keyword.KickerAbility; @@ -28,11 +27,8 @@ public final class SkyclaveRelic extends CardImpl { this.addAbility(IndestructibleAbility.getInstance()); // When Skyclave Relic enters the battlefield, if it was kicked, create two tapped tokens that are copies of Skyclave Relic. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new CreateTokenCopySourceEffect(2, true)), - KickedCondition.ONCE, "When {this} enters, if it was kicked, " + - "create two tapped tokens that are copies of {this}." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenCopySourceEffect(2, true)) + .withInterveningIf(KickedCondition.ONCE)); // {T}: Add one mana of any color. this.addAbility(new AnyColorManaAbility()); diff --git a/Mage.Sets/src/mage/cards/s/SkyclaveShade.java b/Mage.Sets/src/mage/cards/s/SkyclaveShade.java index 5b830fcf62a..3f984c77990 100644 --- a/Mage.Sets/src/mage/cards/s/SkyclaveShade.java +++ b/Mage.Sets/src/mage/cards/s/SkyclaveShade.java @@ -7,7 +7,6 @@ import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.LandfallAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.KickerAbility; @@ -45,12 +44,8 @@ public final class SkyclaveShade extends CardImpl { )); // Landfall — Whenever a land you control enters, if Skyclave Shade is in your graveyard and it's your turn, you may cast it from your graveyard this turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new LandfallAbility(Zone.GRAVEYARD, new SkyclaveShadeEffect(), false), - SkyclaveShadeCondition.instance, "Landfall — Whenever a land " + - "you control enters, if {this} is in your graveyard and it's your turn, " + - "you may cast it from your graveyard this turn." - )); + this.addAbility(new LandfallAbility(Zone.GRAVEYARD, new SkyclaveShadeEffect(), false) + .withInterveningIf(SkyclaveShadeCondition.instance)); } private SkyclaveShade(final SkyclaveShade card) { @@ -71,12 +66,18 @@ enum SkyclaveShadeCondition implements Condition { return game.getActivePlayerId().equals(source.getControllerId()) && game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD; } + + @Override + public String toString() { + return "this card is in your graveyard and it's your turn"; + } } class SkyclaveShadeEffect extends AsThoughEffectImpl { SkyclaveShadeEffect() { super(AsThoughEffectType.CAST_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit); + staticText = "you may cast it from your graveyard this turn"; } private SkyclaveShadeEffect(final SkyclaveShadeEffect effect) { diff --git a/Mage.Sets/src/mage/cards/s/SkylineCascade.java b/Mage.Sets/src/mage/cards/s/SkylineCascade.java index 65f3c2c43bb..df393a141c4 100644 --- a/Mage.Sets/src/mage/cards/s/SkylineCascade.java +++ b/Mage.Sets/src/mage/cards/s/SkylineCascade.java @@ -11,8 +11,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author fireshoes @@ -27,7 +30,7 @@ public final class SkylineCascade extends CardImpl { // When Skyline Cascade enters the battlefield, target creature an opponent controls doesn't untap during its controller's next untap step. Ability ability = new EntersBattlefieldTriggeredAbility(new DontUntapInControllersNextUntapStepTargetEffect(), false); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); // {T}: Add {U}. diff --git a/Mage.Sets/src/mage/cards/s/SkylineDespot.java b/Mage.Sets/src/mage/cards/s/SkylineDespot.java index d8d73074e96..99f89a1fa8c 100644 --- a/Mage.Sets/src/mage/cards/s/SkylineDespot.java +++ b/Mage.Sets/src/mage/cards/s/SkylineDespot.java @@ -1,14 +1,13 @@ package mage.cards.s; import mage.MageInt; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.MonarchIsSourceControllerCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.BecomesMonarchSourceEffect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.hint.common.MonarchHint; import mage.abilities.keyword.FlyingAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -31,17 +30,13 @@ public final class SkylineDespot extends CardImpl { // Flying this.addAbility(FlyingAbility.getInstance()); + // When Skyline Despot enters the battlefield, you become the monarch. this.addAbility(new EntersBattlefieldTriggeredAbility(new BecomesMonarchSourceEffect()).addHint(MonarchHint.instance)); // At the beginning of your upkeep, if you're the monarch, put a 5/5 red Dragon creature token with flying onto the battlefield. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility( - new CreateTokenEffect(new DragonToken2()), false - ), MonarchIsSourceControllerCondition.instance, "At the beginning of your upkeep, " + - "if you're the monarch, create a 5/5 red Dragon creature token with flying." - )); - + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new DragonToken2())) + .withInterveningIf(MonarchIsSourceControllerCondition.instance)); } private SkylineDespot(final SkylineDespot card) { diff --git a/Mage.Sets/src/mage/cards/s/SkymarkRoc.java b/Mage.Sets/src/mage/cards/s/SkymarkRoc.java index b9bc17a294a..fb5be177dff 100644 --- a/Mage.Sets/src/mage/cards/s/SkymarkRoc.java +++ b/Mage.Sets/src/mage/cards/s/SkymarkRoc.java @@ -2,32 +2,38 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; 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.constants.ComparisonType; -import mage.constants.Zone; +import mage.constants.SetTargetPointer; +import mage.constants.SubType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ToughnessPredicate; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; +import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class SkymarkRoc extends CardImpl { + private static final FilterPermanent filter = new FilterCreaturePermanent("creature defending player controls with toughness 2 or less"); + + static { + filter.add(new ToughnessPredicate(ComparisonType.OR_LESS, 2)); + } + public SkymarkRoc(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{U}"); this.subtype.add(SubType.BIRD); this.power = new MageInt(3); @@ -37,7 +43,10 @@ public final class SkymarkRoc extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Whenever Skymark Roc attacks, you may return target creature defending player controls with toughness 2 or less to its owner's hand. - this.addAbility(new SkymarkRocAbility()); + Ability ability = new AttacksTriggeredAbility(new ReturnToHandTargetEffect(), true, null, SetTargetPointer.PLAYER); + ability.addTarget(new TargetPermanent(filter)); + ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster()); + this.addAbility(ability); } private SkymarkRoc(final SkymarkRoc card) { @@ -49,45 +58,3 @@ public final class SkymarkRoc extends CardImpl { return new SkymarkRoc(this); } } - -class SkymarkRocAbility extends TriggeredAbilityImpl { - - public SkymarkRocAbility() { - super(Zone.BATTLEFIELD, new ReturnToHandTargetEffect(), true); - } - - private SkymarkRocAbility(final SkymarkRocAbility ability) { - super(ability); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ATTACKER_DECLARED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getSourceId().equals(this.getSourceId())) { - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls with toughness 2 or less"); - UUID defenderId = game.getCombat().getDefendingPlayerId(sourceId, game); - filter.add(new ControllerIdPredicate(defenderId)); - filter.add(new ToughnessPredicate(ComparisonType.FEWER_THAN, 3)); - - this.getTargets().clear(); - TargetCreaturePermanent target = new TargetCreaturePermanent(filter); - this.addTarget(target); - return true; - } - return false; - } - - @Override - public String getRule() { - return "Whenever {this} attacks, you may return target creature defending player controls with toughness 2 or less to its owner's hand."; - } - - @Override - public SkymarkRocAbility copy() { - return new SkymarkRocAbility(this); - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/SkyshroudArcher.java b/Mage.Sets/src/mage/cards/s/SkyshroudArcher.java index def019a5a0b..3a953a4d172 100644 --- a/Mage.Sets/src/mage/cards/s/SkyshroudArcher.java +++ b/Mage.Sets/src/mage/cards/s/SkyshroudArcher.java @@ -16,6 +16,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -39,7 +40,7 @@ public final class SkyshroudArcher extends CardImpl { // {tap}: Target creature with flying gets -1/-1 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(-1, -1, Duration.EndOfTurn), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SkysovereignConsulFlagship.java b/Mage.Sets/src/mage/cards/s/SkysovereignConsulFlagship.java index a3cdb87498c..7b7ca74daf6 100644 --- a/Mage.Sets/src/mage/cards/s/SkysovereignConsulFlagship.java +++ b/Mage.Sets/src/mage/cards/s/SkysovereignConsulFlagship.java @@ -14,7 +14,7 @@ import mage.constants.SubType; import mage.constants.SuperType; import mage.constants.TargetController; import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent; -import mage.target.common.TargetCreatureOrPlaneswalker; +import mage.target.TargetPermanent; import java.util.UUID; @@ -41,7 +41,7 @@ public final class SkysovereignConsulFlagship extends CardImpl { // Whenever Skysovereign, Consul Flagship enters the battlefield or attacks, it deals 3 damage to target creature or planeswalker an opponent controls. Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility(new DamageTargetEffect(3, "it")); - ability.addTarget(new TargetCreatureOrPlaneswalker(1, 1, filter, false)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // Crew 3 diff --git a/Mage.Sets/src/mage/cards/s/SkywhalersShot.java b/Mage.Sets/src/mage/cards/s/SkywhalersShot.java index 2feaca01741..96a767a2446 100644 --- a/Mage.Sets/src/mage/cards/s/SkywhalersShot.java +++ b/Mage.Sets/src/mage/cards/s/SkywhalersShot.java @@ -10,6 +10,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -29,7 +30,7 @@ public final class SkywhalersShot extends CardImpl { // Destroy target creature with power 3 or greater. Scry 1. getSpellAbility().addEffect(new DestroyTargetEffect()); - getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + getSpellAbility().addTarget(new TargetPermanent(filter)); getSpellAbility().addEffect(new ScryEffect(1)); } diff --git a/Mage.Sets/src/mage/cards/s/Slaughter.java b/Mage.Sets/src/mage/cards/s/Slaughter.java index e7bfe3deaee..28d269eb55a 100644 --- a/Mage.Sets/src/mage/cards/s/Slaughter.java +++ b/Mage.Sets/src/mage/cards/s/Slaughter.java @@ -8,8 +8,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author Temba21 @@ -24,7 +27,7 @@ public final class Slaughter extends CardImpl { // Destroy target nonblack creature. It can't be regenerated. this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); } private Slaughter(final Slaughter card) { diff --git a/Mage.Sets/src/mage/cards/s/SlaughterPact.java b/Mage.Sets/src/mage/cards/s/SlaughterPact.java index 80ae58690b5..57761c98a1b 100644 --- a/Mage.Sets/src/mage/cards/s/SlaughterPact.java +++ b/Mage.Sets/src/mage/cards/s/SlaughterPact.java @@ -9,8 +9,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author Plopman @@ -23,7 +26,7 @@ public final class SlaughterPact extends CardImpl { this.color.setBlack(true); // Destroy target nonblack creature. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); // At the beginning of your next upkeep, pay {2}{B}. If you don't, you lose the game. this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(new PactDelayedTriggeredAbility(new ManaCostsImpl<>("{2}{B}")),false)); diff --git a/Mage.Sets/src/mage/cards/s/SlaughterhouseBouncer.java b/Mage.Sets/src/mage/cards/s/SlaughterhouseBouncer.java index 8627abe95d4..317dd57d256 100644 --- a/Mage.Sets/src/mage/cards/s/SlaughterhouseBouncer.java +++ b/Mage.Sets/src/mage/cards/s/SlaughterhouseBouncer.java @@ -1,23 +1,21 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.condition.common.HellbentCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostTargetEffect; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AbilityWord; 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 SlaughterhouseBouncer extends CardImpl { @@ -31,13 +29,10 @@ public final class SlaughterhouseBouncer extends CardImpl { this.toughness = new MageInt(3); // 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 DiesSourceTriggeredAbility(new BoostTargetEffect(-3, -3, Duration.EndOfTurn)), - HellbentCondition.instance, - AbilityWord.HELLBENT.formatWord() + "When {this} dies, if you have no cards in hand, target creature gets -3/-3 until end of turn." - ); + Ability ability = new DiesSourceTriggeredAbility(new BoostTargetEffect(-3, -3, Duration.EndOfTurn)) + .withInterveningIf(HellbentCondition.instance); ability.addTarget(new TargetCreaturePermanent()); - this.addAbility(ability); + this.addAbility(ability.setAbilityWord(AbilityWord.HELLBENT)); } private SlaughterhouseBouncer(final SlaughterhouseBouncer card) { diff --git a/Mage.Sets/src/mage/cards/s/Slay.java b/Mage.Sets/src/mage/cards/s/Slay.java index f76c49fe73a..d27d8e9237e 100644 --- a/Mage.Sets/src/mage/cards/s/Slay.java +++ b/Mage.Sets/src/mage/cards/s/Slay.java @@ -10,6 +10,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -28,7 +29,7 @@ public final class Slay extends CardImpl { // Destroy target green creature. It can't be regenerated. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("
")); diff --git a/Mage.Sets/src/mage/cards/s/SlayerOfTheWicked.java b/Mage.Sets/src/mage/cards/s/SlayerOfTheWicked.java index d816915ae33..df5b5762239 100644 --- a/Mage.Sets/src/mage/cards/s/SlayerOfTheWicked.java +++ b/Mage.Sets/src/mage/cards/s/SlayerOfTheWicked.java @@ -12,6 +12,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -39,7 +40,7 @@ public final class SlayerOfTheWicked extends CardImpl { // When Slayer of the Wicked enters the battlefield, you may destroy target Vampire, Werewolf, or Zombie. Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), true); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SlimefootThallidTransplant.java b/Mage.Sets/src/mage/cards/s/SlimefootThallidTransplant.java index 1f7150d6b7a..ff06adec65c 100644 --- a/Mage.Sets/src/mage/cards/s/SlimefootThallidTransplant.java +++ b/Mage.Sets/src/mage/cards/s/SlimefootThallidTransplant.java @@ -1,8 +1,7 @@ - package mage.cards.s; import mage.MageInt; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.common.DraftFromSpellbookEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -10,6 +9,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.Predicates; import java.util.Arrays; @@ -22,7 +22,7 @@ import java.util.UUID; */ public final class SlimefootThallidTransplant extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent("a Swamp or Forest"); + private static final FilterPermanent filter = new FilterControlledPermanent("a Swamp or Forest you control"); static { filter.add(Predicates.or( @@ -49,7 +49,7 @@ public final class SlimefootThallidTransplant extends CardImpl { "Yavimaya Sapherd" )); - public SlimefootThallidTransplant (UUID ownerId, CardSetInfo setInfo) { + public SlimefootThallidTransplant(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}{G}"); this.supertype.add(SuperType.LEGENDARY); @@ -58,9 +58,7 @@ public final class SlimefootThallidTransplant extends CardImpl { this.toughness = new MageInt(2); // Whenever a Swamp or Forest you control enters, draft a card from Slimefoot, Thallid Transplant’s spellbook. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility( - new DraftFromSpellbookEffect(spellbook), filter - )); + this.addAbility(new EntersBattlefieldAllTriggeredAbility(new DraftFromSpellbookEffect(spellbook), filter)); } private SlimefootThallidTransplant(final SlimefootThallidTransplant card) { diff --git a/Mage.Sets/src/mage/cards/s/SlingshotGoblin.java b/Mage.Sets/src/mage/cards/s/SlingshotGoblin.java index 16cd0477d76..71031f1e7b2 100644 --- a/Mage.Sets/src/mage/cards/s/SlingshotGoblin.java +++ b/Mage.Sets/src/mage/cards/s/SlingshotGoblin.java @@ -16,6 +16,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class SlingshotGoblin extends CardImpl { // {R}, {tap}: Slingshot Goblin deals 2 damage to target blue creature. Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(2), new ManaCostsImpl<>("{R}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SlinnVodaTheRisingDeep.java b/Mage.Sets/src/mage/cards/s/SlinnVodaTheRisingDeep.java index 69914bc1fce..598b4389652 100644 --- a/Mage.Sets/src/mage/cards/s/SlinnVodaTheRisingDeep.java +++ b/Mage.Sets/src/mage/cards/s/SlinnVodaTheRisingDeep.java @@ -1,11 +1,8 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandFromBattlefieldAllEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -16,8 +13,9 @@ import mage.constants.SuperType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class SlinnVodaTheRisingDeep extends CardImpl { @@ -25,14 +23,11 @@ public final class SlinnVodaTheRisingDeep extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); static { - filter.add(Predicates.not( - Predicates.or( - SubType.KRAKEN.getPredicate(), - SubType.LEVIATHAN.getPredicate(), - SubType.OCTOPUS.getPredicate(), - SubType.MERFOLK.getPredicate(), - SubType.SERPENT.getPredicate()) - )); + filter.add(Predicates.not(SubType.MERFOLK.getPredicate())); + filter.add(Predicates.not(SubType.KRAKEN.getPredicate())); + filter.add(Predicates.not(SubType.LEVIATHAN.getPredicate())); + filter.add(Predicates.not(SubType.OCTOPUS.getPredicate())); + filter.add(Predicates.not(SubType.SERPENT.getPredicate())); } public SlinnVodaTheRisingDeep(UUID ownerId, CardSetInfo setInfo) { @@ -47,13 +42,11 @@ public final class SlinnVodaTheRisingDeep extends CardImpl { this.addAbility(new KickerAbility("{1}{U}")); // When Slinn Voda, the Rising Deep enters the battlefield, if it was kicked, return all creatures to their owners' hands except for Merfolk, Krakens, Leviathans, Octopuses, and Serpents. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new ReturnToHandFromBattlefieldAllEffect(filter)), - KickedCondition.ONCE, - "when {this} enters, if it was kicked, " - + "return all creatures to their owners' hands except for " - + "Merfolk, Krakens, Leviathans, Octopuses, and Serpents." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new ReturnToHandFromBattlefieldAllEffect(filter) + .setText("return all creatures to their owners' hands except for " + + "Merfolk, Krakens, Leviathans, Octopuses, and Serpents") + ).withInterveningIf(KickedCondition.ONCE)); } private SlinnVodaTheRisingDeep(final SlinnVodaTheRisingDeep card) { diff --git a/Mage.Sets/src/mage/cards/s/SlipOnTheRing.java b/Mage.Sets/src/mage/cards/s/SlipOnTheRing.java index 236b405d3b2..98c80fc5587 100644 --- a/Mage.Sets/src/mage/cards/s/SlipOnTheRing.java +++ b/Mage.Sets/src/mage/cards/s/SlipOnTheRing.java @@ -9,6 +9,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -27,7 +28,7 @@ public final class SlipOnTheRing extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}"); // Exile target creature you own, then return it to the battlefield under your control. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new ExileThenReturnTargetEffect(true, false)); // The Ring tempts you. this.getSpellAbility().addEffect(new TheRingTemptsYouEffect()); diff --git a/Mage.Sets/src/mage/cards/s/SliverHive.java b/Mage.Sets/src/mage/cards/s/SliverHive.java index 3a6ecaf21d9..98cf77e5fb3 100644 --- a/Mage.Sets/src/mage/cards/s/SliverHive.java +++ b/Mage.Sets/src/mage/cards/s/SliverHive.java @@ -1,11 +1,11 @@ - package mage.cards.s; import mage.abilities.Ability; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.mana.ColorlessManaAbility; import mage.abilities.mana.ConditionalAnyColorManaAbility; @@ -14,7 +14,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.FilterSpell; import mage.filter.common.FilterControlledPermanent; import mage.game.permanent.token.SliverToken; @@ -22,36 +21,36 @@ import mage.game.permanent.token.SliverToken; import java.util.UUID; /** - * * @author emerald000 */ public final class SliverHive extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent("Sliver"); private static final FilterSpell filterSpell = new FilterSpell("a Sliver spell"); static { - } - - static { - filter.add(SubType.SLIVER.getPredicate()); filterSpell.add(SubType.SLIVER.getPredicate()); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPermanent(SubType.SLIVER, "you control a Sliver") + ); + public SliverHive(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.LAND},""); + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); // {T}: Add {C}. this.addAbility(new ColorlessManaAbility()); // {T}: Add one mana of any color. Spend this mana only to cast a Sliver spell. - this.addAbility(new ConditionalAnyColorManaAbility(new TapSourceCost(), 1, new ConditionalSpellManaBuilder(filterSpell), true)); + this.addAbility(new ConditionalAnyColorManaAbility( + new TapSourceCost(), 1, new ConditionalSpellManaBuilder(filterSpell), true + )); // {5}, {T}: Create a 1/1 colorless Sliver creature token. Activate this ability only if you control a Sliver. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new SliverToken()), new TapSourceCost(), - new PermanentsOnTheBattlefieldCondition(filter), - "{5}, {T}: Create a 1/1 colorless Sliver creature token. Activate only if you control a Sliver."); - ability.addCost(new GenericManaCost(5)); + Ability ability = new ActivateIfConditionActivatedAbility( + new CreateTokenEffect(new SliverToken()), new GenericManaCost(5), condition + ); + ability.addCost(new TapSourceCost()); this.addAbility(ability); } @@ -63,4 +62,4 @@ public final class SliverHive extends CardImpl { public SliverHive copy() { return new SliverHive(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/s/SmellFear.java b/Mage.Sets/src/mage/cards/s/SmellFear.java index 61d944332fe..17427d15649 100644 --- a/Mage.Sets/src/mage/cards/s/SmellFear.java +++ b/Mage.Sets/src/mage/cards/s/SmellFear.java @@ -6,8 +6,8 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -27,7 +27,7 @@ public final class SmellFear extends CardImpl { "
Target creature you control fights up to one target creature you don't control" )); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 1, StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL, false)); + this.getSpellAbility().addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); } private SmellFear(final SmellFear card) { diff --git a/Mage.Sets/src/mage/cards/s/SmeltWardGatekeepers.java b/Mage.Sets/src/mage/cards/s/SmeltWardGatekeepers.java index 1e74e613adc..61544fadbaa 100644 --- a/Mage.Sets/src/mage/cards/s/SmeltWardGatekeepers.java +++ b/Mage.Sets/src/mage/cards/s/SmeltWardGatekeepers.java @@ -3,39 +3,26 @@ package mage.cards.s; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.condition.Condition; -import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.YouControlTwoOrMoreGatesCondition; import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; -import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.common.GatesYouControlHint; import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.filter.StaticFilters; -import mage.filter.common.FilterControlledPermanent; -import mage.target.Target; -import mage.target.common.TargetCreaturePermanent; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.target.common.TargetOpponentsCreaturePermanent; import java.util.UUID; /** * @author LevelX2 */ - - public final class SmeltWardGatekeepers extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent(); - - static { - filter.add(SubType.GATE.getPredicate()); - } - - private static final Condition gatesCondition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1); - public SmeltWardGatekeepers(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}"); this.subtype.add(SubType.HUMAN); @@ -45,16 +32,14 @@ public final class SmeltWardGatekeepers extends CardImpl { this.toughness = new MageInt(4); // When Smelt-Ward Gatekeepers enters the battlefield, if you control two or more Gates, gain control of target creature an opponent controls until end of turn. Untap that creature. That creature gains haste until end of turn. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new GainControlTargetEffect(Duration.EndOfTurn)), - gatesCondition, - "When {this} enters, if you control two or more Gates, gain control of target creature an opponent controls until end of turn. Untap that creature. It gains haste until end of turn."); - ability.addEffect(new UntapTargetEffect()); - ability.addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn)); - Target target = new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE); - ability.addTarget(target); - ability.addHint(new ConditionHint(gatesCondition, "You control two or more Gates")); - this.addAbility(ability); + Ability ability = new EntersBattlefieldTriggeredAbility(new GainControlTargetEffect(Duration.EndOfTurn)) + .withInterveningIf(YouControlTwoOrMoreGatesCondition.instance); + ability.addEffect(new UntapTargetEffect().setText("untap that creature")); + ability.addEffect(new GainAbilityTargetEffect( + HasteAbility.getInstance(), Duration.EndOfTurn + ).setText("It gains haste until end of turn")); + ability.addTarget(new TargetOpponentsCreaturePermanent()); + this.addAbility(ability.addHint(GatesYouControlHint.instance)); } private SmeltWardGatekeepers(final SmeltWardGatekeepers card) { diff --git a/Mage.Sets/src/mage/cards/s/SmeltWardIgnus.java b/Mage.Sets/src/mage/cards/s/SmeltWardIgnus.java index 2a7a7220155..1467a4a06b0 100644 --- a/Mage.Sets/src/mage/cards/s/SmeltWardIgnus.java +++ b/Mage.Sets/src/mage/cards/s/SmeltWardIgnus.java @@ -14,6 +14,7 @@ import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -48,7 +49,7 @@ public final class SmeltWardIgnus extends CardImpl { HasteAbility.getInstance(), Duration.EndOfTurn ).setText("It gains haste until end of turn")); ability.addCost(new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SmirkingSpelljacker.java b/Mage.Sets/src/mage/cards/s/SmirkingSpelljacker.java index 47a815e0176..c81d986891e 100644 --- a/Mage.Sets/src/mage/cards/s/SmirkingSpelljacker.java +++ b/Mage.Sets/src/mage/cards/s/SmirkingSpelljacker.java @@ -6,7 +6,6 @@ import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.effects.common.MayCastTargetCardEffect; @@ -60,12 +59,7 @@ public final class SmirkingSpelljacker extends CardImpl { this.addAbility(ability); // Whenever Smirking Spelljacker attacks, if a card is exiled with it, you may cast the exiled card without paying its mana cost. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new SmirkingSpelljackerEffect()), - SmirkingSpelljackerCondition.instance, - "Whenever {this} attacks, if a card is exiled with it, " - + "you may cast the exiled card without paying its mana cost." - )); + this.addAbility(new AttacksTriggeredAbility(new SmirkingSpelljackerEffect()).withInterveningIf(SmirkingSpelljackerCondition.instance)); } private SmirkingSpelljacker(final SmirkingSpelljacker card) { @@ -90,7 +84,7 @@ enum SmirkingSpelljackerCondition implements Condition { @Override public String toString() { - return "if a card is exiled with it"; + return "a card is exiled with it"; } } @@ -126,4 +120,4 @@ class SmirkingSpelljackerEffect extends OneShotEffect { return true; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/s/Smite.java b/Mage.Sets/src/mage/cards/s/Smite.java index 442335ce236..e30744e8355 100644 --- a/Mage.Sets/src/mage/cards/s/Smite.java +++ b/Mage.Sets/src/mage/cards/s/Smite.java @@ -8,6 +8,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.BlockedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -27,7 +28,7 @@ public final class Smite extends CardImpl { // Destroy target blocked creature. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect(false)); } diff --git a/Mage.Sets/src/mage/cards/s/SmokeTeller.java b/Mage.Sets/src/mage/cards/s/SmokeTeller.java index 77efc054b4e..7ddaebac3f0 100644 --- a/Mage.Sets/src/mage/cards/s/SmokeTeller.java +++ b/Mage.Sets/src/mage/cards/s/SmokeTeller.java @@ -18,6 +18,7 @@ import mage.filter.predicate.card.FaceDownPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -44,7 +45,7 @@ public final class SmokeTeller extends CardImpl { // 1U: Look at target face-down creature. Ability ability = new SimpleActivatedAbility(new SmokeTellerLookFaceDownEffect(), new ManaCostsImpl<>("{1}{U}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/Smother.java b/Mage.Sets/src/mage/cards/s/Smother.java index 05b6892795a..9c3b204c490 100644 --- a/Mage.Sets/src/mage/cards/s/Smother.java +++ b/Mage.Sets/src/mage/cards/s/Smother.java @@ -9,6 +9,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ManaValuePredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -27,7 +28,7 @@ public final class Smother extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{B}"); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); } diff --git a/Mage.Sets/src/mage/cards/s/SnakeOfTheGoldenGrove.java b/Mage.Sets/src/mage/cards/s/SnakeOfTheGoldenGrove.java index 0ce84366155..a7a4090dcf8 100644 --- a/Mage.Sets/src/mage/cards/s/SnakeOfTheGoldenGrove.java +++ b/Mage.Sets/src/mage/cards/s/SnakeOfTheGoldenGrove.java @@ -1,12 +1,8 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TributeNotPaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.keyword.TributeAbility; import mage.cards.CardImpl; @@ -14,25 +10,25 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class SnakeOfTheGoldenGrove extends CardImpl { public SnakeOfTheGoldenGrove(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.SNAKE); this.power = new MageInt(4); this.toughness = new MageInt(4); - // Tribute 3
+ // Tribute 3 this.addAbility(new TributeAbility(3)); + // When Snake of the Golden Grove enters the battlefield, if tribute wasn't paid, you gain 4 life. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new GainLifeEffect(4), false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TributeNotPaidCondition.instance, - "When {this} enters, if tribute wasn't paid, you gain 4 life.")); + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(4)).withInterveningIf(TributeNotPaidCondition.instance)); } private SnakeOfTheGoldenGrove(final SnakeOfTheGoldenGrove card) { diff --git a/Mage.Sets/src/mage/cards/s/SnarlingGorehound.java b/Mage.Sets/src/mage/cards/s/SnarlingGorehound.java index 56f5cc6ba15..bce9fa9c418 100644 --- a/Mage.Sets/src/mage/cards/s/SnarlingGorehound.java +++ b/Mage.Sets/src/mage/cards/s/SnarlingGorehound.java @@ -1,7 +1,7 @@ package mage.cards.s; import mage.MageInt; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.keyword.SurveilEffect; import mage.abilities.keyword.MenaceAbility; import mage.cards.CardImpl; @@ -10,7 +10,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.SubType; import mage.filter.FilterPermanent; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.mageobject.PowerPredicate; @@ -22,7 +22,7 @@ import java.util.UUID; public final class SnarlingGorehound extends CardImpl { private static final FilterPermanent filter - = new FilterCreaturePermanent("another creature with power 2 or less"); + = new FilterControlledCreaturePermanent("another creature you control with power 2 or less"); static { filter.add(AnotherPredicate.instance); @@ -40,7 +40,7 @@ public final class SnarlingGorehound extends CardImpl { this.addAbility(new MenaceAbility(false)); // Whenever another creature with power 2 or less you control enters, surveil 1. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility(new SurveilEffect(1), filter)); + this.addAbility(new EntersBattlefieldAllTriggeredAbility(new SurveilEffect(1), filter)); } private SnarlingGorehound(final SnarlingGorehound card) { diff --git a/Mage.Sets/src/mage/cards/s/SnarlingUndorak.java b/Mage.Sets/src/mage/cards/s/SnarlingUndorak.java index c9e393437e2..97b19a55261 100644 --- a/Mage.Sets/src/mage/cards/s/SnarlingUndorak.java +++ b/Mage.Sets/src/mage/cards/s/SnarlingUndorak.java @@ -15,6 +15,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -37,7 +38,7 @@ public final class SnarlingUndorak extends CardImpl { // {2}{G}: Target Beast creature gets +1/+1 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(1, 1, Duration.EndOfTurn), new ManaCostsImpl<>("{2}{G}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // Morph {1}{G}{G} this.addAbility(new MorphAbility(this, new ManaCostsImpl<>("{1}{G}{G}"))); diff --git a/Mage.Sets/src/mage/cards/s/SnowFortress.java b/Mage.Sets/src/mage/cards/s/SnowFortress.java index 1276c396fdf..7a45faf73e4 100644 --- a/Mage.Sets/src/mage/cards/s/SnowFortress.java +++ b/Mage.Sets/src/mage/cards/s/SnowFortress.java @@ -19,6 +19,7 @@ import mage.constants.Zone; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; import mage.filter.common.FilterCreatureAttackingYou; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -51,7 +52,7 @@ public final class SnowFortress extends CardImpl { // {3}: Snow Fortress deals 1 damage to target creature without flying that's attacking you. Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new GenericManaCost(3)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SnowHound.java b/Mage.Sets/src/mage/cards/s/SnowHound.java index eafb9f224bb..3d61ad59192 100644 --- a/Mage.Sets/src/mage/cards/s/SnowHound.java +++ b/Mage.Sets/src/mage/cards/s/SnowHound.java @@ -1,52 +1,48 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; 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.Effect; +import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.ReturnToHandSourceEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect; 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.mageobject.ColorPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author fireshoes */ public final class SnowHound extends CardImpl { private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("green or blue creature"); + static { filter.add(Predicates.or( new ColorPredicate(ObjectColor.GREEN), - new ColorPredicate(ObjectColor.BLUE))); + new ColorPredicate(ObjectColor.BLUE) + )); } public SnowHound(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.DOG); this.power = new MageInt(1); this.toughness = new MageInt(1); // {1}, {tap}: Return Snow Hound and target green or blue creature you control to their owner's hand. - Effect effect = new ReturnToHandSourceEffect(true); - effect.setText("Return {this}"); - Ability ability = new SimpleActivatedAbility(effect, new ManaCostsImpl<>("{1}")); + Ability ability = new SimpleActivatedAbility(new ReturnToHandSourceEffect(true).setText("Return {this}"), new GenericManaCost(1)); ability.addCost(new TapSourceCost()); - effect = new ReturnToHandTargetEffect(); - effect.setText("and target green or blue creature you control to their owner's hand"); - ability.addTarget(new TargetControlledCreaturePermanent(filter)); - ability.addEffect(effect); + ability.addEffect(new ReturnToHandTargetEffect().setText("and target green or blue creature you control to their owner's hand")); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SnuffOut.java b/Mage.Sets/src/mage/cards/s/SnuffOut.java index 2d22affd606..03a750a1f52 100644 --- a/Mage.Sets/src/mage/cards/s/SnuffOut.java +++ b/Mage.Sets/src/mage/cards/s/SnuffOut.java @@ -10,10 +10,13 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; import mage.filter.common.FilterLandPermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author LevelX2 @@ -36,7 +39,7 @@ public final class SnuffOut extends CardImpl { // // Destroy target nonblack creature. It can't be regenerated. this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); } private SnuffOut(final SnuffOut card) { diff --git a/Mage.Sets/src/mage/cards/s/SoShiny.java b/Mage.Sets/src/mage/cards/s/SoShiny.java index b93d68566e8..3dd86bde66f 100644 --- a/Mage.Sets/src/mage/cards/s/SoShiny.java +++ b/Mage.Sets/src/mage/cards/s/SoShiny.java @@ -5,7 +5,6 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.DontUntapInControllersUntapStepEnchantedEffect; import mage.abilities.effects.common.TapEnchantedEffect; @@ -31,14 +30,14 @@ import java.util.UUID; */ public final class SoShiny extends CardImpl { - private static final FilterPermanent filter = new FilterControlledPermanent(); + private static final FilterPermanent filter = new FilterControlledPermanent("you control a token"); static { filter.add(TokenPredicate.TRUE); } private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); - private static final Hint hint = new ConditionHint(condition, "You control a token"); + private static final Hint hint = new ConditionHint(condition); public SoShiny(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); @@ -49,16 +48,11 @@ public final class SoShiny extends CardImpl { TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // When So Shiny enters the battlefield, if you control a token, tap enchanted creature, then scry 2. - ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new TapEnchantedEffect()), - condition, "When {this} enters, " + - "if you control a token, tap enchanted creature, then scry 2." - ); - ability.addEffect(new ScryEffect(2)); + Ability ability = new EntersBattlefieldTriggeredAbility(new TapEnchantedEffect()).withInterveningIf(condition); + ability.addEffect(new ScryEffect(2).concatBy(", then")); this.addAbility(ability.addHint(hint)); // Enchanted creature doesn't untap during its controller's untap step. diff --git a/Mage.Sets/src/mage/cards/s/SoaringLightbringer.java b/Mage.Sets/src/mage/cards/s/SoaringLightbringer.java index ffde788564e..388f6ca634b 100644 --- a/Mage.Sets/src/mage/cards/s/SoaringLightbringer.java +++ b/Mage.Sets/src/mage/cards/s/SoaringLightbringer.java @@ -2,7 +2,7 @@ package mage.cards.s; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.AttacksPlayerWithCreaturesTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; @@ -13,9 +13,7 @@ import mage.constants.*; import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; -import mage.game.events.GameEvent; import mage.game.permanent.token.GlimmerToken; -import mage.target.targetpointer.FixedTarget; import java.util.UUID; @@ -47,7 +45,7 @@ public final class SoaringLightbringer extends CardImpl { ))); // Whenever you attack a player, create a 1/1 white Glimmer enchantment creature token that's tapped and attacking that player. - this.addAbility(new SoaringLightbringerTriggeredAbility()); + this.addAbility(new AttacksPlayerWithCreaturesTriggeredAbility(new SoaringLightbringerEffect(), SetTargetPointer.PLAYER)); } private SoaringLightbringer(final SoaringLightbringer card) { @@ -60,37 +58,6 @@ public final class SoaringLightbringer extends CardImpl { } } -class SoaringLightbringerTriggeredAbility extends TriggeredAbilityImpl { - - SoaringLightbringerTriggeredAbility() { - super(Zone.BATTLEFIELD, new SoaringLightbringerEffect()); - setTriggerPhrase("Whenever you attack a player, "); - } - - private SoaringLightbringerTriggeredAbility(final SoaringLightbringerTriggeredAbility ability) { - super(ability); - } - - @Override - public SoaringLightbringerTriggeredAbility copy() { - return new SoaringLightbringerTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DEFENDER_ATTACKED; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (!isControlledBy(event.getPlayerId()) || game.getPlayer(event.getTargetId()) == null) { - return false; - } - this.getEffects().setTargetPointer(new FixedTarget(event.getTargetId())); - return true; - } -} - class SoaringLightbringerEffect extends OneShotEffect { SoaringLightbringerEffect() { diff --git a/Mage.Sets/src/mage/cards/s/SokenzanRenegade.java b/Mage.Sets/src/mage/cards/s/SokenzanRenegade.java index 18a06add7df..3383750f36d 100644 --- a/Mage.Sets/src/mage/cards/s/SokenzanRenegade.java +++ b/Mage.Sets/src/mage/cards/s/SokenzanRenegade.java @@ -1,25 +1,27 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.abilities.keyword.BushidoAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.game.permanent.Permanent; import mage.players.Player; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class SokenzanRenegade extends CardImpl { @@ -36,12 +38,8 @@ public final class SokenzanRenegade extends CardImpl { // At the beginning of your upkeep, if a player has more cards in hand than each other player, // the player who has the most cards in hand gains control of Sokenzan Renegade. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new SokenzanRenegadeEffect()), - OnePlayerHasTheMostCards.instance, - "At the beginning of your upkeep, if a player has more cards in hand than each other player, the player who has the most cards in hand gains control of {this}" - )); - + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SokenzanRenegadeEffect()) + .withInterveningIf(OnePlayerHasTheMostCards.instance)); } private SokenzanRenegade(final SokenzanRenegade card) { diff --git a/Mage.Sets/src/mage/cards/s/SoldeviSentry.java b/Mage.Sets/src/mage/cards/s/SoldeviSentry.java index a6ce6342c42..d721d8dc604 100644 --- a/Mage.Sets/src/mage/cards/s/SoldeviSentry.java +++ b/Mage.Sets/src/mage/cards/s/SoldeviSentry.java @@ -32,7 +32,7 @@ public final class SoldeviSentry extends CardImpl { new DrawCardTargetEffect(1, true), false ), true) - .setText("Choose target opponent. Regenerate Soldevi Sentry. " + .setText("Choose target opponent. Regenerate {this}. " + "When it regenerates this way, that player may draw a card"), new GenericManaCost(1) ); @@ -48,4 +48,4 @@ public final class SoldeviSentry extends CardImpl { public SoldeviSentry copy() { return new SoldeviSentry(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/s/SoldierReplica.java b/Mage.Sets/src/mage/cards/s/SoldierReplica.java index 302d0c9aa97..f98e0f7b6cc 100644 --- a/Mage.Sets/src/mage/cards/s/SoldierReplica.java +++ b/Mage.Sets/src/mage/cards/s/SoldierReplica.java @@ -14,6 +14,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterAttackingOrBlockingCreature; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -29,7 +30,7 @@ public final class SoldierReplica extends CardImpl { this.toughness = new MageInt(3); Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(3, "it"), new ManaCostsImpl<>("{1}{W}")); ability.addCost(new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(new FilterAttackingOrBlockingCreature())); + ability.addTarget(new TargetPermanent(new FilterAttackingOrBlockingCreature())); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SoltariVisionary.java b/Mage.Sets/src/mage/cards/s/SoltariVisionary.java index aef0cc4f2a6..1571fe604f3 100644 --- a/Mage.Sets/src/mage/cards/s/SoltariVisionary.java +++ b/Mage.Sets/src/mage/cards/s/SoltariVisionary.java @@ -1,32 +1,31 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; +import mage.abilities.common.DealsDamageToAPlayerTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.ShadowAbility; 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.FilterEnchantmentPermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; -import mage.game.permanent.Permanent; import mage.target.TargetPermanent; +import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class SoltariVisionary extends CardImpl { + private static final FilterPermanent filter = new FilterEnchantmentPermanent("enchantment that player controls"); + public SoltariVisionary(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{W}"); this.subtype.add(SubType.SOLTARI); this.subtype.add(SubType.CLERIC); @@ -37,7 +36,10 @@ public final class SoltariVisionary extends CardImpl { this.addAbility(ShadowAbility.getInstance()); // Whenever Soltari Visionary deals damage to a player, destroy target enchantment that player controls. - this.addAbility(new SoltariVisionaryTriggeredAbility()); + Ability ability = new DealsDamageToAPlayerTriggeredAbility(new DestroyTargetEffect(), false, true); + ability.addTarget(new TargetPermanent(filter)); + ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster()); + this.addAbility(ability); } private SoltariVisionary(final SoltariVisionary card) { @@ -49,43 +51,3 @@ public final class SoltariVisionary extends CardImpl { return new SoltariVisionary(this); } } - -class SoltariVisionaryTriggeredAbility extends TriggeredAbilityImpl { - - SoltariVisionaryTriggeredAbility() { - super(Zone.BATTLEFIELD, new DestroyTargetEffect(), false); - } - - private SoltariVisionaryTriggeredAbility(final SoltariVisionaryTriggeredAbility ability) { - super(ability); - } - - @Override - public SoltariVisionaryTriggeredAbility copy() { - return new SoltariVisionaryTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - Permanent soltari = game.getPermanent(event.getSourceId()); - if (soltari != null && soltari.getId().equals(this.getSourceId())) { - FilterEnchantmentPermanent filter = new FilterEnchantmentPermanent("enchantment that player controls."); - filter.add(new ControllerIdPredicate(event.getPlayerId())); - filter.setMessage("enchantment controlled by " + game.getPlayer(event.getTargetId()).getLogName()); - this.getTargets().clear(); - this.addTarget(new TargetPermanent(filter)); - return true; - } - return false; - } - - @Override - public String getRule() { - return "Whenever {this} deals damage to a player, destroy target enchantment that player controls."; - } -} diff --git a/Mage.Sets/src/mage/cards/s/SomberwaldStag.java b/Mage.Sets/src/mage/cards/s/SomberwaldStag.java index 3d3e33fda47..c308b1a6e1e 100644 --- a/Mage.Sets/src/mage/cards/s/SomberwaldStag.java +++ b/Mage.Sets/src/mage/cards/s/SomberwaldStag.java @@ -10,10 +10,13 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author LevelX2 */ @@ -29,7 +32,7 @@ public final class SomberwaldStag extends CardImpl { Effect effect = new FightTargetSourceEffect(); effect.setText("you may have it fight target creature you don't control"); Ability ability = new EntersBattlefieldTriggeredAbility(effect, true); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + ability.addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/Somnophore.java b/Mage.Sets/src/mage/cards/s/Somnophore.java index cca5c21f436..cf65ad0ca5f 100644 --- a/Mage.Sets/src/mage/cards/s/Somnophore.java +++ b/Mage.Sets/src/mage/cards/s/Somnophore.java @@ -23,6 +23,7 @@ import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -91,7 +92,7 @@ class SomnophoreTriggeredAbility extends TriggeredAbilityImpl { filter.add(new ControllerIdPredicate(opponent.getId())); this.getTargets().clear(); - this.addTarget(new TargetCreaturePermanent(filter)); + this.addTarget(new TargetPermanent(filter)); return true; } } diff --git a/Mage.Sets/src/mage/cards/s/Songstitcher.java b/Mage.Sets/src/mage/cards/s/Songstitcher.java index 6d5a8e93dd1..13cb7d6112d 100644 --- a/Mage.Sets/src/mage/cards/s/Songstitcher.java +++ b/Mage.Sets/src/mage/cards/s/Songstitcher.java @@ -15,6 +15,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.filter.common.FilterAttackingCreature; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class Songstitcher extends CardImpl { // {1}{W}: Prevent all combat damage that would be dealt this turn by target attacking creature with flying. Ability ability = new SimpleActivatedAbility(new PreventDamageByTargetEffect(Duration.EndOfTurn, true) .withTextOptions(true, false), new ManaCostsImpl<>("{1}{W}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SonicTheHedgehog.java b/Mage.Sets/src/mage/cards/s/SonicTheHedgehog.java new file mode 100644 index 00000000000..aa5ee9e48c8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SonicTheHedgehog.java @@ -0,0 +1,72 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.common.DealtDamageAnyTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.counter.AddCountersAllEffect; +import mage.abilities.keyword.FlashAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SetTargetPointer; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.game.permanent.token.TreasureToken; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SonicTheHedgehog extends CardImpl { + + private static final FilterPermanent filter + = new FilterControlledCreaturePermanent("creature you control with flash or haste"); + + static { + filter.add(Predicates.or( + new AbilityPredicate(FlashAbility.class), + new AbilityPredicate(HasteAbility.class) + )); + } + + public SonicTheHedgehog(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{R}{W}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HEDGEHOG); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // Gotta Go Fast -- Whenever Sonic the Hedgehog attacks, put a +1/+1 counter on each creature you control with flash or haste. + this.addAbility(new EntersBattlefieldTriggeredAbility( + new AddCountersAllEffect(CounterType.P1P1.createInstance(), filter) + ).withFlavorWord("Gotta Go Fast")); + + // Whenever a creature you control with flash or haste is dealt damage, create a tapped Treasure token. + this.addAbility(new DealtDamageAnyTriggeredAbility( + new CreateTokenEffect(new TreasureToken(), 1, true), + filter, SetTargetPointer.NONE, false + )); + } + + private SonicTheHedgehog(final SonicTheHedgehog card) { + super(card); + } + + @Override + public SonicTheHedgehog copy() { + return new SonicTheHedgehog(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SootstokeKindler.java b/Mage.Sets/src/mage/cards/s/SootstokeKindler.java index c6cf8cf842a..d23d40e26e6 100644 --- a/Mage.Sets/src/mage/cards/s/SootstokeKindler.java +++ b/Mage.Sets/src/mage/cards/s/SootstokeKindler.java @@ -17,6 +17,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -46,7 +47,7 @@ public final class SootstokeKindler extends CardImpl { SimpleActivatedAbility ability = new SimpleActivatedAbility( new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SoratamiMirrorGuard.java b/Mage.Sets/src/mage/cards/s/SoratamiMirrorGuard.java index fad971a7a4b..7f888ef5bc4 100644 --- a/Mage.Sets/src/mage/cards/s/SoratamiMirrorGuard.java +++ b/Mage.Sets/src/mage/cards/s/SoratamiMirrorGuard.java @@ -20,6 +20,7 @@ import mage.filter.common.FilterControlledLandPermanent; import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; @@ -49,7 +50,7 @@ public final class SoratamiMirrorGuard extends CardImpl { // {2}, Return a land you control to its owner's hand: Target creature with power 2 or less can't be blocked this turn. Ability ability = new SimpleActivatedAbility(new CantBeBlockedTargetEffect(), new GenericManaCost(2)); ability.addCost(new ReturnToHandChosenControlledPermanentCost(new TargetControlledPermanent(filter))); - ability.addTarget(new TargetCreaturePermanent(filterCreature)); + ability.addTarget(new TargetPermanent(filterCreature)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SorayaTheFalconer.java b/Mage.Sets/src/mage/cards/s/SorayaTheFalconer.java index 7548831e065..9727f7bdf80 100644 --- a/Mage.Sets/src/mage/cards/s/SorayaTheFalconer.java +++ b/Mage.Sets/src/mage/cards/s/SorayaTheFalconer.java @@ -18,8 +18,11 @@ import mage.constants.SubType; import mage.constants.SuperType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.constants.SubType.BIRD; + /** * * @author L_J @@ -39,7 +42,7 @@ public final class SorayaTheFalconer extends CardImpl { // {1}{W}: Target Bird creature gains banding until end of turn. Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(BandingAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{1}{W}")); - ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent(SubType.BIRD, "Bird creature"))); + ability.addTarget(new TargetPermanent(new FilterCreaturePermanent(BIRD, "Bird creature"))); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SorceressQueen.java b/Mage.Sets/src/mage/cards/s/SorceressQueen.java index 1c7f147aefe..21dacda5a1e 100644 --- a/Mage.Sets/src/mage/cards/s/SorceressQueen.java +++ b/Mage.Sets/src/mage/cards/s/SorceressQueen.java @@ -15,6 +15,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,7 +39,7 @@ public final class SorceressQueen extends CardImpl { // {tap}: Target creature other than Sorceress Queen becomes 0/2 until end of turn. Ability ability = new SimpleActivatedAbility(new SetBasePowerToughnessTargetEffect(0, 2, Duration.EndOfTurn), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SorinOfHouseMarkov.java b/Mage.Sets/src/mage/cards/s/SorinOfHouseMarkov.java index 9064d66d8b2..ccbbb37b09e 100644 --- a/Mage.Sets/src/mage/cards/s/SorinOfHouseMarkov.java +++ b/Mage.Sets/src/mage/cards/s/SorinOfHouseMarkov.java @@ -1,17 +1,15 @@ package mage.cards.s; import mage.MageInt; -import mage.constants.Pronoun; -import mage.abilities.triggers.BeginningOfPostcombatMainTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.YouGainedLifeCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ExileAndReturnSourceEffect; import mage.abilities.hint.ConditionHint; import mage.abilities.hint.Hint; import mage.abilities.keyword.ExtortAbility; import mage.abilities.keyword.LifelinkAbility; import mage.abilities.keyword.TransformAbility; +import mage.abilities.triggers.BeginningOfPostcombatMainTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -24,8 +22,8 @@ import java.util.UUID; */ public final class SorinOfHouseMarkov extends CardImpl { - private static final Condition condition = new YouGainedLifeCondition(ComparisonType.OR_GREATER, 3); - private static final Hint hint = new ConditionHint(condition, "You gained 3 or more life this turn"); + private static final Condition condition = new YouGainedLifeCondition(ComparisonType.MORE_THAN, 2); + private static final Hint hint = new ConditionHint(condition); public SorinOfHouseMarkov(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); @@ -46,14 +44,9 @@ public final class SorinOfHouseMarkov extends CardImpl { // At the beginning of your postcombat main phase, if you gained 3 or more life this turn, exile Sorin of House Markov, then return him to the battlefield transformed under his owner's control. this.addAbility(new TransformAbility()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfPostcombatMainTriggeredAbility( - new ExileAndReturnSourceEffect(PutCards.BATTLEFIELD_TRANSFORMED, Pronoun.SHE), - false - ), condition, "At the beginning of your postcombat main phase, " - + "if you gained 3 or more life this turn, exile {this}, " - + "then return him to the battlefield transformed under his owner's control." - ).addHint(hint), new PlayerGainedLifeWatcher()); + this.addAbility(new BeginningOfPostcombatMainTriggeredAbility( + new ExileAndReturnSourceEffect(PutCards.BATTLEFIELD_TRANSFORMED, Pronoun.HE), false + ).withInterveningIf(condition).addHint(hint), new PlayerGainedLifeWatcher()); } private SorinOfHouseMarkov(final SorinOfHouseMarkov card) { diff --git a/Mage.Sets/src/mage/cards/s/SotheraTheSupervoid.java b/Mage.Sets/src/mage/cards/s/SotheraTheSupervoid.java new file mode 100644 index 00000000000..e4750c3fb71 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SotheraTheSupervoid.java @@ -0,0 +1,170 @@ +package mage.cards.s; + +import mage.abilities.Ability; +import mage.abilities.common.DiesCreatureTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SuperType; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.counters.Counters; +import mage.filter.StaticFilters; +import mage.game.ExileZone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.TargetPermanent; +import mage.target.common.TargetCardInExile; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.util.CardUtil; +import mage.util.RandomUtil; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SotheraTheSupervoid extends CardImpl { + + public SotheraTheSupervoid(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{B}"); + + this.supertype.add(SuperType.LEGENDARY); + + // Whenever a creature you control dies, each opponent chooses a creature they control and exiles it. + this.addAbility(new DiesCreatureTriggeredAbility( + new SotheraTheSupervoidExileEffect(), false, + StaticFilters.FILTER_CONTROLLED_A_CREATURE + )); + + // At the beginning of your end step, if a player controls no creatures, sacrifice Sothera, then put a creature card exiled with it onto the battlefield under your control with two additional +1/+1 counters on it. + Ability ability = new BeginningOfEndStepTriggeredAbility(new SacrificeSourceEffect()) + .withInterveningIf(SotheraTheSupervoidCondition.instance); + ability.addEffect(new SotheraTheSupervoidReturnEffect()); + this.addAbility(ability); + } + + private SotheraTheSupervoid(final SotheraTheSupervoid card) { + super(card); + } + + @Override + public SotheraTheSupervoid copy() { + return new SotheraTheSupervoid(this); + } +} + +enum SotheraTheSupervoidCondition implements Condition { + instance; + + @Override + public boolean apply(Game game, Ability source) { + return game + .getState() + .getPlayersInRange(source.getControllerId(), game) + .stream() + .anyMatch(playerId -> !game.getBattlefield().contains( + StaticFilters.FILTER_CONTROLLED_CREATURE, playerId, source, game, 1 + )); + } + + @Override + public String toString() { + return "a player controls no creatures"; + } +} + +class SotheraTheSupervoidExileEffect extends OneShotEffect { + + SotheraTheSupervoidExileEffect() { + super(Outcome.Benefit); + staticText = "each opponent chooses a creature they control and exiles it"; + } + + private SotheraTheSupervoidExileEffect(final SotheraTheSupervoidExileEffect effect) { + super(effect); + } + + @Override + public SotheraTheSupervoidExileEffect copy() { + return new SotheraTheSupervoidExileEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (UUID playerId : game.getOpponents(source.getControllerId())) { + Player player = game.getPlayer(playerId); + if (player == null || !game.getBattlefield().contains( + StaticFilters.FILTER_CONTROLLED_CREATURE, playerId, source, game, 1 + )) { + return false; + } + TargetPermanent target = new TargetControlledCreaturePermanent(); + target.withChooseHint("to exile"); + target.withNotTarget(true); + player.choose(Outcome.Exile, target, source, game); + Permanent permanent = game.getPermanent(target.getFirstTarget()); + if (permanent == null) { + continue; + } + player.moveCardsToExile( + permanent, source, game, true, + CardUtil.getExileZoneId(game, source), + CardUtil.getSourceName(game, source) + ); + } + return true; + } +} + +class SotheraTheSupervoidReturnEffect extends OneShotEffect { + + SotheraTheSupervoidReturnEffect() { + super(Outcome.Benefit); + staticText = ", then put a creature card exiled with it onto the battlefield " + + "under your control with two additional +1/+1 counters on it"; + } + + private SotheraTheSupervoidReturnEffect(final SotheraTheSupervoidReturnEffect effect) { + super(effect); + } + + @Override + public SotheraTheSupervoidReturnEffect copy() { + return new SotheraTheSupervoidReturnEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source)); + if (player == null || exileZone == null) { + return false; + } + Card card; + switch (exileZone.count(StaticFilters.FILTER_CARD_CREATURE, game)) { + case 0: + return false; + case 1: + card = RandomUtil.randomFromCollection(exileZone.getCards(StaticFilters.FILTER_CARD_CREATURE, game)); + break; + default: + TargetCard target = new TargetCardInExile(StaticFilters.FILTER_CARD_CREATURE, exileZone.getId()); + player.choose(outcome, target, source, game); + card = game.getCard(target.getFirstTarget()); + } + if (card == null) { + return false; + } + game.setEnterWithCounters(card.getId(), new Counters(CounterType.P1P1.createInstance(2))); + return player.moveCards(card, Zone.BATTLEFIELD, source, game); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SoulExchange.java b/Mage.Sets/src/mage/cards/s/SoulExchange.java index 5770ae38cda..a8882481600 100644 --- a/Mage.Sets/src/mage/cards/s/SoulExchange.java +++ b/Mage.Sets/src/mage/cards/s/SoulExchange.java @@ -1,6 +1,5 @@ package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.costs.Cost; import mage.abilities.costs.common.ExileTargetCost; @@ -16,7 +15,9 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCardInYourGraveyard; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; + +import java.util.UUID; /** * @author MarcoMarin @@ -27,12 +28,11 @@ public final class SoulExchange extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{B}{B}"); // As an additional cost to cast Soul Exchange, exile a creature you control. - Cost cost = new ExileTargetCost(new TargetControlledCreaturePermanent(StaticFilters.FILTER_CONTROLLED_A_CREATURE)); - this.getSpellAbility().addCost(cost); + this.getSpellAbility().addCost(new ExileTargetCost(new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_A_CREATURE))); + // Return target creature card from your graveyard to the battlefield. Put a +2/+2 counter on that creature if the exiled creature was a Thrull. this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); this.getSpellAbility().addEffect(new SoulExchangeEffect()); - } private SoulExchange(final SoulExchange card) { diff --git a/Mage.Sets/src/mage/cards/s/SoulReap.java b/Mage.Sets/src/mage/cards/s/SoulReap.java index 0a8ed8ac482..974447cffe7 100644 --- a/Mage.Sets/src/mage/cards/s/SoulReap.java +++ b/Mage.Sets/src/mage/cards/s/SoulReap.java @@ -18,6 +18,7 @@ import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.game.stack.Spell; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.watchers.Watcher; @@ -39,7 +40,7 @@ public final class SoulReap extends CardImpl { // Destroy target nongreen creature. Its controller loses 3 life if you've cast another black spell this turn. this.getSpellAbility().addEffect(new SoulReapEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addWatcher(new SoulReapWatcher()); } diff --git a/Mage.Sets/src/mage/cards/s/SoulSeizer.java b/Mage.Sets/src/mage/cards/s/SoulSeizer.java index 43db8c735ff..f7e7b786183 100644 --- a/Mage.Sets/src/mage/cards/s/SoulSeizer.java +++ b/Mage.Sets/src/mage/cards/s/SoulSeizer.java @@ -19,6 +19,7 @@ import mage.game.events.DamagedPlayerEvent; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -84,7 +85,7 @@ class SoulSeizerTriggeredAbility extends TriggeredAbilityImpl { filter.add(new ControllerIdPredicate(opponent.getId())); this.getTargets().clear(); - this.addTarget(new TargetCreaturePermanent(filter)); + this.addTarget(new TargetPermanent(filter)); return true; } } diff --git a/Mage.Sets/src/mage/cards/s/SoulShred.java b/Mage.Sets/src/mage/cards/s/SoulShred.java index 32bc68bb3de..c938ec8f5e7 100644 --- a/Mage.Sets/src/mage/cards/s/SoulShred.java +++ b/Mage.Sets/src/mage/cards/s/SoulShred.java @@ -7,8 +7,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author fireshoes @@ -20,7 +23,7 @@ public final class SoulShred extends CardImpl { // Soul Shred deals 3 damage to target nonblack creature. You gain 3 life. this.getSpellAbility().addEffect(new DamageTargetEffect(3)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.getSpellAbility().addEffect(new GainLifeEffect(3)); } diff --git a/Mage.Sets/src/mage/cards/s/SoulSnare.java b/Mage.Sets/src/mage/cards/s/SoulSnare.java index caa87d4258c..9e9bfb02baa 100644 --- a/Mage.Sets/src/mage/cards/s/SoulSnare.java +++ b/Mage.Sets/src/mage/cards/s/SoulSnare.java @@ -12,6 +12,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Zone; import mage.filter.common.FilterCreatureAttackingYou; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -28,7 +29,7 @@ public final class SoulSnare extends CardImpl { Ability ability = new SimpleActivatedAbility( new ExileTargetEffect(), new ManaCostsImpl<>("{W}")); ability.addCost(new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(new FilterCreatureAttackingYou(true))); + ability.addTarget(new TargetPermanent(new FilterCreatureAttackingYou(true))); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SoulSwallower.java b/Mage.Sets/src/mage/cards/s/SoulSwallower.java index 53a2b1ca105..a6968c90ef4 100644 --- a/Mage.Sets/src/mage/cards/s/SoulSwallower.java +++ b/Mage.Sets/src/mage/cards/s/SoulSwallower.java @@ -1,20 +1,20 @@ package mage.cards.s; -import java.util.UUID; - import mage.MageInt; -import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.DeliriumCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; import mage.counters.CounterType; +import java.util.UUID; + /** * @author fireshoes */ @@ -30,12 +30,8 @@ public final class SoulSwallower extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // Delirium — At the beginning of your upkeep, if there are four or more card types among cards in your graveyard, put three +1/+1 counters on Soul Swallower. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(3))), - DeliriumCondition.instance, - "Delirium — At the beginning of your upkeep, if there are four or more card types among cards in your graveyard, " - + "put three +1/+1 counters on Soul Swallower.") - .addHint(CardTypesInGraveyardCount.YOU.getHint())); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(3))) + .withInterveningIf(DeliriumCondition.instance).setAbilityWord(AbilityWord.DELIRIUM).addHint(CardTypesInGraveyardCount.YOU.getHint())); } private SoulSwallower(final SoulSwallower card) { diff --git a/Mage.Sets/src/mage/cards/s/Soulherder.java b/Mage.Sets/src/mage/cards/s/Soulherder.java index 57c5499b6a7..c26f70fec1c 100644 --- a/Mage.Sets/src/mage/cards/s/Soulherder.java +++ b/Mage.Sets/src/mage/cards/s/Soulherder.java @@ -2,10 +2,10 @@ package mage.cards.s; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.ZoneChangeTriggeredAbility; import mage.abilities.effects.common.ExileThenReturnTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -18,7 +18,7 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -41,7 +41,7 @@ public final class Soulherder extends CardImpl { Ability ability = new BeginningOfEndStepTriggeredAbility(TargetController.YOU, new ExileThenReturnTargetEffect(false, true), true ); - ability.addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SoulhunterRakshasa.java b/Mage.Sets/src/mage/cards/s/SoulhunterRakshasa.java index d3b9c723caa..a1f38766859 100644 --- a/Mage.Sets/src/mage/cards/s/SoulhunterRakshasa.java +++ b/Mage.Sets/src/mage/cards/s/SoulhunterRakshasa.java @@ -4,18 +4,15 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.CantBlockAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.condition.common.CastFromEverywhereSourceCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.condition.common.CastFromHandSourcePermanentCondition; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +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.SubType; -import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledPermanent; -import mage.game.Game; -import mage.players.Player; import mage.target.common.TargetOpponent; import mage.watchers.common.CastFromHandWatcher; @@ -26,6 +23,8 @@ import java.util.UUID; */ public final class SoulhunterRakshasa extends CardImpl { + private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.SWAMP)); + public SoulhunterRakshasa(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); this.subtype.add(SubType.DEMON); @@ -37,10 +36,9 @@ public final class SoulhunterRakshasa extends CardImpl { this.addAbility(new CantBlockAbility()); // When Soulhunter Rakshasa enters the battlefield, if you cast it from your hand, it deals 1 damage to target opponent for each Swamp you control. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new SoulhunterRakshasaEffect()), - CastFromEverywhereSourceCondition.instance, - "When {this} enters, if you cast it from your hand, it deals 1 damage to target opponent for each Swamp you control."); + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(xValue)) + .withInterveningIf(CastFromHandSourcePermanentCondition.instance) + .withRuleTextReplacement(true); ability.addTarget(new TargetOpponent()); this.addAbility(ability, new CastFromHandWatcher()); } @@ -54,35 +52,3 @@ public final class SoulhunterRakshasa extends CardImpl { return new SoulhunterRakshasa(this); } } - -class SoulhunterRakshasaEffect extends OneShotEffect { - - private static final FilterPermanent filter = new FilterControlledPermanent(SubType.SWAMP); - - public SoulhunterRakshasaEffect() { - super(Outcome.Damage); - this.staticText = "{this} deals 1 damage to target opponent for each Swamp you control."; - } - - private SoulhunterRakshasaEffect(final SoulhunterRakshasaEffect effect) { - super(effect); - } - - @Override - public SoulhunterRakshasaEffect copy() { - return new SoulhunterRakshasaEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - int amount = game.getBattlefield().count(filter, source.getControllerId(), source, game); - if (amount > 0) { - Player player = game.getPlayer(source.getFirstTarget()); - if (player != null) { - player.damage(amount, source.getSourceId(), source, game); - return true; - } - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/s/SoulswornSpirit.java b/Mage.Sets/src/mage/cards/s/SoulswornSpirit.java index fbde9965605..145c1e407b8 100644 --- a/Mage.Sets/src/mage/cards/s/SoulswornSpirit.java +++ b/Mage.Sets/src/mage/cards/s/SoulswornSpirit.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; @@ -11,17 +9,17 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.StaticFilters; -import mage.target.common.TargetCreaturePermanent; +import mage.target.common.TargetOpponentsCreaturePermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class SoulswornSpirit extends CardImpl { - + public SoulswornSpirit(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); this.subtype.add(SubType.SPIRIT); this.power = new MageInt(2); @@ -29,12 +27,11 @@ public final class SoulswornSpirit extends CardImpl { // Soulsworn Spirit can't be blocked. this.addAbility(new CantBeBlockedSourceAbility()); - + // When Soulsworn Spirit enters the battlefield, detain target creature an opponent controls. //(Until your next turn, that creature can't attack or block and its activated abilities can't be activated.) Ability ability = new EntersBattlefieldTriggeredAbility(new DetainTargetEffect()); - TargetCreaturePermanent target = new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE); - ability.addTarget(target); + ability.addTarget(new TargetOpponentsCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SowingMycospawn.java b/Mage.Sets/src/mage/cards/s/SowingMycospawn.java index dc43d599d5f..ecdd609024b 100644 --- a/Mage.Sets/src/mage/cards/s/SowingMycospawn.java +++ b/Mage.Sets/src/mage/cards/s/SowingMycospawn.java @@ -3,7 +3,6 @@ package mage.cards.s; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CastSourceTriggeredAbility; import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; @@ -44,11 +43,7 @@ public final class SowingMycospawn extends CardImpl { ))); // When you cast this spell, if it was kicked, exile target land. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new CastSourceTriggeredAbility(new ExileTargetEffect()), - KickedCondition.ONCE, "When you cast this spell, " + - "if it was kicked, exile target land." - ); + Ability ability = new CastSourceTriggeredAbility(new ExileTargetEffect()).withInterveningIf(KickedCondition.ONCE); ability.addTarget(new TargetLandPermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SpaceMarineScout.java b/Mage.Sets/src/mage/cards/s/SpaceMarineScout.java index 4f87b52b5bf..ba9f9ba53b9 100644 --- a/Mage.Sets/src/mage/cards/s/SpaceMarineScout.java +++ b/Mage.Sets/src/mage/cards/s/SpaceMarineScout.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.OpponentControlsMoreCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.VigilanceAbility; @@ -46,12 +45,9 @@ public final class SpaceMarineScout extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // Concealed Position -- When Space Marine Scout enters the battlefield, if an opponent controls more lands than you, you may search your library for a Plains card, put it onto the battlefield tapped, then shuffle. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new SearchLibraryPutInPlayEffect( - new TargetCardInLibrary(filter), true - ), true), condition, "When {this} enters, if an opponent controls more lands " + - "than you, you may search your library for a Plains card, put it onto the battlefield tapped, then shuffle." - ).withFlavorWord("Concealed Position")); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter), true), true + ).withInterveningIf(condition).withFlavorWord("Concealed Position")); } private SpaceMarineScout(final SpaceMarineScout card) { diff --git a/Mage.Sets/src/mage/cards/s/SparkElemental.java b/Mage.Sets/src/mage/cards/s/SparkElemental.java index 890dafc2fc3..980f6de38b4 100644 --- a/Mage.Sets/src/mage/cards/s/SparkElemental.java +++ b/Mage.Sets/src/mage/cards/s/SparkElemental.java @@ -1,26 +1,25 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.game.events.GameEvent.EventType; +import mage.constants.TargetController; + +import java.util.UUID; /** - * * @author North */ public final class SparkElemental extends CardImpl { public SparkElemental(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}"); this.subtype.add(SubType.ELEMENTAL); this.power = new MageInt(3); @@ -28,7 +27,9 @@ public final class SparkElemental extends CardImpl { this.addAbility(TrampleAbility.getInstance()); this.addAbility(HasteAbility.getInstance()); - this.addAbility(new OnEventTriggeredAbility(EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new SacrificeSourceEffect())); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.NEXT, new SacrificeSourceEffect(), false + )); } private SparkElemental(final SparkElemental card) { diff --git a/Mage.Sets/src/mage/cards/s/SpeakerOfTheHeavens.java b/Mage.Sets/src/mage/cards/s/SpeakerOfTheHeavens.java index 2ced7bd3b9f..2fcfaa3cfb0 100644 --- a/Mage.Sets/src/mage/cards/s/SpeakerOfTheHeavens.java +++ b/Mage.Sets/src/mage/cards/s/SpeakerOfTheHeavens.java @@ -12,7 +12,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.TimingRule; -import mage.constants.Zone; import mage.game.permanent.token.AngelToken; import java.util.UUID; @@ -38,10 +37,8 @@ public final class SpeakerOfTheHeavens extends CardImpl { // {T}: Create a 4/4 white Angel creature token with flying. Activate only if you have at least 7 more life than your starting life total and only as a sorcery. this.addAbility(new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new CreateTokenEffect(new AngelToken()), - new TapSourceCost(), MoreThanStartingLifeTotalCondition.SEVEN, - TimingRule.SORCERY - )); + new CreateTokenEffect(new AngelToken()), new TapSourceCost(), MoreThanStartingLifeTotalCondition.SEVEN + ).setTiming(TimingRule.SORCERY)); } private SpeakerOfTheHeavens(final SpeakerOfTheHeavens card) { @@ -52,4 +49,4 @@ public final class SpeakerOfTheHeavens extends CardImpl { public SpeakerOfTheHeavens copy() { return new SpeakerOfTheHeavens(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/s/SpearOfHeliod.java b/Mage.Sets/src/mage/cards/s/SpearOfHeliod.java index 9222b5f5eaa..85de10c7bbd 100644 --- a/Mage.Sets/src/mage/cards/s/SpearOfHeliod.java +++ b/Mage.Sets/src/mage/cards/s/SpearOfHeliod.java @@ -17,6 +17,7 @@ import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.other.DamagedPlayerThisTurnPredicate; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -44,7 +45,7 @@ public final class SpearOfHeliod extends CardImpl { // {1}{W}{W}, {T}: Destroy target creature that dealt damage to you this turn. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new ManaCostsImpl<>("{1}{W}{W}")); ability.addCost(new TapSourceCost()); - Target target = new TargetCreaturePermanent(filter); + Target target = new TargetPermanent(filter); ability.addTarget(target); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SpearbreakerBehemoth.java b/Mage.Sets/src/mage/cards/s/SpearbreakerBehemoth.java index 6c1c66b5f8d..ecbc1fc64d5 100644 --- a/Mage.Sets/src/mage/cards/s/SpearbreakerBehemoth.java +++ b/Mage.Sets/src/mage/cards/s/SpearbreakerBehemoth.java @@ -16,6 +16,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -43,7 +44,7 @@ public final class SpearbreakerBehemoth extends CardImpl { SimpleActivatedAbility ability = new SimpleActivatedAbility( new GainAbilityTargetEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{1}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SpellweaverDuo.java b/Mage.Sets/src/mage/cards/s/SpellweaverDuo.java index 56d4e05bd79..8bb8dc88462 100644 --- a/Mage.Sets/src/mage/cards/s/SpellweaverDuo.java +++ b/Mage.Sets/src/mage/cards/s/SpellweaverDuo.java @@ -13,6 +13,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class SpellweaverDuo extends CardImpl { // When Spellweaver Duo enters the battlefield, you may return target tapped creature to its owner's hand. Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SpikeRogue.java b/Mage.Sets/src/mage/cards/s/SpikeRogue.java index 60054497861..0873b0b5323 100644 --- a/Mage.Sets/src/mage/cards/s/SpikeRogue.java +++ b/Mage.Sets/src/mage/cards/s/SpikeRogue.java @@ -1,6 +1,5 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; @@ -14,14 +13,13 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.counters.CounterType; -import mage.filter.StaticFilters; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class SpikeRogue extends CardImpl { @@ -43,7 +41,7 @@ public final class SpikeRogue extends CardImpl { // {2}, Remove a +1/+1 counter from a creature you control: Put a +1/+1 counter on Spike Rogue. Ability ability2 = new SimpleActivatedAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(1)), new GenericManaCost(2)); - ability2.addCost(new RemoveCounterCost(new TargetControlledCreaturePermanent(1, 1, StaticFilters.FILTER_CONTROLLED_CREATURE, true), CounterType.P1P1)); + ability2.addCost(new RemoveCounterCost(new TargetControlledCreaturePermanent(), CounterType.P1P1)); this.addAbility(ability2); } diff --git a/Mage.Sets/src/mage/cards/s/SpinalVillain.java b/Mage.Sets/src/mage/cards/s/SpinalVillain.java index 024d66d413c..939bbe18f1e 100644 --- a/Mage.Sets/src/mage/cards/s/SpinalVillain.java +++ b/Mage.Sets/src/mage/cards/s/SpinalVillain.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -37,7 +38,7 @@ public final class SpinalVillain extends CardImpl { // {tap}: Destroy target blue creature. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SpinningDarkness.java b/Mage.Sets/src/mage/cards/s/SpinningDarkness.java index 5d69e872bc7..11fccebbb95 100644 --- a/Mage.Sets/src/mage/cards/s/SpinningDarkness.java +++ b/Mage.Sets/src/mage/cards/s/SpinningDarkness.java @@ -22,8 +22,11 @@ import mage.filter.StaticFilters; import mage.filter.predicate.mageobject.ColorPredicate; import mage.game.Game; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author emerald000 @@ -39,7 +42,7 @@ public final class SpinningDarkness extends CardImpl { // Spinning Darkness deals 3 damage to target nonblack creature. You gain 3 life. this.getSpellAbility().addEffect(new DamageTargetEffect(3)); this.getSpellAbility().addEffect(new GainLifeEffect(3)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); } private SpinningDarkness(final SpinningDarkness card) { diff --git a/Mage.Sets/src/mage/cards/s/SpinyStarfish.java b/Mage.Sets/src/mage/cards/s/SpinyStarfish.java index a4b9a5b1f5e..74f9d145ae3 100644 --- a/Mage.Sets/src/mage/cards/s/SpinyStarfish.java +++ b/Mage.Sets/src/mage/cards/s/SpinyStarfish.java @@ -1,22 +1,26 @@ package mage.cards.s; import mage.MageInt; +import mage.MageObjectReference; import mage.abilities.Ability; -import mage.abilities.triggers.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.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.RegenerateSourceEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; 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.constants.WatcherScope; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.token.StarfishToken; +import mage.util.CardUtil; import mage.watchers.Watcher; import java.util.HashMap; @@ -38,16 +42,9 @@ public final class SpinyStarfish extends CardImpl { this.addAbility(new SimpleActivatedAbility(new RegenerateSourceEffect(), new ManaCostsImpl<>("{U}"))); // At the beginning of each end step, if Spiny Starfish regenerated this turn, create a 0/1 blue Starfish creature token for each time it regenerated this turn. - this.addAbility( - new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - TargetController.ANY, new CreateTokenEffect( - new StarfishToken(), - new SpinyStarfishDynamicValue()), - false), - SpinyStarfishCondition.instance, - "At the beginning of each end step, if {this} regenerated this turn, create a 0/1 blue Starfish creature token for each time it regenerated this turn."), - new SpinyStarfishWatcher()); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.ANY, new CreateTokenEffect(new StarfishToken(), SpinyStarfishValue.instance), false + ).withInterveningIf(SpinyStarfishCondition.instance), new SpinyStarfishWatcher()); } private SpinyStarfish(final SpinyStarfish card) { @@ -66,66 +63,26 @@ enum SpinyStarfishCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - SpinyStarfishWatcher watcher = game.getState().getWatcher(SpinyStarfishWatcher.class); - return watcher != null && watcher.regeneratedCount(source.getSourceId()) != 0; + return SpinyStarfishWatcher.regeneratedCount(game, source) > 0; } @Override public String toString() { - return "if Spiny Starfish regenerated this turn"; + return "{this} regenerated this turn"; } - } -class SpinyStarfishWatcher extends Watcher { - - // Probably dumb to record all regeneration events, could just record this, - // but not sure how to know what source this watcher is attached to. - private final Map regeneratedCount = new HashMap<>(); - - public SpinyStarfishWatcher() { - super(WatcherScope.GAME); - } - - @Override - public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.REGENERATED) { - UUID regeneratedId = event.getTargetId(); - Integer count = regeneratedCount.get(regeneratedId); - if (count == null) { - count = 0; - } - regeneratedCount.put(regeneratedId, ++count); - } - } - - @Override - public void reset() { - super.reset(); - regeneratedCount.clear(); - } - - public int regeneratedCount(UUID sourceId) { - return regeneratedCount.getOrDefault(sourceId, 0); - } - -} - -class SpinyStarfishDynamicValue implements DynamicValue { +enum SpinyStarfishValue implements DynamicValue { + instance; @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - SpinyStarfishWatcher watcher = game.getState().getWatcher( - SpinyStarfishWatcher.class); - if (watcher != null) { - return watcher.regeneratedCount(sourceAbility.getSourceId()); - } - return 0; + return SpinyStarfishWatcher.regeneratedCount(game, sourceAbility); } @Override - public SpinyStarfishDynamicValue copy() { - return new SpinyStarfishDynamicValue(); + public SpinyStarfishValue copy() { + return this; } @Override @@ -135,6 +92,35 @@ class SpinyStarfishDynamicValue implements DynamicValue { @Override public String getMessage() { - return "time {this} regenerated this turn"; + return "time it regenerated this turn"; + } +} + +class SpinyStarfishWatcher extends Watcher { + + private final Map regeneratedCount = new HashMap<>(); + + public SpinyStarfishWatcher() { + super(WatcherScope.GAME); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.REGENERATED) { + regeneratedCount.compute(new MageObjectReference(event.getTargetId(), game), CardUtil::setOrIncrementValue); + } + } + + @Override + public void reset() { + super.reset(); + regeneratedCount.clear(); + } + + static int regeneratedCount(Game game, Ability source) { + return game.getState() + .getWatcher(SpinyStarfishWatcher.class) + .regeneratedCount + .getOrDefault(new MageObjectReference(source.getSourcePermanentOrLKI(game), game), 0); } } diff --git a/Mage.Sets/src/mage/cards/s/SpiresOfOrazca.java b/Mage.Sets/src/mage/cards/s/SpiresOfOrazca.java index 09c1026c17e..2e8945aa7e9 100644 --- a/Mage.Sets/src/mage/cards/s/SpiresOfOrazca.java +++ b/Mage.Sets/src/mage/cards/s/SpiresOfOrazca.java @@ -16,6 +16,7 @@ import mage.constants.TargetController; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.AttackingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -45,7 +46,7 @@ public final class SpiresOfOrazca extends CardImpl { effect = new RemoveFromCombatTargetEffect(); effect.setText(" "); ability.addEffect(effect); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SpiritBonds.java b/Mage.Sets/src/mage/cards/s/SpiritBonds.java index d421a43a230..5bdf691fdc3 100644 --- a/Mage.Sets/src/mage/cards/s/SpiritBonds.java +++ b/Mage.Sets/src/mage/cards/s/SpiritBonds.java @@ -20,6 +20,7 @@ import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.game.permanent.token.SpiritWhiteToken; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; @@ -49,7 +50,7 @@ public final class SpiritBonds extends CardImpl { Ability ability = new SimpleActivatedAbility( new GainAbilityTargetEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{1}{W}")); ability.addCost(new SacrificeTargetCost(filterSpirit)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SpiritMirror.java b/Mage.Sets/src/mage/cards/s/SpiritMirror.java index 27046c43c6f..1e304c1d5e3 100644 --- a/Mage.Sets/src/mage/cards/s/SpiritMirror.java +++ b/Mage.Sets/src/mage/cards/s/SpiritMirror.java @@ -1,45 +1,45 @@ - package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.FilterPermanent; import mage.filter.predicate.permanent.TokenPredicate; import mage.game.permanent.token.ReflectionToken; import mage.target.TargetPermanent; +import java.util.UUID; + /** * @author LevelX2 */ public final class SpiritMirror extends CardImpl { - private static final FilterPermanent filterToken = new FilterPermanent(SubType.REFLECTION, "Reflection token"); + private static final FilterPermanent filterToken = new FilterPermanent(SubType.REFLECTION, "there are no Reflection tokens on the battlefield"); private static final FilterPermanent filter = new FilterPermanent("Reflection"); static { - filterToken.add(SubType.REFLECTION.getPredicate()); filterToken.add(TokenPredicate.TRUE); filter.add(SubType.REFLECTION.getPredicate()); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filterToken, ComparisonType.EQUAL_TO, 0, false); + public SpiritMirror(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); // At the beginning of your upkeep, if there are no Reflection tokens on the battlefield, create a 2/2 white Reflection creature token. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new ReflectionToken())), - new PermanentsOnTheBattlefieldCondition(filterToken, ComparisonType.EQUAL_TO, 0, false), - "At the beginning of your upkeep, if there are no Reflection tokens on the battlefield, create a 2/2 white Reflection creature token.")); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new CreateTokenEffect(new ReflectionToken())).withInterveningIf(condition)); // {0}: Destroy target Reflection. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new GenericManaCost(0)); diff --git a/Mage.Sets/src/mage/cards/s/SpiritWeaver.java b/Mage.Sets/src/mage/cards/s/SpiritWeaver.java index 15767aca4b7..97f81729947 100644 --- a/Mage.Sets/src/mage/cards/s/SpiritWeaver.java +++ b/Mage.Sets/src/mage/cards/s/SpiritWeaver.java @@ -17,6 +17,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -41,7 +42,7 @@ public final class SpiritWeaver extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(1); Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(0, 1, Duration.EndOfTurn), new GenericManaCost(2)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SpiritualSanctuary.java b/Mage.Sets/src/mage/cards/s/SpiritualSanctuary.java index 81619d25157..a29b5f56efe 100644 --- a/Mage.Sets/src/mage/cards/s/SpiritualSanctuary.java +++ b/Mage.Sets/src/mage/cards/s/SpiritualSanctuary.java @@ -1,11 +1,9 @@ - package mage.cards.s; -import java.util.UUID; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -13,32 +11,28 @@ import mage.constants.SubType; import mage.constants.TargetController; import mage.filter.FilterPermanent; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class SpiritualSanctuary extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent(); + private static final FilterPermanent filter = new FilterPermanent(SubType.PLAINS, "that player controls a Plains"); static { - filter.add(SubType.PLAINS.getPredicate()); filter.add(TargetController.ACTIVE.getControllerPredicate()); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, false); + public SpiritualSanctuary(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); // At the beginning of each player's upkeep, if that player controls a Plains, they gain 1 life. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility( - TargetController.ANY, new GainLifeTargetEffect(1).setText("they gain 1 life"), - false - ), - new PermanentsOnTheBattlefieldCondition(filter), - "at the beginning of each player's upkeep, " - + "if that player controls a Plains, they gain 1 life" - )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + TargetController.EACH_PLAYER, new GainLifeTargetEffect(1).setText("they gain 1 life"), false + ).withInterveningIf(condition)); } private SpiritualSanctuary(final SpiritualSanctuary card) { diff --git a/Mage.Sets/src/mage/cards/s/SpiteMalice.java b/Mage.Sets/src/mage/cards/s/SpiteMalice.java index 27a4b2fc5fd..dd4cf56a26c 100644 --- a/Mage.Sets/src/mage/cards/s/SpiteMalice.java +++ b/Mage.Sets/src/mage/cards/s/SpiteMalice.java @@ -8,9 +8,12 @@ import mage.cards.SplitCard; import mage.constants.CardType; import mage.constants.SpellAbilityType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.TargetSpell; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author FenrisulfrX @@ -28,7 +31,7 @@ public final class SpiteMalice extends SplitCard { // Malice // Destroy target nonblack creature. It can't be regenerated. this.getRightHalfCard().getSpellAbility().addEffect(new DestroyTargetEffect(true)); - this.getRightHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getRightHalfCard().getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); } private SpiteMalice(final SpiteMalice card) { diff --git a/Mage.Sets/src/mage/cards/s/SplashySpellcaster.java b/Mage.Sets/src/mage/cards/s/SplashySpellcaster.java index 0bcdfb6ba40..c7ae29d71ab 100644 --- a/Mage.Sets/src/mage/cards/s/SplashySpellcaster.java +++ b/Mage.Sets/src/mage/cards/s/SplashySpellcaster.java @@ -12,12 +12,11 @@ import mage.constants.SubType; import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; /** - * * @author Susucr */ public final class SplashySpellcaster extends CardImpl { @@ -31,7 +30,7 @@ public final class SplashySpellcaster extends CardImpl { public SplashySpellcaster(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); - + this.subtype.add(SubType.ELEMENTAL); this.subtype.add(SubType.WIZARD); this.power = new MageInt(2); @@ -42,8 +41,7 @@ public final class SplashySpellcaster extends CardImpl { new CreateRoleAttachedTargetEffect(RoleType.SORCERER), StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false ); - ability.addTarget(new TargetControlledCreaturePermanent(0, 1, filter, false)); - + ability.addTarget(new TargetPermanent(0, 1, filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/Splinterfright.java b/Mage.Sets/src/mage/cards/s/Splinterfright.java index 318a8d17bee..716e03e6c8a 100644 --- a/Mage.Sets/src/mage/cards/s/Splinterfright.java +++ b/Mage.Sets/src/mage/cards/s/Splinterfright.java @@ -1,41 +1,43 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; import mage.abilities.effects.common.MillCardsControllerEffect; import mage.abilities.effects.common.continuous.SetBasePowerToughnessSourceEffect; import mage.abilities.keyword.TrampleAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; -import mage.filter.common.FilterCreatureCard; -import mage.game.events.GameEvent.EventType; +import mage.filter.StaticFilters; + +import java.util.UUID; /** - * * @author North */ public final class Splinterfright extends CardImpl { + private static final DynamicValue xValue = new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_CREATURES); + public Splinterfright(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); this.subtype.add(SubType.ELEMENTAL); this.power = new MageInt(0); this.toughness = new MageInt(0); this.addAbility(TrampleAbility.getInstance()); + // Splinterfright's power and toughness are each equal to the number of creature cards in your graveyard. - CardsInControllerGraveyardCount count = new CardsInControllerGraveyardCount(new FilterCreatureCard("creature cards")); - this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetBasePowerToughnessSourceEffect(count))); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetBasePowerToughnessSourceEffect(xValue))); + // At the beginning of your upkeep, put the top two cards of your library into your graveyard. - this.addAbility(new OnEventTriggeredAbility(EventType.UPKEEP_STEP_PRE, "beginning of your upkeep", new MillCardsControllerEffect(2), false)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new MillCardsControllerEffect(2))); } private Splinterfright(final Splinterfright card) { diff --git a/Mage.Sets/src/mage/cards/s/SplitTheParty.java b/Mage.Sets/src/mage/cards/s/SplitTheParty.java index 21ab34362f1..3815306dc2c 100644 --- a/Mage.Sets/src/mage/cards/s/SplitTheParty.java +++ b/Mage.Sets/src/mage/cards/s/SplitTheParty.java @@ -1,9 +1,5 @@ package mage.cards.s; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; - import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; @@ -17,11 +13,14 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.TargetPlayer; -import mage.target.common.TargetCreaturePermanent; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; /** - * * @author weirddan455 */ public final class SplitTheParty extends CardImpl { @@ -72,7 +71,7 @@ class SplitThePartyEffect extends OneShotEffect { int halfCreatures = (numCreatures / 2) + (numCreatures % 2); FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures controlled by " + targetPlayer.getName()); filter.add(new ControllerIdPredicate(targetPlayer.getId())); - TargetCreaturePermanent target = new TargetCreaturePermanent(halfCreatures, halfCreatures, filter, true); + TargetPermanent target = new TargetPermanent(halfCreatures, halfCreatures, filter, true); if (controller.chooseTarget(outcome, target, source, game)) { Set cardsToHand = new HashSet<>(); for (UUID creatureId : target.getTargets()) { diff --git a/Mage.Sets/src/mage/cards/s/SporebackTroll.java b/Mage.Sets/src/mage/cards/s/SporebackTroll.java index d5ef05423f6..361679077be 100644 --- a/Mage.Sets/src/mage/cards/s/SporebackTroll.java +++ b/Mage.Sets/src/mage/cards/s/SporebackTroll.java @@ -14,8 +14,11 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_CREATURE_P1P1; + /** * * @author fireshoes @@ -34,7 +37,7 @@ public final class SporebackTroll extends CardImpl { // {1}{G}: Regenerate target creature with a +1/+1 counter on it. Ability ability = new SimpleActivatedAbility(new RegenerateTargetEffect(), new ManaCostsImpl<>("{1}{G}")); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_P1P1)); + ability.addTarget(new TargetPermanent(FILTER_CREATURE_P1P1)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/Sporogenesis.java b/Mage.Sets/src/mage/cards/s/Sporogenesis.java index 61960d3cf7c..29d093f1613 100644 --- a/Mage.Sets/src/mage/cards/s/Sporogenesis.java +++ b/Mage.Sets/src/mage/cards/s/Sporogenesis.java @@ -23,6 +23,7 @@ import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; import mage.game.permanent.token.SaprolingToken; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; @@ -44,7 +45,7 @@ public final class Sporogenesis extends CardImpl { // At the beginning of your upkeep, you may put a fungus counter on target nontoken creature. Ability ability = new BeginningOfUpkeepTriggeredAbility(new AddCountersTargetEffect(CounterType.FUNGUS.createInstance()), true); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // Whenever a creature with a fungus counter on it dies, create a 1/1 green Saproling creature token for each fungus counter on that creature. diff --git a/Mage.Sets/src/mage/cards/s/SpringleafDrum.java b/Mage.Sets/src/mage/cards/s/SpringleafDrum.java index 9a19176ec54..478c2a72f9a 100644 --- a/Mage.Sets/src/mage/cards/s/SpringleafDrum.java +++ b/Mage.Sets/src/mage/cards/s/SpringleafDrum.java @@ -1,33 +1,26 @@ - package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.costs.common.TapTargetCost; import mage.abilities.mana.AnyColorManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.filter.StaticFilters; + +import java.util.UUID; /** * @author Loki */ public final class SpringleafDrum extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); - - static { - filter.add(TappedPredicate.UNTAPPED); - } - public SpringleafDrum(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{1}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}"); + // {T}, Tap an untapped creature you control: Add one mana of any color. Ability ability = new AnyColorManaAbility(); - ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, false))); + ability.addCost(new TapTargetCost(StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SpyNetwork.java b/Mage.Sets/src/mage/cards/s/SpyNetwork.java index 036591054f7..98f916d29df 100644 --- a/Mage.Sets/src/mage/cards/s/SpyNetwork.java +++ b/Mage.Sets/src/mage/cards/s/SpyNetwork.java @@ -16,8 +16,8 @@ import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.TargetPlayer; -import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -103,7 +103,7 @@ class SpyNetworkFaceDownEffect extends OneShotEffect { FilterCreaturePermanent filter = new FilterCreaturePermanent("face down creature controlled by " + player.getLogName()); filter.add(FaceDownPredicate.instance); filter.add(new ControllerIdPredicate(player.getId())); - TargetCreaturePermanent target = new TargetCreaturePermanent(1, 1, filter, true); + TargetPermanent target = new TargetPermanent(1, 1, filter, true); if (target.canChoose(controller.getId(), source, game)) { while (controller.chooseUse(outcome, "Look at a face down creature controlled by " + player.getLogName() + "?", source, game)) { target.clearChosen(); diff --git a/Mage.Sets/src/mage/cards/s/SquadCommander.java b/Mage.Sets/src/mage/cards/s/SquadCommander.java index a4974b9e741..821fec403b8 100644 --- a/Mage.Sets/src/mage/cards/s/SquadCommander.java +++ b/Mage.Sets/src/mage/cards/s/SquadCommander.java @@ -2,16 +2,15 @@ package mage.cards.s; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.FullPartyCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.PartyCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.abilities.hint.common.PartyCountHint; import mage.abilities.keyword.IndestructibleAbility; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -36,23 +35,19 @@ public final class SquadCommander extends CardImpl { this.toughness = new MageInt(3); // When Squad Commander enters the battlefield, create a 1/1 white Kor Warrior creature token for each creature in your party. - this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect( - new KorWarriorToken(), PartyCount.instance) + this.addAbility(new EntersBattlefieldTriggeredAbility( + new CreateTokenEffect(new KorWarriorToken(), PartyCount.instance) ).addHint(PartyCountHint.instance)); // At the beginning of combat on your turn, if you have a full party, creatures you control get +1/+0 and gain indestructible until end of turn. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility( - new BoostControlledEffect( - 1, 0, Duration.EndOfTurn - ) - ), FullPartyCondition.instance, "At the beginning of combat on your turn, " + - "if you have a full party, creatures you control get +1/+0 and gain indestructible until end of turn." - ); + Ability ability = new BeginningOfCombatTriggeredAbility( + new BoostControlledEffect(1, 0, Duration.EndOfTurn) + .setText("creatures you control get +1/+0") + ).withInterveningIf(FullPartyCondition.instance); ability.addEffect(new GainAbilityAllEffect( IndestructibleAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURE - )); + ).setText("and gain indestructible until end of turn")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/StalkingAssassin.java b/Mage.Sets/src/mage/cards/s/StalkingAssassin.java index f0dfc6a5b67..506107506ec 100644 --- a/Mage.Sets/src/mage/cards/s/StalkingAssassin.java +++ b/Mage.Sets/src/mage/cards/s/StalkingAssassin.java @@ -16,6 +16,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -46,7 +47,7 @@ public final class StalkingAssassin extends CardImpl { // {3}{B}, {T}: Destroy target tapped creature. ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new ManaCostsImpl<>("{3}{B}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/StalkingYeti.java b/Mage.Sets/src/mage/cards/s/StalkingYeti.java index 3a9d6cc6a87..e8a2d84cc3b 100644 --- a/Mage.Sets/src/mage/cards/s/StalkingYeti.java +++ b/Mage.Sets/src/mage/cards/s/StalkingYeti.java @@ -1,29 +1,23 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateAsSorceryActivatedAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.SourceOnBattlefieldCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ReturnToHandSourceEffect; -import mage.constants.SubType; -import mage.constants.SuperType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetOpponentsCreaturePermanent; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class StalkingYeti extends CardImpl { @@ -37,18 +31,15 @@ public final class StalkingYeti extends CardImpl { this.toughness = new MageInt(3); // When Stalking Yeti enters the battlefield, if it's on the battlefield, it deals damage equal to its power to target creature an opponent controls and that creature deals damage equal to its power to Stalking Yeti. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new StalkingYetiEffect()), - SourceOnBattlefieldCondition.instance, - "When {this} enters, if it's on the battlefield, " - + "it deals damage equal to its power to target creature an opponent controls " - + "and that creature deals damage equal to its power to {this}." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new StalkingYetiEffect()) + .withInterveningIf(SourceOnBattlefieldCondition.instance); ability.addTarget(new TargetOpponentsCreaturePermanent()); this.addAbility(ability); // {2}{snow}: Return Stalking Yeti to its owner's hand. Activate this ability only any time you could cast a sorcery. - this.addAbility(new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandSourceEffect(true), new ManaCostsImpl<>("{2}{S}"))); + this.addAbility(new ActivateAsSorceryActivatedAbility( + Zone.BATTLEFIELD, new ReturnToHandSourceEffect(true), new ManaCostsImpl<>("{2}{S}") + )); } private StalkingYeti(final StalkingYeti card) { @@ -86,6 +77,7 @@ class StalkingYetiEffect extends OneShotEffect { return false; } thatCreature.damage(thisCreature.getPower().getValue(), thisCreature.getId(), source, game, false, true); + game.processAction(); thisCreature.damage(thatCreature.getPower().getValue(), thatCreature.getId(), source, game, false, true); return true; } diff --git a/Mage.Sets/src/mage/cards/s/StallionOfAshmouth.java b/Mage.Sets/src/mage/cards/s/StallionOfAshmouth.java index 4caf6afde6e..3a3c3075ba2 100644 --- a/Mage.Sets/src/mage/cards/s/StallionOfAshmouth.java +++ b/Mage.Sets/src/mage/cards/s/StallionOfAshmouth.java @@ -3,12 +3,15 @@ package mage.cards.s; import mage.MageInt; import mage.abilities.condition.common.DeliriumCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.AbilityWord; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; import java.util.UUID; @@ -26,8 +29,7 @@ public final class StallionOfAshmouth extends CardImpl { // Delirium — {1}{B}: Stallion of Ashmouth gets +1/+1 until end of turn. Activate this ability only if there are // four or more card types among cards in your graveyard. - this.addAbility(new ConditionalActivatedAbility( - Zone.BATTLEFIELD, + this.addAbility(new ActivateIfConditionActivatedAbility( new BoostSourceEffect(1, 1, Duration.EndOfTurn), new ManaCostsImpl<>("{1}{B}"), DeliriumCondition.instance ).setAbilityWord(AbilityWord.DELIRIUM).addHint(CardTypesInGraveyardCount.YOU.getHint())); diff --git a/Mage.Sets/src/mage/cards/s/StalwartPathlighter.java b/Mage.Sets/src/mage/cards/s/StalwartPathlighter.java index 5bc9270cbb8..16291ad8b2c 100644 --- a/Mage.Sets/src/mage/cards/s/StalwartPathlighter.java +++ b/Mage.Sets/src/mage/cards/s/StalwartPathlighter.java @@ -1,16 +1,18 @@ package mage.cards.s; import mage.MageInt; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.condition.common.CovenCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.hint.common.CovenHint; import mage.abilities.keyword.IndestructibleAbility; import mage.abilities.keyword.VigilanceAbility; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.AbilityWord; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; import mage.filter.StaticFilters; import java.util.UUID; @@ -32,14 +34,10 @@ public final class StalwartPathlighter extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // Coven — At the beginning of combat on your turn, if you control three or more creatures with different powers, creatures you control gain indestructible until end of turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility(new GainAbilityControlledEffect( - IndestructibleAbility.getInstance(), Duration.EndOfTurn, - StaticFilters.FILTER_CONTROLLED_CREATURE - )), CovenCondition.instance, "At the beginning " + - "of combat on your turn, if you control three or more creatures with different powers, " + - "creatures you control gain indestructible until end of turn." - ).addHint(CovenHint.instance).setAbilityWord(AbilityWord.COVEN)); + this.addAbility(new BeginningOfCombatTriggeredAbility(new GainAbilityControlledEffect( + IndestructibleAbility.getInstance(), Duration.EndOfTurn, + StaticFilters.FILTER_PERMANENT_CREATURES + )).withInterveningIf(CovenCondition.instance).addHint(CovenHint.instance).setAbilityWord(AbilityWord.COVEN)); } private StalwartPathlighter(final StalwartPathlighter card) { diff --git a/Mage.Sets/src/mage/cards/s/StampedeRider.java b/Mage.Sets/src/mage/cards/s/StampedeRider.java index b37887a022e..0ab8f2d272e 100644 --- a/Mage.Sets/src/mage/cards/s/StampedeRider.java +++ b/Mage.Sets/src/mage/cards/s/StampedeRider.java @@ -1,11 +1,11 @@ package mage.cards.s; import mage.MageInt; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; 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.TrampleAbility; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -31,13 +31,9 @@ public final class StampedeRider extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // At the beginning of each combat, if you control a creature with power 4 or greater, Stampede Rider gets +1/+1 until end of turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility( - TargetController.ANY, new BoostSourceEffect(1, 1, Duration.EndOfTurn), - false - ), FerociousCondition.instance, "At the beginning of each combat, " + - "if you control a creature with power 4 or greater, {this} gets +1/+1 until end of turn." - )); + this.addAbility(new BeginningOfCombatTriggeredAbility( + TargetController.ANY, new BoostSourceEffect(1, 1, Duration.EndOfTurn), false + ).withInterveningIf(FerociousCondition.instance).addHint(FerociousHint.instance)); } private StampedeRider(final StampedeRider card) { diff --git a/Mage.Sets/src/mage/cards/s/StampedingElkHerd.java b/Mage.Sets/src/mage/cards/s/StampedingElkHerd.java index f5b5a7bc4b7..6c54515a694 100644 --- a/Mage.Sets/src/mage/cards/s/StampedingElkHerd.java +++ b/Mage.Sets/src/mage/cards/s/StampedingElkHerd.java @@ -1,38 +1,35 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.FormidableCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.filter.common.FilterControlledCreaturePermanent; +import mage.constants.SubType; +import mage.filter.StaticFilters; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class StampedingElkHerd extends CardImpl { public StampedingElkHerd(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}"); this.subtype.add(SubType.ELK); this.power = new MageInt(5); this.toughness = new MageInt(5); // Formidable — Whenever Stampeding Elk Herd attacks, if creatures you control have total power 8 or greater, creatures you control gain trample until end of turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, new FilterControlledCreaturePermanent()), false), - FormidableCondition.instance, - "Formidable — Whenever {this} attacks, if creatures you control have total power 8 or greater, creatures you control gain trample until end of turn." - )); + this.addAbility(new AttacksTriggeredAbility(new GainAbilityControlledEffect( + TrampleAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURES + )).withInterveningIf(FormidableCondition.instance).setAbilityWord(AbilityWord.FORMIDABLE)); } private StampedingElkHerd(final StampedingElkHerd card) { diff --git a/Mage.Sets/src/mage/cards/s/StandOrFall.java b/Mage.Sets/src/mage/cards/s/StandOrFall.java index d9aa5f889b3..d17588f3ae2 100644 --- a/Mage.Sets/src/mage/cards/s/StandOrFall.java +++ b/Mage.Sets/src/mage/cards/s/StandOrFall.java @@ -1,9 +1,9 @@ package mage.cards.s; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.combat.CantBlockAllEffect; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -17,7 +17,7 @@ import mage.filter.predicate.permanent.PermanentReferenceInCollectionPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import java.util.ArrayList; import java.util.List; @@ -77,7 +77,7 @@ class StandOrFallEffect extends OneShotEffect { } FilterCreaturePermanent opponentFilter = new FilterCreaturePermanent(); opponentFilter.add(new ControllerIdPredicate(oppId)); - TargetCreaturePermanent creatures = new TargetCreaturePermanent(0, Integer.MAX_VALUE, opponentFilter, true); + TargetPermanent creatures = new TargetPermanent(0, Integer.MAX_VALUE, opponentFilter, true); List pile1 = new ArrayList<>(); if (player.choose(Outcome.Neutral, creatures, source, game)) { List targets = creatures.getTargets(); diff --git a/Mage.Sets/src/mage/cards/s/StarCrownedStag.java b/Mage.Sets/src/mage/cards/s/StarCrownedStag.java index ca39f3e5089..f83d6e64c96 100644 --- a/Mage.Sets/src/mage/cards/s/StarCrownedStag.java +++ b/Mage.Sets/src/mage/cards/s/StarCrownedStag.java @@ -12,6 +12,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.DefendingPlayerControlsSourceAttackingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -34,7 +35,7 @@ public final class StarCrownedStag extends CardImpl { // Whenever attacks, tap target creature defending player controls. Ability ability = new AttacksTriggeredAbility(new TapTargetEffect(), false); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/StarDestroyer.java b/Mage.Sets/src/mage/cards/s/StarDestroyer.java index 02bfcf1b8a1..f3a3ffc6a85 100644 --- a/Mage.Sets/src/mage/cards/s/StarDestroyer.java +++ b/Mage.Sets/src/mage/cards/s/StarDestroyer.java @@ -16,8 +16,9 @@ import mage.filter.common.FilterCreatureOrPlayer; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.game.permanent.token.TIEFighterToken; -import mage.target.common.TargetCreatureOrPlayer; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import mage.target.common.TargetPermanentOrPlayer; import java.util.UUID; @@ -45,7 +46,7 @@ public final class StarDestroyer extends CardImpl { // {2}{U}: Tap target artifact creature. Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new ManaCostsImpl<>("{2}{U}")); - ability.addTarget(new TargetCreaturePermanent(filter1)); + ability.addTarget(new TargetPermanent(filter1)); this.addAbility(ability); // {2}{B}: Create a 1/1 black Starship artifact creature token with spaceflight named TIE Fighter. @@ -53,7 +54,7 @@ public final class StarDestroyer extends CardImpl { // {2}{R}: Star Destroyer deals 2 damge to target non-Starship creature or player. ability = new SimpleActivatedAbility(new DamageTargetEffect(2), new ManaCostsImpl<>("{2}{R}")); - ability.addTarget(new TargetCreatureOrPlayer(filter3)); + ability.addTarget(new TargetPermanentOrPlayer(filter3)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/StarforgedSword.java b/Mage.Sets/src/mage/cards/s/StarforgedSword.java index 9f9d50aa5ca..52e1c6bd132 100644 --- a/Mage.Sets/src/mage/cards/s/StarforgedSword.java +++ b/Mage.Sets/src/mage/cards/s/StarforgedSword.java @@ -4,7 +4,6 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAttachToTarget; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.GiftWasPromisedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.effects.common.continuous.LoseAbilityAttachedEffect; import mage.abilities.keyword.EquipAbility; @@ -33,10 +32,7 @@ public final class StarforgedSword extends CardImpl { this.addAbility(new GiftAbility(this, GiftType.TAPPED_FISH)); // When Starforged Sword enters, if the gift was promised, attach Starforged Sword to target creature you control. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldAttachToTarget(), GiftWasPromisedCondition.TRUE, - "When {this} enters, if the gift was promised, attach {this} to target creature you control." - )); + this.addAbility(new EntersBattlefieldAttachToTarget().withInterveningIf(GiftWasPromisedCondition.TRUE)); // Equipped creature gets +3/+3 and loses flying. Ability ability = new SimpleStaticAbility(new BoostEquippedEffect(3, 3)); diff --git a/Mage.Sets/src/mage/cards/s/StarscreamPowerHungry.java b/Mage.Sets/src/mage/cards/s/StarscreamPowerHungry.java index 0e847a27e42..9000a352fdb 100644 --- a/Mage.Sets/src/mage/cards/s/StarscreamPowerHungry.java +++ b/Mage.Sets/src/mage/cards/s/StarscreamPowerHungry.java @@ -1,11 +1,10 @@ package mage.cards.s; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.CombatDamageDealtToYouTriggeredAbility; import mage.abilities.common.DrawCardControllerTriggeredAbility; import mage.abilities.condition.common.MonarchIsSourceControllerCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.LoseLifeTargetEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.hint.common.MonarchHint; @@ -41,18 +40,14 @@ public final class StarscreamPowerHungry extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Whenever you draw a card, if you're the monarch, target opponent loses 2 life. - TriggeredAbility trigger = new ConditionalInterveningIfTriggeredAbility( - new DrawCardControllerTriggeredAbility(new LoseLifeTargetEffect(2), false), - MonarchIsSourceControllerCondition.instance, - "Whenever you draw a card, if you're the monarch, target opponent loses 2 life." - ); - trigger.addTarget(new TargetOpponent()); - trigger.addHint(MonarchHint.instance); - this.addAbility(trigger); + Ability ability = new DrawCardControllerTriggeredAbility(new LoseLifeTargetEffect(2), false) + .withInterveningIf(MonarchIsSourceControllerCondition.instance); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability.addHint(MonarchHint.instance)); // Whenever one or more creatures deal combat damage to you, convert Starscream. this.addAbility(new CombatDamageDealtToYouTriggeredAbility( - new TransformSourceEffect().setText("convert {this}") + new TransformSourceEffect().setText("convert {this}") )); } @@ -64,4 +59,4 @@ public final class StarscreamPowerHungry extends CardImpl { public StarscreamPowerHungry copy() { return new StarscreamPowerHungry(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/s/StarscreamSeekerLeader.java b/Mage.Sets/src/mage/cards/s/StarscreamSeekerLeader.java index 094c85c01c4..e8f24856628 100644 --- a/Mage.Sets/src/mage/cards/s/StarscreamSeekerLeader.java +++ b/Mage.Sets/src/mage/cards/s/StarscreamSeekerLeader.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.common.BecomesMonarchSourceControllerTriggeredAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.condition.common.MonarchIsNotSetCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.BecomesMonarchTargetEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.hint.common.MonarchHint; @@ -48,15 +47,13 @@ public final class StarscreamSeekerLeader extends CardImpl { this.addAbility(HasteAbility.getInstance()); // Whenever Starscream deals combat damage to a player, if there is no monarch, that player becomes the monarch. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new DealsCombatDamageToAPlayerTriggeredAbility(new BecomesMonarchTargetEffect(), false, true), - MonarchIsNotSetCondition.instance, - "Whenever {this} deals combat damage to a player, if there is no monarch, that player becomes the monarch." - ).addHint(MonarchHint.instance)); + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility( + new BecomesMonarchTargetEffect().setText("that player becomes the monarch"), false, true + ).withInterveningIf(MonarchIsNotSetCondition.instance).addHint(MonarchHint.instance)); // Whenever you become the monarch, convert Starscream. this.addAbility(new BecomesMonarchSourceControllerTriggeredAbility( - new TransformSourceEffect().setText("convert {this}") + new TransformSourceEffect().setText("convert {this}") )); } diff --git a/Mage.Sets/src/mage/cards/s/StarseerMentor.java b/Mage.Sets/src/mage/cards/s/StarseerMentor.java index 5e4c4bb4674..a176893417c 100644 --- a/Mage.Sets/src/mage/cards/s/StarseerMentor.java +++ b/Mage.Sets/src/mage/cards/s/StarseerMentor.java @@ -2,16 +2,15 @@ package mage.cards.s; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.common.YouGainedOrLostLifeCondition; import mage.abilities.costs.OrCost; import mage.abilities.costs.common.DiscardCardCost; import mage.abilities.costs.common.SacrificeTargetCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DoUnlessTargetPlayerOrTargetsControllerPaysEffect; import mage.abilities.effects.common.LoseLifeTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.VigilanceAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -42,24 +41,19 @@ public final class StarseerMentor extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // At the beginning of your end step, if you gained or lost life this turn, target opponent loses 3 life unless they sacrifice a nonland permanent or discard a card. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - new DoUnlessTargetPlayerOrTargetsControllerPaysEffect( - new LoseLifeTargetEffect(3), - new OrCost( - "sacrifice a nonland permanent or discard a card", - new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_NON_LAND), - new DiscardCardCost() - ), - "Sacrifice a nonland permanent or discard a card to prevent losing 3 life?" - ) - ), YouGainedOrLostLifeCondition.instance, "At the beginning of your end step, if you gained or lost life this turn, " - + "target opponent loses 3 life unless they sacrifice a nonland permanent of their choice or discard a card." - ); + Ability ability = new BeginningOfEndStepTriggeredAbility( + new DoUnlessTargetPlayerOrTargetsControllerPaysEffect( + new LoseLifeTargetEffect(3), + new OrCost( + "sacrifice a nonland permanent or discard a card", + new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_NON_LAND), + new DiscardCardCost() + ), + "Sacrifice a nonland permanent or discard a card to prevent losing 3 life?" + ).setText("target opponent loses 3 life unless they sacrifice a nonland permanent of their choice or discard a card") + ).withInterveningIf(YouGainedOrLostLifeCondition.instance); ability.addTarget(new TargetOpponent()); - ability.addWatcher(new PlayerGainedLifeWatcher()); - ability.addHint(YouGainedOrLostLifeCondition.getHint()); - this.addAbility(ability); + this.addAbility(ability.addHint(YouGainedOrLostLifeCondition.getHint()), new PlayerGainedLifeWatcher()); } private StarseerMentor(final StarseerMentor card) { diff --git a/Mage.Sets/src/mage/cards/s/StartFinish.java b/Mage.Sets/src/mage/cards/s/StartFinish.java index 1a80fefa46e..85ea7fd1390 100644 --- a/Mage.Sets/src/mage/cards/s/StartFinish.java +++ b/Mage.Sets/src/mage/cards/s/StartFinish.java @@ -14,6 +14,7 @@ import mage.constants.SpellAbilityType; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.game.permanent.token.WarriorVigilantToken; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; @@ -37,7 +38,7 @@ public final class StartFinish extends SplitCard { // As an additional cost to cast Finish, sacrifice a creature. Destroy target creature. getRightHalfCard().addAbility(new AftermathAbility().setRuleAtTheTop(true)); getRightHalfCard().getSpellAbility().addCost(new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_CREATURE)); - getRightHalfCard().getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (to destoy)"))); + getRightHalfCard().getSpellAbility().addTarget(new TargetPermanent(new FilterCreaturePermanent("creature (to destoy)"))); getRightHalfCard().getSpellAbility().addEffect(new DestroyTargetEffect("Destroy target creature")); } diff --git a/Mage.Sets/src/mage/cards/s/StarvingRevenant.java b/Mage.Sets/src/mage/cards/s/StarvingRevenant.java index 8d0a80c749d..1479337add8 100644 --- a/Mage.Sets/src/mage/cards/s/StarvingRevenant.java +++ b/Mage.Sets/src/mage/cards/s/StarvingRevenant.java @@ -5,7 +5,6 @@ import mage.abilities.Ability; import mage.abilities.common.DrawCardControllerTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.DescendCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.LoseLifeTargetEffect; @@ -38,13 +37,8 @@ public final class StarvingRevenant extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new StarvingRevenantEffect())); // Descend 8 -- Whenever you draw a card, if there are eight or more permanent cards in your graveyard, target opponent loses 1 life and you gain 1 life. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new DrawCardControllerTriggeredAbility(new LoseLifeTargetEffect(1), false), - DescendCondition.EIGHT, "Whenever you draw a card, " - + "if there are eight or more permanent cards in your graveyard, " - + "target opponent loses 1 life and you gain 1 life." - ); - ability.addEffect(new GainLifeEffect(1)); + Ability ability = new DrawCardControllerTriggeredAbility(new LoseLifeTargetEffect(1), false).withInterveningIf(DescendCondition.EIGHT); + ability.addEffect(new GainLifeEffect(1).concatBy("and")); ability.addTarget(new TargetOpponent()); this.addAbility(ability.addHint(DescendCondition.getHint()).setAbilityWord(AbilityWord.DESCEND_8)); } @@ -90,4 +84,4 @@ class StarvingRevenantEffect extends OneShotEffect { return true; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/s/SteadfastUnicorn.java b/Mage.Sets/src/mage/cards/s/SteadfastUnicorn.java index bd89a9d7841..fbc5c6931ec 100644 --- a/Mage.Sets/src/mage/cards/s/SteadfastUnicorn.java +++ b/Mage.Sets/src/mage/cards/s/SteadfastUnicorn.java @@ -14,7 +14,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.StaticFilters; import java.util.UUID; @@ -33,8 +32,9 @@ public final class SteadfastUnicorn extends CardImpl { // {3}{W}: Creatures you control get +1/+1 and gain vigilance until end of turn. Activate only during your turn. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new BoostControlledEffect(1, 1, Duration.EndOfTurn) - .setText("creatures you control get +1/+1"), new ManaCostsImpl<>("{3}{W}"), MyTurnCondition.instance + new BoostControlledEffect(1, 1, Duration.EndOfTurn) + .setText("creatures you control get +1/+1"), + new ManaCostsImpl<>("{3}{W}"), MyTurnCondition.instance ); ability.addEffect(new GainAbilityControlledEffect( VigilanceAbility.getInstance(), Duration.EndOfTurn, diff --git a/Mage.Sets/src/mage/cards/s/StealStrength.java b/Mage.Sets/src/mage/cards/s/StealStrength.java index 9597f4fbbf6..0797db89e1d 100644 --- a/Mage.Sets/src/mage/cards/s/StealStrength.java +++ b/Mage.Sets/src/mage/cards/s/StealStrength.java @@ -1,44 +1,29 @@ - package mage.cards.s; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.effects.ContinuousEffectImpl; +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.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.other.AnotherTargetPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.SecondTargetPointer; + +import java.util.UUID; /** - * * @author fireshoes */ public final class StealStrength extends CardImpl { public StealStrength(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}"); // Target creature gets +1/+1 until end of turn. Another target creature gets -1/-1 until end of turn. - this.getSpellAbility().addEffect(new StealStrengthEffect()); - - FilterCreaturePermanent filter1 = new FilterCreaturePermanent("creature (gets +1/+1 until end of turn)"); - TargetCreaturePermanent target1 = new TargetCreaturePermanent(filter1); - target1.setTargetTag(1); - this.getSpellAbility().addTarget(target1); - - FilterCreaturePermanent filter2 = new FilterCreaturePermanent("another creature (gets -1/-1 until end of turn)"); - filter2.add(new AnotherTargetPredicate(2)); - TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter2); - target2.setTargetTag(2); - this.getSpellAbility().addTarget(target2); + this.getSpellAbility().addEffect(new BoostTargetEffect(1, 1)); + this.getSpellAbility().addEffect(new BoostTargetEffect(-1, -1).setTargetPointer(new SecondTargetPointer()).setText("Another target creature gets -1/-1 until end of turn")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent().withChooseHint("+1/+1").setTargetTag(1)); + this.getSpellAbility().addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2).withChooseHint("-1/-1").setTargetTag(2)); } private StealStrength(final StealStrength card) { @@ -50,35 +35,3 @@ public final class StealStrength extends CardImpl { return new StealStrength(this); } } - -class StealStrengthEffect extends ContinuousEffectImpl { - - StealStrengthEffect() { - super(Duration.EndOfTurn, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature); - this.staticText = "Target creature gets +1/+1 until end of turn. Another target creature gets -1/-1 until end of turn"; - } - - private StealStrengthEffect(final StealStrengthEffect effect) { - super(effect); - } - - @Override - public StealStrengthEffect copy() { - return new StealStrengthEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getFirstTarget()); - if (permanent != null) { - permanent.addPower(1); - permanent.addToughness(1); - } - permanent = game.getPermanent(source.getTargets().get(1).getFirstTarget()); - if (permanent != null) { - permanent.addPower(-1); - permanent.addToughness(-1); - } - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/s/SteamCatapult.java b/Mage.Sets/src/mage/cards/s/SteamCatapult.java index f9a2a9244fa..e06801fbc1e 100644 --- a/Mage.Sets/src/mage/cards/s/SteamCatapult.java +++ b/Mage.Sets/src/mage/cards/s/SteamCatapult.java @@ -1,7 +1,5 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; @@ -12,17 +10,18 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class SteamCatapult extends CardImpl { - + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped creature"); static { @@ -30,16 +29,17 @@ public final class SteamCatapult extends CardImpl { } public SteamCatapult(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.SOLDIER); this.power = new MageInt(2); this.toughness = new MageInt(3); // {tap}: Destroy target tapped creature. Activate this ability only during your turn, before attackers are declared. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new DestroyTargetEffect(), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); - ability.addTarget(new TargetCreaturePermanent(filter)); + Ability ability = new ActivateIfConditionActivatedAbility( + new DestroyTargetEffect(), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance + ); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SteamcoreWeird.java b/Mage.Sets/src/mage/cards/s/SteamcoreWeird.java index 852c4980643..b11ced49a24 100644 --- a/Mage.Sets/src/mage/cards/s/SteamcoreWeird.java +++ b/Mage.Sets/src/mage/cards/s/SteamcoreWeird.java @@ -1,37 +1,34 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.ManaWasSpentCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; 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.ColoredManaSymbol; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** - * * @author FenrisulfrX */ public final class SteamcoreWeird extends CardImpl { public SteamcoreWeird(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); this.subtype.add(SubType.WEIRD); this.power = new MageInt(1); this.toughness = new MageInt(3); // When Steamcore Weird enters the battlefield, if {R} was spent to cast Steamcore Weird, it deals 2 damage to any target. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2, "it")); + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2, "it")) + .withInterveningIf(ManaWasSpentCondition.RED); ability.addTarget(new TargetAnyTarget()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, ManaWasSpentCondition.RED, - "When {this} enters, if {R} was spent to cast it, it deals 2 damage to any target.")); + this.addAbility(ability); } private SteamcoreWeird(final SteamcoreWeird card) { diff --git a/Mage.Sets/src/mage/cards/s/SteelclawLance.java b/Mage.Sets/src/mage/cards/s/SteelclawLance.java index 733f9a55e64..b80874c09d7 100644 --- a/Mage.Sets/src/mage/cards/s/SteelclawLance.java +++ b/Mage.Sets/src/mage/cards/s/SteelclawLance.java @@ -9,17 +9,18 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; -import mage.target.common.TargetControlledCreaturePermanent; /** * @author TheElk801 */ public final class SteelclawLance extends CardImpl { - private static final FilterControlledCreaturePermanent filter + private static final FilterPermanent filter = new FilterControlledCreaturePermanent(SubType.KNIGHT, "Knight"); public SteelclawLance(UUID ownerId, CardSetInfo setInfo) { @@ -31,10 +32,10 @@ public final class SteelclawLance extends CardImpl { this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(2, 2))); // Equip Knight {1} - this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(1), new TargetControlledCreaturePermanent(filter), false)); + this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(1), new TargetPermanent(filter), false)); // Equip {3} - this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(3), new TargetControlledCreaturePermanent(), false)); + this.addAbility(new EquipAbility(3, false)); } diff --git a/Mage.Sets/src/mage/cards/s/StellaLeeWildCard.java b/Mage.Sets/src/mage/cards/s/StellaLeeWildCard.java index d64bc90e05f..a3fd08dd33b 100644 --- a/Mage.Sets/src/mage/cards/s/StellaLeeWildCard.java +++ b/Mage.Sets/src/mage/cards/s/StellaLeeWildCard.java @@ -47,8 +47,7 @@ public final class StellaLeeWildCard extends CardImpl { // {T}: Copy target instant or sorcery spell you control. You may choose new targets for the copy. Activate only if you've cast three or more spells this turn. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new CopyTargetStackObjectEffect(), - new TapSourceCost(), StellaLeeWildCardCondition.instance + new CopyTargetStackObjectEffect(), new TapSourceCost(), StellaLeeWildCardCondition.instance ); ability.addTarget(new TargetSpell(filter)); this.addAbility(ability.addHint(StormAbility.getHint())); diff --git a/Mage.Sets/src/mage/cards/s/SteppeGlider.java b/Mage.Sets/src/mage/cards/s/SteppeGlider.java index 5b01012e024..7b1bd660799 100644 --- a/Mage.Sets/src/mage/cards/s/SteppeGlider.java +++ b/Mage.Sets/src/mage/cards/s/SteppeGlider.java @@ -17,8 +17,11 @@ import mage.constants.SubType; import mage.constants.Duration; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_A_CREATURE_P1P1; + /** * * @author fireshoes @@ -44,7 +47,7 @@ public final class SteppeGlider extends CardImpl { effect = new GainAbilityTargetEffect(VigilanceAbility.getInstance(), Duration.EndOfTurn); effect.setText("and vigilance until end of turn"); ability.addEffect(effect); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_A_CREATURE_P1P1)); + ability.addTarget(new TargetPermanent(FILTER_A_CREATURE_P1P1)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SternMarshal.java b/Mage.Sets/src/mage/cards/s/SternMarshal.java index 56900530e2f..a924dfc0874 100644 --- a/Mage.Sets/src/mage/cards/s/SternMarshal.java +++ b/Mage.Sets/src/mage/cards/s/SternMarshal.java @@ -1,7 +1,5 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; @@ -11,27 +9,29 @@ import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class SternMarshal extends CardImpl { public SternMarshal(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.SOLDIER); this.power = new MageInt(2); this.toughness = new MageInt(2); // {tap}: Target creature gets +2/+2 until end of turn. Activate this ability only during your turn, before attackers are declared. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new BoostTargetEffect(2, 2, Duration.EndOfTurn), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new BoostTargetEffect(2, 2, Duration.EndOfTurn), + new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance + ); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/StingerflingSpider.java b/Mage.Sets/src/mage/cards/s/StingerflingSpider.java index b0b3c981717..2e38bd05cba 100644 --- a/Mage.Sets/src/mage/cards/s/StingerflingSpider.java +++ b/Mage.Sets/src/mage/cards/s/StingerflingSpider.java @@ -15,6 +15,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -36,7 +37,7 @@ public final class StingerflingSpider extends CardImpl { this.toughness = new MageInt(5); this.addAbility(ReachAbility.getInstance()); Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), true); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/StingingCaveCrawler.java b/Mage.Sets/src/mage/cards/s/StingingCaveCrawler.java index b24f63945ed..03aa6835d48 100644 --- a/Mage.Sets/src/mage/cards/s/StingingCaveCrawler.java +++ b/Mage.Sets/src/mage/cards/s/StingingCaveCrawler.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.DescendCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.LoseLifeSourceControllerEffect; import mage.abilities.keyword.DeathtouchAbility; @@ -33,12 +32,8 @@ public final class StingingCaveCrawler extends CardImpl { this.addAbility(DeathtouchAbility.getInstance()); // Descend 4 -- Whenever Stinging Cave Crawler attacks, if there are four or more permanent cards in your graveyard, you draw a card and you lose 1 life. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new DrawCardSourceControllerEffect(1)), - DescendCondition.FOUR, "Whenever {this} attacks, if there are four " + - "or more permanent cards in your graveyard, you draw a card and you lose 1 life." - ); - ability.addEffect(new LoseLifeSourceControllerEffect(1)); + Ability ability = new AttacksTriggeredAbility(new DrawCardSourceControllerEffect(1, true)).withInterveningIf(DescendCondition.FOUR); + ability.addEffect(new LoseLifeSourceControllerEffect(1).concatBy("and")); this.addAbility(ability.setAbilityWord(AbilityWord.DESCEND_4).addHint(DescendCondition.getHint())); } diff --git a/Mage.Sets/src/mage/cards/s/StingingShot.java b/Mage.Sets/src/mage/cards/s/StingingShot.java index 138a2d01de1..b3fb6f6d770 100644 --- a/Mage.Sets/src/mage/cards/s/StingingShot.java +++ b/Mage.Sets/src/mage/cards/s/StingingShot.java @@ -12,6 +12,7 @@ import mage.constants.CardType; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -30,7 +31,7 @@ public final class StingingShot extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{G}"); // Put three -1/-1 counters on target creature with flying. - getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + getSpellAbility().addTarget(new TargetPermanent(filter)); getSpellAbility().addEffect(new AddCountersTargetEffect(CounterType.M1M1.createInstance(3))); // Cycling {2} diff --git a/Mage.Sets/src/mage/cards/s/Stingscourger.java b/Mage.Sets/src/mage/cards/s/Stingscourger.java index ed9b214ad50..f9cefbe112d 100644 --- a/Mage.Sets/src/mage/cards/s/Stingscourger.java +++ b/Mage.Sets/src/mage/cards/s/Stingscourger.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; @@ -11,17 +9,17 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.StaticFilters; -import mage.target.common.TargetCreaturePermanent; +import mage.target.common.TargetOpponentsCreaturePermanent; + +import java.util.UUID; /** - * * @author jonubuu */ public final class Stingscourger extends CardImpl { public Stingscourger(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.GOBLIN); this.subtype.add(SubType.WARRIOR); @@ -30,10 +28,10 @@ public final class Stingscourger extends CardImpl { // Echo {3}{R} this.addAbility(new EchoAbility("{3}{R}")); + // When Stingscourger enters the battlefield, return target creature an opponent controls to its owner's hand. Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()); - TargetCreaturePermanent target = new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE); - ability.addTarget(target); + ability.addTarget(new TargetOpponentsCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/StitchedMangler.java b/Mage.Sets/src/mage/cards/s/StitchedMangler.java index 0487d1754ee..4d6a9a94b1d 100644 --- a/Mage.Sets/src/mage/cards/s/StitchedMangler.java +++ b/Mage.Sets/src/mage/cards/s/StitchedMangler.java @@ -13,8 +13,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -36,7 +39,7 @@ public final class StitchedMangler extends CardImpl { Effect effect = new DontUntapInControllersNextUntapStepTargetEffect(); effect.setText("That creature doesn't untap during its controller's next untap step"); ability.addEffect(effect); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/StoneCatapult.java b/Mage.Sets/src/mage/cards/s/StoneCatapult.java index b0ba155ccf9..5bcca38c131 100644 --- a/Mage.Sets/src/mage/cards/s/StoneCatapult.java +++ b/Mage.Sets/src/mage/cards/s/StoneCatapult.java @@ -1,7 +1,5 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; import mage.abilities.Ability; @@ -13,20 +11,21 @@ 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.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author fireshoes */ public final class StoneCatapult extends CardImpl { - - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("tapped nonblack creature"); + + private static final FilterPermanent filter = new FilterCreaturePermanent("tapped nonblack creature"); static { filter.add(TappedPredicate.TAPPED); @@ -34,16 +33,17 @@ public final class StoneCatapult extends CardImpl { } public StoneCatapult(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.SOLDIER); this.power = new MageInt(1); this.toughness = new MageInt(2); // {tap}: Destroy target tapped nonblack creature. Activate this ability only during your turn, before attackers are declared. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new DestroyTargetEffect(), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); - ability.addTarget(new TargetCreaturePermanent(filter)); + Ability ability = new ActivateIfConditionActivatedAbility( + new DestroyTargetEffect(), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance + ); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/StoneHavenPilgrim.java b/Mage.Sets/src/mage/cards/s/StoneHavenPilgrim.java index f1f2685ffb9..aa066ecc210 100644 --- a/Mage.Sets/src/mage/cards/s/StoneHavenPilgrim.java +++ b/Mage.Sets/src/mage/cards/s/StoneHavenPilgrim.java @@ -5,7 +5,6 @@ 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; @@ -14,7 +13,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.filter.StaticFilters; +import mage.filter.common.FilterArtifactOrEnchantmentPermanent; import java.util.UUID; @@ -23,8 +22,9 @@ import java.util.UUID; */ public final class StoneHavenPilgrim extends CardImpl { - private static final Condition condition - = new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT); + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterArtifactOrEnchantmentPermanent("you control an artifact or enchantment") + ); public StoneHavenPilgrim(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); @@ -35,13 +35,12 @@ public final class StoneHavenPilgrim extends CardImpl { 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)); + Ability ability = new AttacksTriggeredAbility(new BoostSourceEffect( + 1, 1, Duration.EndOfTurn + ).setText("{this} gets +1/+1")).withInterveningIf(condition); + ability.addEffect(new GainAbilitySourceEffect( + LifelinkAbility.getInstance(), Duration.EndOfTurn + ).setText("and gains lifelink until end of turn")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/StormElemental.java b/Mage.Sets/src/mage/cards/s/StormElemental.java index 41673d298e1..3f793bcb1d8 100644 --- a/Mage.Sets/src/mage/cards/s/StormElemental.java +++ b/Mage.Sets/src/mage/cards/s/StormElemental.java @@ -19,6 +19,7 @@ import mage.filter.common.FilterLandCard; import mage.filter.predicate.mageobject.AbilityPredicate; import mage.game.Game; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -46,7 +47,7 @@ public final class StormElemental extends CardImpl { // {U}, Exile the top card of your library: Tap target creature with flying. Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new ManaCostsImpl<>("{U}")); ability.addCost(new ExileTopCardLibraryCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // {U}, Exile the top card of your library: If the exiled card is a snow land, Storm Elemental gets +1/+1 until end of turn. diff --git a/Mage.Sets/src/mage/cards/s/StormFleetArsonist.java b/Mage.Sets/src/mage/cards/s/StormFleetArsonist.java index 48ee6857076..0f9895ad186 100644 --- a/Mage.Sets/src/mage/cards/s/StormFleetArsonist.java +++ b/Mage.Sets/src/mage/cards/s/StormFleetArsonist.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SacrificeEffect; import mage.abilities.hint.common.RaidHint; import mage.cards.CardImpl; @@ -12,7 +11,7 @@ import mage.cards.CardSetInfo; import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.target.common.TargetOpponent; import mage.watchers.common.PlayerAttackedWatcher; @@ -32,14 +31,11 @@ public final class StormFleetArsonist extends CardImpl { this.toughness = new MageInt(4); // Raid - When Storm Fleet Arsonist enters the battlefield, if you attacked this turn, target opponent sacrifices a permanent. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new SacrificeEffect(new FilterPermanent(), 1, "Target opponent")), - RaidCondition.instance, - "When {this} enters, if you attacked this turn, target opponent sacrifices a permanent."); + Ability ability = new EntersBattlefieldTriggeredAbility( + new SacrificeEffect(StaticFilters.FILTER_PERMANENT_A, 1, "target opponent") + ).withInterveningIf(RaidCondition.instance); ability.addTarget(new TargetOpponent()); - ability.setAbilityWord(AbilityWord.RAID); - ability.addHint(RaidHint.instance); - this.addAbility(ability, new PlayerAttackedWatcher()); + this.addAbility(ability.setAbilityWord(AbilityWord.RAID).addHint(RaidHint.instance), new PlayerAttackedWatcher()); } private StormFleetArsonist(final StormFleetArsonist card) { diff --git a/Mage.Sets/src/mage/cards/s/StormFleetPyromancer.java b/Mage.Sets/src/mage/cards/s/StormFleetPyromancer.java index cc9967b7acf..8ac6ef90b68 100644 --- a/Mage.Sets/src/mage/cards/s/StormFleetPyromancer.java +++ b/Mage.Sets/src/mage/cards/s/StormFleetPyromancer.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.hint.common.RaidHint; import mage.cards.CardImpl; @@ -32,14 +31,9 @@ public final class StormFleetPyromancer extends CardImpl { this.toughness = new MageInt(2); // Raid - When Storm Fleet Pyromancer enters the battlefield, if you attacked this turn, Storm Fleet Pyromancer deals 2 damage to any target. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2)), - RaidCondition.instance, - "When {this} enters, if you attacked this turn, {this} deals 2 damage to any target."); + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2)).withInterveningIf(RaidCondition.instance); ability.addTarget(new TargetAnyTarget()); - ability.setAbilityWord(AbilityWord.RAID); - ability.addHint(RaidHint.instance); - this.addAbility(ability, new PlayerAttackedWatcher()); + this.addAbility(ability.setAbilityWord(AbilityWord.RAID).addHint(RaidHint.instance), new PlayerAttackedWatcher()); } private StormFleetPyromancer(final StormFleetPyromancer card) { diff --git a/Mage.Sets/src/mage/cards/s/StormFleetSpy.java b/Mage.Sets/src/mage/cards/s/StormFleetSpy.java index cf37d6515c4..ddda8a2da29 100644 --- a/Mage.Sets/src/mage/cards/s/StormFleetSpy.java +++ b/Mage.Sets/src/mage/cards/s/StormFleetSpy.java @@ -1,10 +1,8 @@ package mage.cards.s; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.hint.common.RaidHint; import mage.cards.CardImpl; @@ -30,13 +28,8 @@ public final class StormFleetSpy extends CardImpl { this.toughness = new MageInt(2); // Raid — When this creature enters, if you attacked this turn, draw a card. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)), - RaidCondition.instance, - "When this creature enters, if you attacked this turn, draw a card."); - ability.setAbilityWord(AbilityWord.RAID); - ability.addHint(RaidHint.instance); - this.addAbility(ability, new PlayerAttackedWatcher()); + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)) + .withInterveningIf(RaidCondition.instance).setAbilityWord(AbilityWord.RAID).addHint(RaidHint.instance), new PlayerAttackedWatcher()); } private StormFleetSpy(final StormFleetSpy card) { diff --git a/Mage.Sets/src/mage/cards/s/StormFront.java b/Mage.Sets/src/mage/cards/s/StormFront.java index c5eebd53499..6ab00a62498 100644 --- a/Mage.Sets/src/mage/cards/s/StormFront.java +++ b/Mage.Sets/src/mage/cards/s/StormFront.java @@ -13,6 +13,7 @@ import mage.constants.CardType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -32,7 +33,7 @@ public final class StormFront extends CardImpl { // {G}{G}: Tap target creature with flying. Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new ManaCostsImpl<>("{G}{G}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/StormTheVault.java b/Mage.Sets/src/mage/cards/s/StormTheVault.java index 11d924c3997..a76502a82c5 100644 --- a/Mage.Sets/src/mage/cards/s/StormTheVault.java +++ b/Mage.Sets/src/mage/cards/s/StormTheVault.java @@ -1,30 +1,32 @@ - package mage.cards.s; -import java.util.UUID; - -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.OneOrMoreCombatDamagePlayerTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.TransformSourceEffect; -import mage.abilities.hint.ValueHint; +import mage.abilities.hint.common.ArtifactYouControlHint; import mage.abilities.keyword.TransformAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.SuperType; -import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledArtifactPermanent; import mage.game.permanent.token.TreasureToken; +import java.util.UUID; + /** * @author LevelX2 */ public final class StormTheVault extends CardImpl { + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledArtifactPermanent("you control five or more artifacts"), ComparisonType.MORE_THAN, 4 + ); + public StormTheVault(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}{R}"); @@ -37,11 +39,8 @@ public final class StormTheVault extends CardImpl { // At the beginning of your end step, if you control five or more artifacts, transform Storm the Vault. this.addAbility(new TransformAbility()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect()), - new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT, ComparisonType.MORE_THAN, 4), - "At the beginning of your end step, if you control five or more artifacts, transform {this}" - ).addHint(new ValueHint("Artifacts you control", new PermanentsOnBattlefieldCount(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT)))); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect()) + .withInterveningIf(condition).addHint(ArtifactYouControlHint.instance)); } private StormTheVault(final StormTheVault card) { diff --git a/Mage.Sets/src/mage/cards/s/StormscapeBattlemage.java b/Mage.Sets/src/mage/cards/s/StormscapeBattlemage.java index 676e6c643ca..414424d8f18 100644 --- a/Mage.Sets/src/mage/cards/s/StormscapeBattlemage.java +++ b/Mage.Sets/src/mage/cards/s/StormscapeBattlemage.java @@ -1,11 +1,10 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.KickedCostCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.keyword.KickerAbility; @@ -14,16 +13,20 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class StormscapeBattlemage extends CardImpl { + private static final Condition condition = new KickedCostCondition("{W}"); + private static final Condition condition2 = new KickedCostCondition("{2}{B}"); + public StormscapeBattlemage(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.METATHRAN); this.subtype.add(SubType.WIZARD); @@ -36,17 +39,14 @@ public final class StormscapeBattlemage extends CardImpl { this.addAbility(kickerAbility); // When Stormscape Battlemage enters the battlefield, if it was kicked with its {W} kicker, you gain 3 life. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3),false), - new KickedCostCondition("{W}"), - "When Stormscape Battlemage enters the battlefield, if it was kicked with its {W} kicker, you gain 3 life.")); + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(3)).withInterveningIf(condition)); // When Stormscape Battlemage enters the battlefield, if it was kicked with its {2}{B} kicker, destroy target nonblack creature. That creature can't be regenerated. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(true),false); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - ability, new KickedCostCondition("{2}{B}"), - "When Stormscape Battlemage enters the battlefield, if it was kicked with its {2}{B} kicker, destroy target nonblack creature. That creature can't be regenerated.")); + Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect( + "destroy target nonblack creature. That creature can't be regenerated", true + )).withInterveningIf(condition2); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.addAbility(ability); } private StormscapeBattlemage(final StormscapeBattlemage card) { diff --git a/Mage.Sets/src/mage/cards/s/Storyweave.java b/Mage.Sets/src/mage/cards/s/Storyweave.java index a49c99a5b33..e69ae663f01 100644 --- a/Mage.Sets/src/mage/cards/s/Storyweave.java +++ b/Mage.Sets/src/mage/cards/s/Storyweave.java @@ -71,8 +71,8 @@ class StoryweaveReplacementEffect extends ReplacementEffectImpl { StoryweaveReplacementEffect() { super(Duration.EndOfTurn, Outcome.BoostCreature); - staticText = "The next time one or more enchantment creatures enter the battlefield " + - "under your control this turn, each enters with two additional +1/+1 counters on it"; + staticText = "The next time one or more enchantment creatures you control enter this turn, " + + "each enters with two additional +1/+1 counters on it"; } private StoryweaveReplacementEffect(final StoryweaveReplacementEffect effect) { diff --git a/Mage.Sets/src/mage/cards/s/Strafe.java b/Mage.Sets/src/mage/cards/s/Strafe.java index bb69167d509..4fdf5bd5df1 100644 --- a/Mage.Sets/src/mage/cards/s/Strafe.java +++ b/Mage.Sets/src/mage/cards/s/Strafe.java @@ -10,6 +10,7 @@ import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -30,7 +31,7 @@ public final class Strafe extends CardImpl { // Strafe deals 3 damage to target nonred creature. this.getSpellAbility().addEffect(new DamageTargetEffect(3)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private Strafe(final Strafe card) { diff --git a/Mage.Sets/src/mage/cards/s/StranglingSoot.java b/Mage.Sets/src/mage/cards/s/StranglingSoot.java index e720e91b118..fe1f37ca4b5 100644 --- a/Mage.Sets/src/mage/cards/s/StranglingSoot.java +++ b/Mage.Sets/src/mage/cards/s/StranglingSoot.java @@ -12,6 +12,7 @@ import mage.constants.ComparisonType; import mage.constants.TimingRule; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ToughnessPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -29,7 +30,7 @@ public final class StranglingSoot extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{B}"); // Destroy target creature with toughness 3 or less. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); // Flashback {5}{R} this.addAbility(new FlashbackAbility(this, new ManaCostsImpl<>("{5}{R}"))); diff --git a/Mage.Sets/src/mage/cards/s/StreambedAquitects.java b/Mage.Sets/src/mage/cards/s/StreambedAquitects.java index 32ba35910ea..e1f85fcb534 100644 --- a/Mage.Sets/src/mage/cards/s/StreambedAquitects.java +++ b/Mage.Sets/src/mage/cards/s/StreambedAquitects.java @@ -14,6 +14,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetLandPermanent; @@ -41,7 +42,7 @@ public final class StreambedAquitects extends CardImpl { ability.addEffect(new GainAbilityTargetEffect( new IslandwalkAbility(false), Duration.EndOfTurn ).setText("and gains islandwalk until end of turn")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // {tap}: Target land becomes an Island until end of turn. diff --git a/Mage.Sets/src/mage/cards/s/StreetSpasm.java b/Mage.Sets/src/mage/cards/s/StreetSpasm.java index 4492e3de0d0..d43add838ba 100644 --- a/Mage.Sets/src/mage/cards/s/StreetSpasm.java +++ b/Mage.Sets/src/mage/cards/s/StreetSpasm.java @@ -15,6 +15,7 @@ import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -35,7 +36,7 @@ public final class StreetSpasm extends CardImpl { // Street Spasm deals X damage to target creature without flying you don't control. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DamageTargetEffect(GetXValue.instance)); // Overload {X}{X}{R}{R} (You may cast this spell for its overload cost. If you do, change its text by replacing all instances of "target" with "each.") @@ -50,4 +51,4 @@ public final class StreetSpasm extends CardImpl { public StreetSpasm copy() { return new StreetSpasm(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/s/StrongTheBrutishThespian.java b/Mage.Sets/src/mage/cards/s/StrongTheBrutishThespian.java index d7c9f8849ad..0defbb6289f 100644 --- a/Mage.Sets/src/mage/cards/s/StrongTheBrutishThespian.java +++ b/Mage.Sets/src/mage/cards/s/StrongTheBrutishThespian.java @@ -19,6 +19,7 @@ import mage.game.events.GameEvent; import java.util.UUID; public class StrongTheBrutishThespian extends CardImpl { + public StrongTheBrutishThespian(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}{G}"); this.addSuperType(SuperType.LEGENDARY); @@ -31,14 +32,13 @@ public class StrongTheBrutishThespian extends CardImpl { // Ward {2} this.addAbility(new WardAbility(new ManaCostsImpl<>("{2}"))); - // Enrage - Whenever strong is dealt damage, you get three rad counters and put three +1/+1 counters on Strong. + // Enrage - Whenever Strong is dealt damage, you get three rad counters and put three +1/+1 counters on Strong. Ability enrageAbility = new DealtDamageToSourceTriggeredAbility(new AddCountersPlayersEffect(CounterType.RAD.createInstance(3), TargetController.YOU), false, true); - enrageAbility.addEffect(new AddCountersSourceEffect(CounterType.P1P1.createInstance(3)).setText("put three +1/+1 counters on Strong")); + enrageAbility.addEffect(new AddCountersSourceEffect(CounterType.P1P1.createInstance(3)).concatBy("and")); this.addAbility(enrageAbility); // You gain life rather than lose life from radiation. - Ability healAbility = new SimpleStaticAbility(new StrongTheBrutishThespianHealEffect().setText("You gain life rather than lose life from radiation.")); - this.addAbility(healAbility); + this.addAbility(new SimpleStaticAbility(new StrongTheBrutishThespianHealEffect())); } public StrongTheBrutishThespian(StrongTheBrutishThespian card) { @@ -50,29 +50,32 @@ public class StrongTheBrutishThespian extends CardImpl { return new StrongTheBrutishThespian(this); } - class StrongTheBrutishThespianHealEffect extends ContinuousRuleModifyingEffectImpl { +} - protected StrongTheBrutishThespianHealEffect() { - super(Duration.Custom, Outcome.Benefit); - } +// TODO: It doesn't interfere with anything else yet, but this should be restructured as a replacement, not continuous rule modifying +class StrongTheBrutishThespianHealEffect extends ContinuousRuleModifyingEffectImpl { - public StrongTheBrutishThespianHealEffect(StrongTheBrutishThespianHealEffect effect) { - super(effect); - } + StrongTheBrutishThespianHealEffect() { + super(Duration.Custom, Outcome.Benefit); + staticText = "You gain life rather than lose life from radiation"; + } - @Override - public StrongTheBrutishThespianHealEffect copy() { - return new StrongTheBrutishThespianHealEffect(this); - } + private StrongTheBrutishThespianHealEffect(StrongTheBrutishThespianHealEffect effect) { + super(effect); + } - @Override - public boolean checksEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.RADIATION_GAIN_LIFE; - } + @Override + public StrongTheBrutishThespianHealEffect copy() { + return new StrongTheBrutishThespianHealEffect(this); + } - @Override - public boolean applies(GameEvent event, Ability source, Game game) { - return event.getPlayerId().equals(source.getControllerId()); - } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.RADIATION_GAIN_LIFE; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return event.getPlayerId().equals(source.getControllerId()); } } diff --git a/Mage.Sets/src/mage/cards/s/StrongholdAssassin.java b/Mage.Sets/src/mage/cards/s/StrongholdAssassin.java index cfa0017f30c..64db08a91e8 100644 --- a/Mage.Sets/src/mage/cards/s/StrongholdAssassin.java +++ b/Mage.Sets/src/mage/cards/s/StrongholdAssassin.java @@ -14,9 +14,12 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.StaticFilters; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author LevelX2 @@ -35,7 +38,7 @@ public final class StrongholdAssassin extends CardImpl { // {tap}, Sacrifice a creature: Destroy target nonblack creature. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new TapSourceCost()); ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_CREATURE)); - Target target = new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK); + Target target = new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK); ability.addTarget(target); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/StruggleForSkemfar.java b/Mage.Sets/src/mage/cards/s/StruggleForSkemfar.java index 13f0055c916..37ed7ade191 100644 --- a/Mage.Sets/src/mage/cards/s/StruggleForSkemfar.java +++ b/Mage.Sets/src/mage/cards/s/StruggleForSkemfar.java @@ -8,8 +8,8 @@ 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 mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -28,8 +28,8 @@ public final class StruggleForSkemfar extends CardImpl { "(Each deals damage equal to its power to the other.)" )); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent( - 0, 1, StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL, false + this.getSpellAbility().addTarget(new TargetPermanent( + 0, 1, StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL )); // Foretell {G} diff --git a/Mage.Sets/src/mage/cards/s/SubterraneanScout.java b/Mage.Sets/src/mage/cards/s/SubterraneanScout.java index 6e9650ec68c..f714f5c1bec 100644 --- a/Mage.Sets/src/mage/cards/s/SubterraneanScout.java +++ b/Mage.Sets/src/mage/cards/s/SubterraneanScout.java @@ -13,6 +13,7 @@ import mage.constants.SubType; import mage.constants.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -36,7 +37,7 @@ public final class SubterraneanScout extends CardImpl { // When Subterranean Scout enters the battlefield, target creature with power 2 or less can't be blocked this turn. Ability ability = new EntersBattlefieldTriggeredAbility(new CantBeBlockedTargetEffect(), false); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SultaiCharm.java b/Mage.Sets/src/mage/cards/s/SultaiCharm.java index e3857574757..380c7c8377e 100644 --- a/Mage.Sets/src/mage/cards/s/SultaiCharm.java +++ b/Mage.Sets/src/mage/cards/s/SultaiCharm.java @@ -33,7 +33,7 @@ public final class SultaiCharm extends CardImpl { // Choose one - // * Destroy target monocolored creature. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); // * Destroy target artifact or enchantment. diff --git a/Mage.Sets/src/mage/cards/s/SunbirdsInvocation.java b/Mage.Sets/src/mage/cards/s/SunbirdsInvocation.java index 6c27701de1c..b31c57e3a04 100644 --- a/Mage.Sets/src/mage/cards/s/SunbirdsInvocation.java +++ b/Mage.Sets/src/mage/cards/s/SunbirdsInvocation.java @@ -2,23 +2,17 @@ package mage.cards.s; import mage.abilities.Ability; import mage.abilities.common.SpellCastControllerTriggeredAbility; -import mage.abilities.effects.Effect; 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.ComparisonType; -import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.FilterCard; import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.game.Game; -import mage.game.events.GameEvent; import mage.game.stack.Spell; import mage.players.Player; -import mage.target.targetpointer.FixedTarget; import mage.util.CardUtil; import java.util.UUID; @@ -35,7 +29,10 @@ public final class SunbirdsInvocation extends CardImpl { // where X is that spell's converted mana cost. You may cast a card revealed this // way with converted mana cost X or less without paying its mana cost. Put the // rest on the bottom of your library in a random order. - this.addAbility(new SunbirdsInvocationTriggeredAbility()); + this.addAbility(new SpellCastControllerTriggeredAbility( + Zone.BATTLEFIELD, new SunbirdsInvocationEffect(), null, + false, SetTargetPointer.SPELL, Zone.HAND + )); } private SunbirdsInvocation(final SunbirdsInvocation card) { @@ -48,52 +45,14 @@ public final class SunbirdsInvocation extends CardImpl { } } -class SunbirdsInvocationTriggeredAbility extends SpellCastControllerTriggeredAbility { - - SunbirdsInvocationTriggeredAbility() { - super(new SunbirdsInvocationEffect(), false); - } - - private SunbirdsInvocationTriggeredAbility(SunbirdsInvocationTriggeredAbility ability) { - super(ability); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getPlayerId().equals(getControllerId())) { - Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell != null - && spell.getFromZone() == Zone.HAND - && spell.isOwnedBy(getControllerId())) { // must be from the controller's hand - if (spell.getCard() != null) { - for (Effect effect : getEffects()) { - effect.setTargetPointer(new FixedTarget(spell.getId())); - } - return true; - } - } - } - return false; - } - - @Override - public SunbirdsInvocationTriggeredAbility copy() { - return new SunbirdsInvocationTriggeredAbility(this); - } - - @Override - public String getRule() { - return "Whenever you cast a spell from your hand, reveal the top X cards of your library, " + - "where X is that spell's mana value. You may cast a spell with mana value X or less " + - "from among cards revealed this way without paying its mana cost. " + - "Put the rest on the bottom of your library in a random order."; - } -} - class SunbirdsInvocationEffect extends OneShotEffect { SunbirdsInvocationEffect() { super(Outcome.PutCardInPlay); + setText("reveal the top X cards of your library, where X is that spell's mana value. " + + "You may cast a spell with mana value X or less " + + "from among cards revealed this way without paying its mana cost. " + + "Put the rest on the bottom of your library in a random order."); } private SunbirdsInvocationEffect(final SunbirdsInvocationEffect effect) { diff --git a/Mage.Sets/src/mage/cards/s/SundialOfTheInfinite.java b/Mage.Sets/src/mage/cards/s/SundialOfTheInfinite.java index 5fca98c8f07..7a240dcba93 100644 --- a/Mage.Sets/src/mage/cards/s/SundialOfTheInfinite.java +++ b/Mage.Sets/src/mage/cards/s/SundialOfTheInfinite.java @@ -6,11 +6,9 @@ import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.EndTurnEffect; -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; @@ -23,9 +21,10 @@ public final class SundialOfTheInfinite extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); // {1}, {T}: End the turn. Activate this ability only during your turn. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new EndTurnEffect(), new GenericManaCost(1), MyTurnCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new EndTurnEffect(), new GenericManaCost(1), MyTurnCondition.instance + ); ability.addCost(new TapSourceCost()); - ability.addHint(MyTurnHint.instance); this.addAbility(ability); } @@ -37,4 +36,4 @@ public final class SundialOfTheInfinite extends CardImpl { public SundialOfTheInfinite copy() { return new SundialOfTheInfinite(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/s/SungoldSentinel.java b/Mage.Sets/src/mage/cards/s/SungoldSentinel.java index 1951791b24f..b6d6782888b 100644 --- a/Mage.Sets/src/mage/cards/s/SungoldSentinel.java +++ b/Mage.Sets/src/mage/cards/s/SungoldSentinel.java @@ -5,7 +5,7 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility; import mage.abilities.condition.common.CovenCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.effects.common.combat.CantBeBlockedByAllSourceEffect; @@ -43,9 +43,8 @@ public final class SungoldSentinel extends CardImpl { this.addAbility(ability); // Coven — {1}{W}: Choose a color. Sungold Sentinel gains hexproof from that color until end of turn and can't be blocked by creatures of that color this turn. Activate only if you control three or more creatures with different powers. - this.addAbility(new ConditionalActivatedAbility( - Zone.BATTLEFIELD, new SungoldSentinelEffect(), - new ManaCostsImpl<>("{1}{W}"), CovenCondition.instance + this.addAbility(new ActivateIfConditionActivatedAbility( + new SungoldSentinelEffect(), new ManaCostsImpl<>("{1}{W}"), CovenCondition.instance ).addHint(CovenHint.instance).setAbilityWord(AbilityWord.COVEN)); } diff --git a/Mage.Sets/src/mage/cards/s/Sunlance.java b/Mage.Sets/src/mage/cards/s/Sunlance.java index 59f69241c1f..29a371bb8a8 100644 --- a/Mage.Sets/src/mage/cards/s/Sunlance.java +++ b/Mage.Sets/src/mage/cards/s/Sunlance.java @@ -10,6 +10,7 @@ import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -30,7 +31,7 @@ public final class Sunlance extends CardImpl { // Sunlance deals 3 damage to target nonwhite creature. this.getSpellAbility().addEffect(new DamageTargetEffect(3)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private Sunlance(final Sunlance card) { diff --git a/Mage.Sets/src/mage/cards/s/SunscapeBattlemage.java b/Mage.Sets/src/mage/cards/s/SunscapeBattlemage.java index 84fde706032..17180abd35d 100644 --- a/Mage.Sets/src/mage/cards/s/SunscapeBattlemage.java +++ b/Mage.Sets/src/mage/cards/s/SunscapeBattlemage.java @@ -1,12 +1,10 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.KickedCostCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.keyword.FlyingAbility; @@ -17,21 +15,26 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author FenrisulfrX */ public final class SunscapeBattlemage extends CardImpl { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with flying"); + static { filter.add(new AbilityPredicate(FlyingAbility.class)); } + private static final Condition condition = new KickedCostCondition("{1}{G}"); + private static final Condition condition2 = new KickedCostCondition("{2}{U}"); + public SunscapeBattlemage(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.WIZARD); this.power = new MageInt(2); @@ -43,15 +46,12 @@ public final class SunscapeBattlemage extends CardImpl { this.addAbility(kickerAbility); // When {this} enters, if it was kicked with its {1}{G} kicker, destroy target creature with flying. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), false); - ability.addTarget(new TargetCreaturePermanent(filter)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new KickedCostCondition("{1}{G}"), - "When {this} enters, if it was kicked with its {1}{G} kicker, destroy target creature with flying.")); + Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()).withInterveningIf(condition); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); // When {this} enters, if it was kicked with its {2}{U} kicker, draw two cards. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility( - new DrawCardSourceControllerEffect(2)), new KickedCostCondition("{2}{U}"), - "When {this} enters, if it was kicked with its {2}{U} kicker, draw two cards.")); + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(2)).withInterveningIf(condition2)); } private SunscapeBattlemage(final SunscapeBattlemage card) { diff --git a/Mage.Sets/src/mage/cards/s/SunspireGatekeepers.java b/Mage.Sets/src/mage/cards/s/SunspireGatekeepers.java index 991b66ad310..6b31290ab33 100644 --- a/Mage.Sets/src/mage/cards/s/SunspireGatekeepers.java +++ b/Mage.Sets/src/mage/cards/s/SunspireGatekeepers.java @@ -2,17 +2,13 @@ package mage.cards.s; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.condition.Condition; -import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.YouControlTwoOrMoreGatesCondition; import mage.abilities.effects.common.CreateTokenEffect; -import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.common.GatesYouControlHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.ComparisonType; import mage.constants.SubType; -import mage.filter.common.FilterControlledPermanent; import mage.game.permanent.token.KnightToken; import java.util.UUID; @@ -20,18 +16,8 @@ import java.util.UUID; /** * @author LevelX2 */ - - public final class SunspireGatekeepers extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent(); - - static { - filter.add(SubType.GATE.getPredicate()); - } - - private static final Condition gatesCondition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1); - public SunspireGatekeepers(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); this.subtype.add(SubType.HUMAN); @@ -41,11 +27,8 @@ public final class SunspireGatekeepers extends CardImpl { this.toughness = new MageInt(4); // When Sunspire Gatekeepers enter the battlefield, if you control two or more Gates, create a 2/2 white Knight creature token with vigilance. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new KnightToken())), - gatesCondition, - "When {this} enters, if you control two or more Gates, create a 2/2 white Knight creature token with vigilance.") - .addHint(new ConditionHint(gatesCondition, "you control two or more Gates"))); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new KnightToken())) + .withInterveningIf(YouControlTwoOrMoreGatesCondition.instance).addHint(GatesYouControlHint.instance)); } private SunspireGatekeepers(final SunspireGatekeepers card) { diff --git a/Mage.Sets/src/mage/cards/s/SunstrikeLegionnaire.java b/Mage.Sets/src/mage/cards/s/SunstrikeLegionnaire.java index 007dad01b53..b076bf3dc5a 100644 --- a/Mage.Sets/src/mage/cards/s/SunstrikeLegionnaire.java +++ b/Mage.Sets/src/mage/cards/s/SunstrikeLegionnaire.java @@ -20,6 +20,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -49,7 +50,7 @@ public final class SunstrikeLegionnaire extends CardImpl { this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new UntapSourceEffect(), untapFilter, false)); // {tap}: Tap target creature with converted mana cost 3 or less. Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(tapFilter)); + ability.addTarget(new TargetPermanent(tapFilter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SuperState.java b/Mage.Sets/src/mage/cards/s/SuperState.java new file mode 100644 index 00000000000..54c74486952 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SuperState.java @@ -0,0 +1,100 @@ +package mage.cards.s; + +import mage.abilities.Ability; +import mage.abilities.common.DealsDamageToAPlayerAttachedTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.common.SavedDamageValue; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.effects.common.continuous.SetBasePowerToughnessAttachedEffect; +import mage.abilities.keyword.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.Optional; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SuperState extends CardImpl { + + public SuperState(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{7}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.AURA); + + // Enchant creature you control + TargetPermanent auraTarget = new TargetControlledCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + this.addAbility(new EnchantAbility(auraTarget)); + + // Enchanted creature has base power and toughness 9/9 and has flying, first strike, trample, and haste. + Ability ability = new SimpleStaticAbility(new SetBasePowerToughnessAttachedEffect(9, 9, AttachmentType.AURA)); + ability.addEffect(new GainAbilityAttachedEffect(FlyingAbility.getInstance(), AttachmentType.AURA).setText("and has flying")); + ability.addEffect(new GainAbilityAttachedEffect(FirstStrikeAbility.getInstance(), AttachmentType.AURA).setText(", first strike")); + ability.addEffect(new GainAbilityAttachedEffect(TrampleAbility.getInstance(), AttachmentType.AURA).setText(", trample")); + ability.addEffect(new GainAbilityAttachedEffect(HasteAbility.getInstance(), AttachmentType.AURA).setText(", and haste")); + this.addAbility(ability); + + // Whenever enchanted creature deals combat damage to an opponent, it deals that much damage to each other opponent. + this.addAbility(new DealsDamageToAPlayerAttachedTriggeredAbility( + new SuperStateEffect(), "enchanted creature", false, + true, true, TargetController.OPPONENT + )); + } + + private SuperState(final SuperState card) { + super(card); + } + + @Override + public SuperState copy() { + return new SuperState(this); + } +} + +class SuperStateEffect extends OneShotEffect { + + SuperStateEffect() { + super(Outcome.Benefit); + staticText = "it deals that much damage to each other opponent"; + } + + private SuperStateEffect(final SuperStateEffect effect) { + super(effect); + } + + @Override + public SuperStateEffect copy() { + return new SuperStateEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + UUID permanentId = Optional + .ofNullable(source.getSourcePermanentOrLKI(game)) + .map(Permanent::getAttachedTo) + .orElse(null); + int damage = SavedDamageValue.MUCH.calculate(game, source, this); + if (permanentId == null || damage < 1) { + return false; + } + UUID playerId = getTargetPointer().getFirst(game, source); + for (UUID opponentId : game.getOpponents(source.getControllerId())) { + Optional.ofNullable(opponentId) + .filter(uuid -> !uuid.equals(playerId)) + .map(game::getPlayer) + .ifPresent(player -> player.damage(damage, permanentId, source, game)); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/s/SupplyCaravan.java b/Mage.Sets/src/mage/cards/s/SupplyCaravan.java index 432f671342a..d6f488d3d18 100644 --- a/Mage.Sets/src/mage/cards/s/SupplyCaravan.java +++ b/Mage.Sets/src/mage/cards/s/SupplyCaravan.java @@ -1,15 +1,15 @@ - package mage.cards.s; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -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.FilterControlledCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; import mage.game.permanent.token.WarriorVigilantToken; @@ -17,17 +17,18 @@ import mage.game.permanent.token.WarriorVigilantToken; import java.util.UUID; /** - * * @author fireshoes */ public final class SupplyCaravan extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("a tapped creature"); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("you control a tapped creature"); static { filter.add(TappedPredicate.TAPPED); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); + public SupplyCaravan(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}"); @@ -36,9 +37,7 @@ public final class SupplyCaravan extends CardImpl { this.toughness = new MageInt(5); // When Supply Caravan enters the battlefield, if you control a tapped creature, create a 1/1 white Warrior creature token with vigilance. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new WarriorVigilantToken())), - new PermanentsOnTheBattlefieldCondition(filter), - "When {this} enters, if you control a tapped creature, create a 1/1 white Warrior creature token with vigilance.")); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new WarriorVigilantToken())).withInterveningIf(condition)); } private SupplyCaravan(final SupplyCaravan card) { diff --git a/Mage.Sets/src/mage/cards/s/SupremeLeaderSnoke.java b/Mage.Sets/src/mage/cards/s/SupremeLeaderSnoke.java index a827ad49a06..c58a477800a 100644 --- a/Mage.Sets/src/mage/cards/s/SupremeLeaderSnoke.java +++ b/Mage.Sets/src/mage/cards/s/SupremeLeaderSnoke.java @@ -23,6 +23,7 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetadjustment.XManaValueTargetAdjuster; import mage.watchers.Watcher; @@ -31,6 +32,8 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE; + /** * @author NinthWorld */ @@ -59,7 +62,7 @@ public final class SupremeLeaderSnoke extends CardImpl { ability3.addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield).setText("It gains haste")); ability3.addEffect(new GainAbilityTargetEffect(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new SacrificeSourceEffect()), Duration.WhileOnBattlefield) .setText("Sacrifice that creature at the beginning of the next end step")); - ability3.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE)); + ability3.addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE)); ability3.setTargetAdjuster(new XManaValueTargetAdjuster()); this.addAbility(ability3); } diff --git a/Mage.Sets/src/mage/cards/s/SurgeEngine.java b/Mage.Sets/src/mage/cards/s/SurgeEngine.java index 0e525fa1cf4..37713904f21 100644 --- a/Mage.Sets/src/mage/cards/s/SurgeEngine.java +++ b/Mage.Sets/src/mage/cards/s/SurgeEngine.java @@ -17,10 +17,12 @@ import mage.abilities.keyword.CantBeBlockedSourceAbility; import mage.abilities.keyword.DefenderAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; import mage.game.Game; -import java.util.Objects; import java.util.Optional; import java.util.UUID; @@ -50,7 +52,7 @@ public final class SurgeEngine extends CardImpl { // {2}{U}: Surge Engine becomes blue and has base power and toughness 5/4. Activate only if Surge Engine doesn't have defender. ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new BecomesColorSourceEffect(ObjectColor.BLUE, Duration.Custom), + new BecomesColorSourceEffect(ObjectColor.BLUE, Duration.Custom), new ManaCostsImpl<>("{2}{U}"), SurgeEngineCondition.instance ); ability.addEffect(new SetBasePowerToughnessSourceEffect( @@ -85,7 +87,7 @@ enum SurgeEngineCondition implements Condition { @Override public String toString() { - return "if {this} doesn't have defender"; + return "{this} doesn't have defender"; } } diff --git a/Mage.Sets/src/mage/cards/s/SurgeOfRighteousness.java b/Mage.Sets/src/mage/cards/s/SurgeOfRighteousness.java index b5e8abf1f44..d6d9f80a58b 100644 --- a/Mage.Sets/src/mage/cards/s/SurgeOfRighteousness.java +++ b/Mage.Sets/src/mage/cards/s/SurgeOfRighteousness.java @@ -12,6 +12,7 @@ import mage.filter.common.FilterAttackingOrBlockingCreature; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -32,7 +33,7 @@ public final class SurgeOfRighteousness extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W}"); // Destroy target black or red creature that's attacking or blocking. You gain 2 life. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); this.getSpellAbility().addEffect(new GainLifeEffect(2)); } diff --git a/Mage.Sets/src/mage/cards/s/SurrakElusiveHunter.java b/Mage.Sets/src/mage/cards/s/SurrakElusiveHunter.java index 074aa4a8807..4b94ef71e87 100644 --- a/Mage.Sets/src/mage/cards/s/SurrakElusiveHunter.java +++ b/Mage.Sets/src/mage/cards/s/SurrakElusiveHunter.java @@ -16,7 +16,6 @@ import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.stack.Spell; import mage.game.stack.StackObject; -import mage.util.CardUtil; import java.util.UUID; @@ -90,7 +89,7 @@ class SurrakElusiveHunterTriggeredAbility extends TriggeredAbilityImpl { if (!checkTargeted(event.getTargetId(), game)) { return false; } - StackObject targetingObject = CardUtil.findTargetingStackObject(this.getId().toString(), event, game); + StackObject targetingObject = game.findTargetingStackObject(this.getId().toString(), event); return targetingObject != null && game.getOpponents(getControllerId()).contains(targetingObject.getControllerId()); } } diff --git a/Mage.Sets/src/mage/cards/s/SurrakTheHuntCaller.java b/Mage.Sets/src/mage/cards/s/SurrakTheHuntCaller.java index 1a604ab6d66..2b849e7690f 100644 --- a/Mage.Sets/src/mage/cards/s/SurrakTheHuntCaller.java +++ b/Mage.Sets/src/mage/cards/s/SurrakTheHuntCaller.java @@ -1,30 +1,25 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.condition.common.FormidableCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.HasteAbility; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; 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.*; import mage.target.common.TargetControlledCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class SurrakTheHuntCaller extends CardImpl { public SurrakTheHuntCaller(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.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WARRIOR); @@ -32,12 +27,11 @@ public final class SurrakTheHuntCaller extends CardImpl { this.toughness = new MageInt(4); // Formidable — At the beginning of combat on your turn, if creatures you control have total power 8 or greater, target creature you control gains haste until end of turn. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn)), - FormidableCondition.instance, - "Formidable — At the beginning of combat on your turn, if creatures you control have total power 8 or greater, target creature you control gains haste until end of turn."); + Ability ability = new BeginningOfCombatTriggeredAbility(new GainAbilityTargetEffect( + HasteAbility.getInstance(), Duration.EndOfTurn + )).withInterveningIf(FormidableCondition.instance); ability.addTarget(new TargetControlledCreaturePermanent()); - this.addAbility(ability); + this.addAbility(ability.setAbilityWord(AbilityWord.FORMIDABLE)); } private SurrakTheHuntCaller(final SurrakTheHuntCaller card) { diff --git a/Mage.Sets/src/mage/cards/s/SurrakarBanisher.java b/Mage.Sets/src/mage/cards/s/SurrakarBanisher.java index 0b049c9f53e..b4d473462b8 100644 --- a/Mage.Sets/src/mage/cards/s/SurrakarBanisher.java +++ b/Mage.Sets/src/mage/cards/s/SurrakarBanisher.java @@ -12,6 +12,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -34,7 +35,7 @@ public final class SurrakarBanisher extends CardImpl { this.toughness = new MageInt(3); Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), true); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SvyelunitePriest.java b/Mage.Sets/src/mage/cards/s/SvyelunitePriest.java index 8aa108fdba3..0084ae13ebd 100644 --- a/Mage.Sets/src/mage/cards/s/SvyelunitePriest.java +++ b/Mage.Sets/src/mage/cards/s/SvyelunitePriest.java @@ -1,40 +1,40 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.ShroudAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.PhaseStep; -import mage.constants.Zone; +import mage.constants.SubType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class SvyelunitePriest extends CardImpl { public SvyelunitePriest(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.CLERIC); this.power = new MageInt(1); this.toughness = new MageInt(1); // {U}{U}, {tap}: Target creature gains shroud until end of turn. Activate this ability only during your upkeep. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new GainAbilityTargetEffect(ShroudAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{U}{U}"), - new IsStepCondition(PhaseStep.UPKEEP), null); + Ability ability = new ActivateIfConditionActivatedAbility( + new GainAbilityTargetEffect( + ShroudAbility.getInstance(), Duration.EndOfTurn + ), new ManaCostsImpl<>("{U}{U}"), IsStepCondition.getMyUpkeep() + ); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/s/Swarmyard.java b/Mage.Sets/src/mage/cards/s/Swarmyard.java index b1833ba27e9..575fba873aa 100644 --- a/Mage.Sets/src/mage/cards/s/Swarmyard.java +++ b/Mage.Sets/src/mage/cards/s/Swarmyard.java @@ -14,6 +14,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -41,7 +42,7 @@ public final class Swarmyard extends CardImpl { // {tap}: Regenerate target Insect, Rat, Spider, or Squirrel. Ability ability = new SimpleActivatedAbility(new RegenerateTargetEffect(), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/Swat.java b/Mage.Sets/src/mage/cards/s/Swat.java index 336201fd61b..f7d35aed9d9 100644 --- a/Mage.Sets/src/mage/cards/s/Swat.java +++ b/Mage.Sets/src/mage/cards/s/Swat.java @@ -11,6 +11,7 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -31,7 +32,7 @@ public final class Swat extends CardImpl { // Destroy target creature with power 2 or less. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // Cycling {2} this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{2}"))); } diff --git a/Mage.Sets/src/mage/cards/s/SwayOfIllusion.java b/Mage.Sets/src/mage/cards/s/SwayOfIllusion.java index e312df45a2f..d5240b2134b 100644 --- a/Mage.Sets/src/mage/cards/s/SwayOfIllusion.java +++ b/Mage.Sets/src/mage/cards/s/SwayOfIllusion.java @@ -1,19 +1,16 @@ - package mage.cards.s; -import java.util.UUID; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.continuous.BecomesColorTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.filter.StaticFilters; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class SwayOfIllusion extends CardImpl { @@ -22,10 +19,9 @@ public final class SwayOfIllusion extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); // Any number of target creatures become the color of your choice until end of turn. - Effect effect = new BecomesColorTargetEffect(Duration.EndOfTurn); - effect.setText("Any number of target creatures become the color of your choice until end of turn"); - this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, Integer.MAX_VALUE, StaticFilters.FILTER_PERMANENT_CREATURE, false)); + this.getSpellAbility().addEffect(new BecomesColorTargetEffect(Duration.EndOfTurn) + .setText("Any number of target creatures become the color of your choice until end of turn")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, Integer.MAX_VALUE)); // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("
")); diff --git a/Mage.Sets/src/mage/cards/s/SwiftKick.java b/Mage.Sets/src/mage/cards/s/SwiftKick.java index d1f50d8462d..9f49a28e41f 100644 --- a/Mage.Sets/src/mage/cards/s/SwiftKick.java +++ b/Mage.Sets/src/mage/cards/s/SwiftKick.java @@ -8,11 +8,14 @@ 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 mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author LevelX2 */ @@ -29,7 +32,7 @@ public final class SwiftKick extends CardImpl { effect = new FightTargetsEffect(); effect.setText("It fights target creature you don't control"); this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); } private SwiftKick(final SwiftKick card) { diff --git a/Mage.Sets/src/mage/cards/s/SwiftReckoning.java b/Mage.Sets/src/mage/cards/s/SwiftReckoning.java index 58980f6a871..649fd935d54 100644 --- a/Mage.Sets/src/mage/cards/s/SwiftReckoning.java +++ b/Mage.Sets/src/mage/cards/s/SwiftReckoning.java @@ -13,6 +13,7 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -42,7 +43,7 @@ public final class SwiftReckoning extends CardImpl { // Destroy target tapped creature. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private SwiftReckoning(final SwiftReckoning card) { diff --git a/Mage.Sets/src/mage/cards/s/Switcheroo.java b/Mage.Sets/src/mage/cards/s/Switcheroo.java index 40bb2a065db..32dda7fe957 100644 --- a/Mage.Sets/src/mage/cards/s/Switcheroo.java +++ b/Mage.Sets/src/mage/cards/s/Switcheroo.java @@ -1,7 +1,5 @@ - package mage.cards.s; -import java.util.UUID; import mage.abilities.effects.common.continuous.ExchangeControlTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -9,19 +7,20 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * @author noxx */ public final class Switcheroo extends CardImpl { - private static final String rule = "Exchange control of two target creatures"; - public Switcheroo(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{U}"); - + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{U}"); // Exchange control of two target creatures. - this.getSpellAbility().addEffect(new ExchangeControlTargetEffect(Duration.EndOfGame, rule)); + this.getSpellAbility().addEffect(new ExchangeControlTargetEffect( + Duration.EndOfGame, "exchange control of two target creatures" + )); this.getSpellAbility().addTarget(new TargetCreaturePermanent(2)); } diff --git a/Mage.Sets/src/mage/cards/s/SwoopingPteranodon.java b/Mage.Sets/src/mage/cards/s/SwoopingPteranodon.java index 488c2e5c6bd..0c6b47e941d 100644 --- a/Mage.Sets/src/mage/cards/s/SwoopingPteranodon.java +++ b/Mage.Sets/src/mage/cards/s/SwoopingPteranodon.java @@ -26,6 +26,8 @@ import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author jimga150 @@ -62,7 +64,7 @@ public final class SwoopingPteranodon extends CardImpl { ability.addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn).setText("and haste until end of turn.")); ability.addEffect(new SwoopingPteranodonCreateDelayedTriggerEffect()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/s/SwordOfTheChosen.java b/Mage.Sets/src/mage/cards/s/SwordOfTheChosen.java index cdb30c613c3..6ae5cf22d2d 100644 --- a/Mage.Sets/src/mage/cards/s/SwordOfTheChosen.java +++ b/Mage.Sets/src/mage/cards/s/SwordOfTheChosen.java @@ -13,6 +13,7 @@ import mage.constants.Duration; import mage.constants.SuperType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -33,7 +34,7 @@ public final class SwordOfTheChosen extends CardImpl { // {tap}: Target legendary creature gets +2/+2 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(2, 2, Duration.EndOfTurn), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SwordOfTheMeek.java b/Mage.Sets/src/mage/cards/s/SwordOfTheMeek.java index 92f8ad6f43c..c7ef125f9ee 100644 --- a/Mage.Sets/src/mage/cards/s/SwordOfTheMeek.java +++ b/Mage.Sets/src/mage/cards/s/SwordOfTheMeek.java @@ -1,8 +1,7 @@ package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.OneShotEffect; @@ -12,20 +11,22 @@ import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; import mage.filter.predicate.mageobject.ToughnessPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class SwordOfTheMeek extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a 1/1 creature"); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("a 1/1 creature you control"); static { filter.add(new PowerPredicate(ComparisonType.EQUAL_TO, 1)); @@ -33,16 +34,19 @@ public final class SwordOfTheMeek extends CardImpl { } public SwordOfTheMeek(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/+2. - this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(1, 2, Duration.WhileOnBattlefield))); + this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(1, 2))); + // Equip {2} this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(2), false)); + // Whenever a 1/1 creature you control enters, you may return Sword of the Meek from your graveyard to the battlefield, then attach it to that creature. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.GRAVEYARD, new SwordOfTheMeekEffect(), filter, true, SetTargetPointer.PERMANENT) - .setTriggerPhrase("Whenever a 1/1 creature enters under your control, ")); + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + Zone.GRAVEYARD, new SwordOfTheMeekEffect(), filter, true, SetTargetPointer.PERMANENT + )); } private SwordOfTheMeek(final SwordOfTheMeek card) { @@ -59,7 +63,7 @@ class SwordOfTheMeekEffect extends OneShotEffect { SwordOfTheMeekEffect() { super(Outcome.Benefit); - this.staticText = "you may return {this} from your graveyard to the battlefield, then attach it to that creature"; + this.staticText = "you may return this card from your graveyard to the battlefield, then attach it to that creature"; } private SwordOfTheMeekEffect(final SwordOfTheMeekEffect effect) { diff --git a/Mage.Sets/src/mage/cards/s/Symbiosis.java b/Mage.Sets/src/mage/cards/s/Symbiosis.java index 00bbedc8898..0cd976e38b7 100644 --- a/Mage.Sets/src/mage/cards/s/Symbiosis.java +++ b/Mage.Sets/src/mage/cards/s/Symbiosis.java @@ -1,27 +1,24 @@ - package mage.cards.s; -import java.util.UUID; 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.target.common.TargetCreaturePermanent; -/** - * - * @author LoneFox +import java.util.UUID; +/** + * @author LoneFox */ public final class Symbiosis extends CardImpl { public Symbiosis(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}"); // Two target creatures each get +2/+2 until end of turn. + this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2)); this.getSpellAbility().addTarget(new TargetCreaturePermanent(2)); - this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2, Duration.EndOfTurn)); } private Symbiosis(final Symbiosis card) { diff --git a/Mage.Sets/src/mage/cards/s/SymbioticDeployment.java b/Mage.Sets/src/mage/cards/s/SymbioticDeployment.java index bae31e2a3b7..81c761cebf7 100644 --- a/Mage.Sets/src/mage/cards/s/SymbioticDeployment.java +++ b/Mage.Sets/src/mage/cards/s/SymbioticDeployment.java @@ -1,43 +1,33 @@ - package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.common.TapTargetCost; -import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.SkipDrawStepEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.filter.StaticFilters; + +import java.util.UUID; /** - * * @author fireshoes */ public final class SymbioticDeployment extends CardImpl { - - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); - - static { - filter.add(TappedPredicate.UNTAPPED); - } public SymbioticDeployment(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); // Skip your draw step. this.addAbility(new SimpleStaticAbility(new SkipDrawStepEffect())); - + // {1}, Tap two untapped creatures you control: Draw a card. - Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new ManaCostsImpl<>("{1}")); - ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(2, 2, filter, false))); + Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(1), new GenericManaCost(1)); + ability.addCost(new TapTargetCost(2, StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURES)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SymmetryMatrix.java b/Mage.Sets/src/mage/cards/s/SymmetryMatrix.java index 4d57437fbec..059d54e3a5f 100644 --- a/Mage.Sets/src/mage/cards/s/SymmetryMatrix.java +++ b/Mage.Sets/src/mage/cards/s/SymmetryMatrix.java @@ -1,6 +1,6 @@ package mage.cards.s; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.DrawCardSourceControllerEffect; @@ -8,7 +8,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.FilterPermanent; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.Predicate; import mage.game.Game; import mage.game.permanent.Permanent; @@ -20,7 +20,7 @@ import java.util.UUID; */ public final class SymmetryMatrix extends CardImpl { - private static final FilterPermanent filter = new FilterCreaturePermanent("a creature with power equal to its toughness"); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("a creature you control with power equal to its toughness"); static { filter.add(SymmetryMatrixPredicate.instance); @@ -30,9 +30,9 @@ public final class SymmetryMatrix extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); // Whenever a creature with power equal to its toughness you control enters, you may pay {1}. If you do, draw a card. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility(new DoIfCostPaid( - new DrawCardSourceControllerEffect(1), new GenericManaCost(1) - ), filter)); + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new GenericManaCost(1)), filter + )); } private SymmetryMatrix(final SymmetryMatrix card) { diff --git a/Mage.Sets/src/mage/cards/s/SynthInfiltrator.java b/Mage.Sets/src/mage/cards/s/SynthInfiltrator.java index 7af3c8dfa0f..a1475f4fb49 100644 --- a/Mage.Sets/src/mage/cards/s/SynthInfiltrator.java +++ b/Mage.Sets/src/mage/cards/s/SynthInfiltrator.java @@ -45,7 +45,7 @@ public final class SynthInfiltrator extends CardImpl { } }; Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, synthInfiltratorCopyApplier); - effect.setText("You may have {this} enter the battlefield as a copy of any creature on the battlefield, except it's a Synth artifact creature in addition to its other types"); + effect.setText("You may have {this} enter as a copy of any creature on the battlefield, except it's a Synth artifact creature in addition to its other types"); Ability ability = new SimpleStaticAbility(Zone.ALL, new EntersBattlefieldEffect(effect, "", true)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SyrGwynHeroOfAshvale.java b/Mage.Sets/src/mage/cards/s/SyrGwynHeroOfAshvale.java index 3af5f5c8d07..6680746e72c 100644 --- a/Mage.Sets/src/mage/cards/s/SyrGwynHeroOfAshvale.java +++ b/Mage.Sets/src/mage/cards/s/SyrGwynHeroOfAshvale.java @@ -15,10 +15,10 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.permanent.EquippedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -27,11 +27,9 @@ import java.util.UUID; */ public final class SyrGwynHeroOfAshvale extends CardImpl { - private static final FilterControlledCreaturePermanent filter + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("equipped creature you control"); private static final FilterPermanent filter2 - = new FilterControlledPermanent(SubType.EQUIPMENT); - private static final FilterControlledCreaturePermanent filter3 = new FilterControlledCreaturePermanent(SubType.KNIGHT, "Knight"); static { @@ -63,9 +61,8 @@ public final class SyrGwynHeroOfAshvale extends CardImpl { // Equipment you control have equip Knight {0}. this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect( new EquipAbility( - Outcome.AddAbility, new GenericManaCost(0), - new TargetControlledCreaturePermanent(filter3) - ), Duration.WhileOnBattlefield, filter2 + Outcome.AddAbility, new GenericManaCost(0), new TargetPermanent(filter2) + ), Duration.WhileOnBattlefield, StaticFilters.FILTER_CONTROLLED_PERMANENT_EQUIPMENT ).setText("Equipment you control have equip Knight {0}."))); } diff --git a/Mage.Sets/src/mage/cards/s/SzarelGenesisShepherd.java b/Mage.Sets/src/mage/cards/s/SzarelGenesisShepherd.java new file mode 100644 index 00000000000..4783143f058 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SzarelGenesisShepherd.java @@ -0,0 +1,70 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SacrificePermanentTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.MyTurnCondition; +import mage.abilities.dynamicvalue.common.SourcePermanentPowerValue; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.effects.common.ruleModifying.PlayFromGraveyardControllerEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class SzarelGenesisShepherd extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("another nontoken permanent"); + + static { + filter.add(AnotherPredicate.instance); + filter.add(TokenPredicate.FALSE); + } + + public SzarelGenesisShepherd(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{R}{G}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.INSECT); + this.subtype.add(SubType.DRUID); + this.power = new MageInt(2); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // You may play lands from your graveyard. + this.addAbility(new SimpleStaticAbility(PlayFromGraveyardControllerEffect.playLands())); + + // Whenever you sacrifice another nontoken permanent during your turn, put a number of +1/+1 counters equal to Szarel's power on up to one other target creature. + Ability ability = new SacrificePermanentTriggeredAbility( + new AddCountersTargetEffect(CounterType.P1P1.createInstance(), SourcePermanentPowerValue.NOT_NEGATIVE) + .setText("put a number of +1/+1 counters equal to {this}'s power on up to one other target creature"), filter + ).withTriggerCondition(MyTurnCondition.instance); + ability.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + this.addAbility(ability); + } + + private SzarelGenesisShepherd(final SzarelGenesisShepherd card) { + super(card); + } + + @Override + public SzarelGenesisShepherd copy() { + return new SzarelGenesisShepherd(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TARDIS.java b/Mage.Sets/src/mage/cards/t/TARDIS.java index b4556aee1c0..62858d0ab90 100644 --- a/Mage.Sets/src/mage/cards/t/TARDIS.java +++ b/Mage.Sets/src/mage/cards/t/TARDIS.java @@ -5,7 +5,6 @@ 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.PlaneswalkEffect; import mage.abilities.effects.common.continuous.NextSpellCastHasAbilityEffect; import mage.abilities.hint.ConditionHint; @@ -25,11 +24,12 @@ import java.util.UUID; * @author Skiwkr */ public final class TARDIS extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.TIME_LORD); - private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPermanent(SubType.TIME_LORD, "you control a Time Lord") + ); - private static final Hint hint = new ConditionHint(condition, "You control a Time Lord"); + private static final Hint hint = new ConditionHint(condition); public TARDIS(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); @@ -40,19 +40,14 @@ public final class TARDIS extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Whenever TARDIS attacks, if you control a Time Lord, the next spell you cast this turn has cascade and you may planeswalk. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new NextSpellCastHasAbilityEffect(new CascadeAbility()), false), - new PermanentsOnTheBattlefieldCondition(filter), - "Whenever {this} attacks, if you control a Time Lord, the next spell you cast this turn has cascade and you may planeswalk."); + Ability ability = new AttacksTriggeredAbility( + new NextSpellCastHasAbilityEffect(new CascadeAbility()) + ).withInterveningIf(condition); + ability.addEffect(new PlaneswalkEffect(true).concatBy("and")); + this.addAbility(ability.addHint(hint)); - ability.addEffect(new PlaneswalkEffect(true)); - - ability.addHint(hint); - - this.addAbility(ability); // Crew 2 this.addAbility(new CrewAbility(2)); - } private TARDIS(final TARDIS card) { diff --git a/Mage.Sets/src/mage/cards/t/TIEBomber.java b/Mage.Sets/src/mage/cards/t/TIEBomber.java index 72ef2bae096..05adb874de5 100644 --- a/Mage.Sets/src/mage/cards/t/TIEBomber.java +++ b/Mage.Sets/src/mage/cards/t/TIEBomber.java @@ -1,27 +1,29 @@ package mage.cards.t; -import java.util.UUID; import mage.MageInt; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.IsPhaseCondition; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.continuous.LoseAbilitySourceEffect; import mage.abilities.keyword.SpaceflightAbility; 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.TurnPhase; -import mage.constants.Zone; + +import java.util.UUID; /** - * * @author Styxo */ public final class TIEBomber extends CardImpl { + private static final Condition condition = new IsPhaseCondition(TurnPhase.COMBAT); + public TIEBomber(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}{B}"); this.subtype.add(SubType.STARSHIP); @@ -32,12 +34,10 @@ public final class TIEBomber extends CardImpl { this.addAbility(SpaceflightAbility.getInstance()); // {1}: TIE Bomber loses Spaceflight until end od turn. Activate this ability only during combat. - this.addAbility(new ConditionalActivatedAbility( - Zone.BATTLEFIELD, + this.addAbility(new ActivateIfConditionActivatedAbility( new LoseAbilitySourceEffect(SpaceflightAbility.getInstance(), Duration.EndOfTurn), - new GenericManaCost(1), - new IsPhaseCondition(TurnPhase.COMBAT), - "{1}: {this} loses Spaceflight until end od turn. Activate only during combat.")); + new GenericManaCost(1), condition + )); } private TIEBomber(final TIEBomber card) { diff --git a/Mage.Sets/src/mage/cards/t/TabletOfCompleation.java b/Mage.Sets/src/mage/cards/t/TabletOfCompleation.java index 4a009269a93..43a6817091b 100644 --- a/Mage.Sets/src/mage/cards/t/TabletOfCompleation.java +++ b/Mage.Sets/src/mage/cards/t/TabletOfCompleation.java @@ -1,7 +1,5 @@ package mage.cards.t; -import java.util.UUID; - import mage.Mana; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; @@ -21,6 +19,8 @@ import mage.constants.ManaType; import mage.constants.Zone; import mage.counters.CounterType; +import java.util.UUID; + /** * @author TheElk801 */ @@ -44,8 +44,7 @@ public final class TabletOfCompleation extends CardImpl { // {1}, {T}: Draw a card. Activate only if Tablet of Compleation has five or more oil counters on it. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), - new GenericManaCost(1), condition2 + new DrawCardSourceControllerEffect(1), new GenericManaCost(1), condition2 ); ability.addCost(new TapSourceCost()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/t/TacticalAdvantage.java b/Mage.Sets/src/mage/cards/t/TacticalAdvantage.java index e63e6f0ea8e..412a4381318 100644 --- a/Mage.Sets/src/mage/cards/t/TacticalAdvantage.java +++ b/Mage.Sets/src/mage/cards/t/TacticalAdvantage.java @@ -10,6 +10,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.BlockedPredicate; import mage.filter.predicate.permanent.BlockingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -36,7 +37,7 @@ public final class TacticalAdvantage extends CardImpl { // Target blocking or blocked creature you control gets +2/+2 until end of turn. this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2, Duration.EndOfTurn)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private TacticalAdvantage(final TacticalAdvantage card) { diff --git a/Mage.Sets/src/mage/cards/t/TaigamOjutaiMaster.java b/Mage.Sets/src/mage/cards/t/TaigamOjutaiMaster.java index 68cf65183b4..77e7c42cfab 100644 --- a/Mage.Sets/src/mage/cards/t/TaigamOjutaiMaster.java +++ b/Mage.Sets/src/mage/cards/t/TaigamOjutaiMaster.java @@ -2,26 +2,22 @@ package mage.cards.t; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.DelayedTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.common.AttackedThisTurnSourceCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.CantBeCounteredControlledEffect; import mage.abilities.keyword.ReboundAbility; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.FilterSpell; +import mage.filter.StaticFilters; import mage.filter.predicate.Predicates; import mage.game.Game; -import mage.game.events.GameEvent; import mage.game.stack.Spell; -import mage.players.Player; -import mage.target.targetpointer.FixedTarget; +import java.util.Optional; import java.util.UUID; /** @@ -29,16 +25,14 @@ import java.util.UUID; */ public final class TaigamOjutaiMaster extends CardImpl { - private static final String effectText = "Whenever you cast an instant or sorcery spell from your hand, if {this} attacked this turn, that spell gains rebound."; - private static final FilterSpell filter = new FilterSpell("Instant, sorcery, and Dragon spells you control"); + private static final FilterSpell filter = new FilterSpell("instant, sorcery, and Dragon spells you control"); static { - filter.add( - (Predicates.or( - CardType.INSTANT.getPredicate(), - CardType.SORCERY.getPredicate(), - SubType.DRAGON.getPredicate())) - ); + filter.add(Predicates.or( + CardType.INSTANT.getPredicate(), + CardType.SORCERY.getPredicate(), + SubType.DRAGON.getPredicate() + )); } public TaigamOjutaiMaster(UUID ownerId, CardSetInfo setInfo) { @@ -54,10 +48,11 @@ public final class TaigamOjutaiMaster extends CardImpl { this.addAbility(new SimpleStaticAbility(new CantBeCounteredControlledEffect(filter, Duration.WhileOnBattlefield))); // Whenever you cast an instant or sorcery spell from your hand, if Taigam, Ojutai Master attacked this turn, that spell gains rebound. - Ability ability = new ConditionalInterveningIfTriggeredAbility(new TaigamOjutaiMasterTriggeredAbility(), - AttackedThisTurnSourceCondition.instance, - effectText); - this.addAbility(ability); + this.addAbility(new SpellCastControllerTriggeredAbility( + Zone.BATTLEFIELD, new TaigamOjutaiMasterEffect(), + StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, + false, SetTargetPointer.SPELL, Zone.HAND + ).withInterveningIf(AttackedThisTurnSourceCondition.instance)); } private TaigamOjutaiMaster(final TaigamOjutaiMaster card) { @@ -70,84 +65,33 @@ public final class TaigamOjutaiMaster extends CardImpl { } } -class TaigamOjutaiMasterTriggeredAbility extends DelayedTriggeredAbility { +class TaigamOjutaiMasterEffect extends ContinuousEffectImpl { - public TaigamOjutaiMasterTriggeredAbility() { - super(new TaigamOjutaiMasterGainReboundEffect(), Duration.EndOfTurn, true); - setTriggerPhrase("Whenever you cast an instant or sorcery spell from your hand, if {this} attacked this turn, "); - } - - private TaigamOjutaiMasterTriggeredAbility(final TaigamOjutaiMasterTriggeredAbility ability) { - super(ability); - } - - @Override - public TaigamOjutaiMasterTriggeredAbility copy() { - return new TaigamOjutaiMasterTriggeredAbility(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.getPlayerId().equals(this.getControllerId())) { - Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell != null && spell.getFromZone() == Zone.HAND) { - if (spell.getCard() != null - && spell.getCard().isInstantOrSorcery(game)) { - for (Effect effect : getEffects()) { - effect.setTargetPointer(new FixedTarget(spell.getId())); - } - return true; - } - } - } - return false; - } -} - -class TaigamOjutaiMasterGainReboundEffect extends ContinuousEffectImpl { - - TaigamOjutaiMasterGainReboundEffect() { + TaigamOjutaiMasterEffect() { super(Duration.Custom, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); staticText = "that spell gains rebound"; } - private TaigamOjutaiMasterGainReboundEffect(final TaigamOjutaiMasterGainReboundEffect effect) { + private TaigamOjutaiMasterEffect(final TaigamOjutaiMasterEffect effect) { super(effect); } @Override - public TaigamOjutaiMasterGainReboundEffect copy() { - return new TaigamOjutaiMasterGainReboundEffect(this); + public TaigamOjutaiMasterEffect copy() { + return new TaigamOjutaiMasterEffect(this); } @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - Spell spell = game.getStack().getSpell(getTargetPointer().getFirst(game, source)); - if (spell != null) { - Card card = spell.getCard(); - if (card != null) { - addReboundAbility(card, source, game); - } - } else { - discard(); - } - return true; - } - return false; - } - - private void addReboundAbility(Card card, Ability source, Game game) { - boolean found = card.getAbilities(game).containsClass(ReboundAbility.class); - if (!found) { - Ability ability = new ReboundAbility(); - game.getState().addOtherAbility(card, ability); + Spell spell = game.getStack().getSpell(getTargetPointer().getFirst(game, source)); + if (spell == null) { + discard(); + return false; } + Optional.of(spell) + .map(Spell::getCard) + .filter(card -> !card.getAbilities(game).containsClass(ReboundAbility.class)) + .ifPresent(card -> game.getState().addOtherAbility(card, new ReboundAbility())); + return true; } } diff --git a/Mage.Sets/src/mage/cards/t/TailSlash.java b/Mage.Sets/src/mage/cards/t/TailSlash.java index bc5f9619427..ad50c57fbbd 100644 --- a/Mage.Sets/src/mage/cards/t/TailSlash.java +++ b/Mage.Sets/src/mage/cards/t/TailSlash.java @@ -5,11 +5,14 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author LevelX2 */ @@ -21,7 +24,7 @@ public final class TailSlash extends CardImpl { // Target creature you control deals damage equal to its power to target creature you don't control. this.getSpellAbility().addEffect(new DamageWithPowerFromOneToAnotherTargetEffect()); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); } private TailSlash(final TailSlash card) { diff --git a/Mage.Sets/src/mage/cards/t/TajuruArcher.java b/Mage.Sets/src/mage/cards/t/TajuruArcher.java index ac1d5cffa70..18fc688065e 100644 --- a/Mage.Sets/src/mage/cards/t/TajuruArcher.java +++ b/Mage.Sets/src/mage/cards/t/TajuruArcher.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -41,7 +42,7 @@ public final class TajuruArcher extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(2); Ability ability = new AllyEntersBattlefieldTriggeredAbility(new DamageTargetEffect(new PermanentsOnBattlefieldCount(filter)), true); - ability.addTarget(new TargetCreaturePermanent(filterTarget)); + ability.addTarget(new TargetPermanent(filterTarget)); this.addAbility(ability.setAbilityWord(null)); } diff --git a/Mage.Sets/src/mage/cards/t/TakeDown.java b/Mage.Sets/src/mage/cards/t/TakeDown.java index 7cf0576ccc9..14989740706 100644 --- a/Mage.Sets/src/mage/cards/t/TakeDown.java +++ b/Mage.Sets/src/mage/cards/t/TakeDown.java @@ -11,6 +11,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -31,7 +32,7 @@ public final class TakeDown extends CardImpl { // Choose one — // • Take Down deals 4 damage to target creature with flying. this.getSpellAbility().addEffect(new DamageTargetEffect(4)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // • Take Down deals 1 damage to each creature with flying Mode mode = new Mode(new DamageAllEffect(1, filter)); diff --git a/Mage.Sets/src/mage/cards/t/TakeIntoCustody.java b/Mage.Sets/src/mage/cards/t/TakeIntoCustody.java index f0fa97252a3..daf8fa68f64 100644 --- a/Mage.Sets/src/mage/cards/t/TakeIntoCustody.java +++ b/Mage.Sets/src/mage/cards/t/TakeIntoCustody.java @@ -1,7 +1,5 @@ - package mage.cards.t; -import java.util.UUID; import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect; import mage.abilities.effects.common.TapTargetEffect; import mage.cards.CardImpl; @@ -9,8 +7,9 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class TakeIntoCustody extends CardImpl { @@ -20,8 +19,8 @@ public final class TakeIntoCustody extends CardImpl { // Tap target creature. It doesn't untap during its controller's next untap step. this.getSpellAbility().addEffect(new TapTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(1)); this.getSpellAbility().addEffect(new DontUntapInControllersNextUntapStepTargetEffect("It")); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } private TakeIntoCustody(final TakeIntoCustody card) { diff --git a/Mage.Sets/src/mage/cards/t/TakeInventory.java b/Mage.Sets/src/mage/cards/t/TakeInventory.java index f3c89ded44a..11b40c82df5 100644 --- a/Mage.Sets/src/mage/cards/t/TakeInventory.java +++ b/Mage.Sets/src/mage/cards/t/TakeInventory.java @@ -1,7 +1,6 @@ package mage.cards.t; -import java.util.UUID; import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; @@ -13,8 +12,9 @@ import mage.constants.CardType; import mage.filter.FilterCard; import mage.filter.predicate.mageobject.NamePredicate; +import java.util.UUID; + /** - * * @author fireshoes * modified tiera3 - added Hint */ @@ -25,17 +25,18 @@ public final class TakeInventory extends CardImpl { static { filter.add(new NamePredicate("Take Inventory")); } + private static final Hint hint = new ValueHint( "Cards named Take Inventory in your graveyard", new CardsInControllerGraveyardCount(filter) ); public TakeInventory(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}"); // Draw a card, then draw cards equal to the number of cards named Take Inventory in your graveyard. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); Effect effect = new DrawCardSourceControllerEffect(new CardsInControllerGraveyardCount(filter)); - effect.setText(", then draw cards equal to the number of cards named {this} in your graveyard"); + effect.setText(", then draw cards equal to the number of cards named Take Inventory in your graveyard"); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addHint(hint); } diff --git a/Mage.Sets/src/mage/cards/t/TakeVengeance.java b/Mage.Sets/src/mage/cards/t/TakeVengeance.java index 53eb232659f..253cd29bb61 100644 --- a/Mage.Sets/src/mage/cards/t/TakeVengeance.java +++ b/Mage.Sets/src/mage/cards/t/TakeVengeance.java @@ -7,6 +7,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -26,7 +27,7 @@ public final class TakeVengeance extends CardImpl { // Destroy target tapped creature. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private TakeVengeance(final TakeVengeance card) { diff --git a/Mage.Sets/src/mage/cards/t/Takklemaggot.java b/Mage.Sets/src/mage/cards/t/Takklemaggot.java index d67eb63a0bd..45ccdda4756 100644 --- a/Mage.Sets/src/mage/cards/t/Takklemaggot.java +++ b/Mage.Sets/src/mage/cards/t/Takklemaggot.java @@ -101,7 +101,7 @@ class TakklemaggotEffect extends OneShotEffect { } FilterCreaturePermanent filter = new FilterCreaturePermanent(); filter.add(new CanBeEnchantedByPredicate(auraCard)); - Target target = new TargetCreaturePermanent(filter).withNotTarget(true); + Target target = new TargetPermanent(filter).withNotTarget(true); if (!game.getBattlefield().getActivePermanents(filter, player.getId(), source, game).isEmpty() && player.choose(outcome, target, source, game)) { // return attached to that creature diff --git a/Mage.Sets/src/mage/cards/t/TalasResearcher.java b/Mage.Sets/src/mage/cards/t/TalasResearcher.java index 7bd3d41700e..8c1408d0f55 100644 --- a/Mage.Sets/src/mage/cards/t/TalasResearcher.java +++ b/Mage.Sets/src/mage/cards/t/TalasResearcher.java @@ -1,9 +1,6 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.common.MyTurnBeforeAttackersDeclaredCondition; import mage.abilities.costs.common.TapSourceCost; @@ -12,16 +9,16 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; + +import java.util.UUID; /** - * * @author fireshoes */ public final class TalasResearcher extends CardImpl { public TalasResearcher(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.PIRATE); this.subtype.add(SubType.WIZARD); @@ -29,10 +26,10 @@ public final class TalasResearcher extends CardImpl { this.toughness = new MageInt(1); // {tap}: Draw a card. Activate this ability only during your turn, before attackers are declared. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new DrawCardSourceControllerEffect(1), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); - - this.addAbility(ability); + this.addAbility(new ActivateIfConditionActivatedAbility( + new DrawCardSourceControllerEffect(1), new TapSourceCost(), + MyTurnBeforeAttackersDeclaredCondition.instance + )); } private TalasResearcher(final TalasResearcher card) { diff --git a/Mage.Sets/src/mage/cards/t/TaleOfTinuviel.java b/Mage.Sets/src/mage/cards/t/TaleOfTinuviel.java index 436831ae34f..f5ccf51b009 100644 --- a/Mage.Sets/src/mage/cards/t/TaleOfTinuviel.java +++ b/Mage.Sets/src/mage/cards/t/TaleOfTinuviel.java @@ -48,7 +48,7 @@ public final class TaleOfTinuviel extends CardImpl { sagaAbility.addChapterEffect( this, SagaChapter.CHAPTER_III, SagaChapter.CHAPTER_III, new GainAbilityTargetEffect(LifelinkAbility.getInstance(), Duration.EndOfTurn), - new TargetControlledCreaturePermanent(0, 2, StaticFilters.FILTER_CONTROLLED_CREATURES, false) + new TargetControlledCreaturePermanent(0, 2) ); this.addAbility(sagaAbility); } diff --git a/Mage.Sets/src/mage/cards/t/TalionTheKindlyLord.java b/Mage.Sets/src/mage/cards/t/TalionTheKindlyLord.java index c6d438b3499..19ccefbf0f6 100644 --- a/Mage.Sets/src/mage/cards/t/TalionTheKindlyLord.java +++ b/Mage.Sets/src/mage/cards/t/TalionTheKindlyLord.java @@ -75,7 +75,7 @@ enum TalionTheKindlyLordPredicate implements ObjectSourcePlayerPredicate input, Game game) { Object obj = game.getState().getValue( "chosenNumber_" + input.getSource().getSourceId() - + '_' + input.getSource().getSourceObjectZoneChangeCounter() + + '_' + input.getObject().getZoneChangeCounter(game) ); if (obj == null) { return false; diff --git a/Mage.Sets/src/mage/cards/t/TamiyoFieldResearcher.java b/Mage.Sets/src/mage/cards/t/TamiyoFieldResearcher.java index 3fd3f65fb23..85f9c3e17f8 100644 --- a/Mage.Sets/src/mage/cards/t/TamiyoFieldResearcher.java +++ b/Mage.Sets/src/mage/cards/t/TamiyoFieldResearcher.java @@ -42,7 +42,7 @@ public final class TamiyoFieldResearcher extends CardImpl { // +1: Choose up to two target creatures. Until your next turn, whenever either of those creatures deals combat damage, you draw a card. Ability ability = new LoyaltyAbility(new TamiyoFieldResearcherEffect1(), 1); - ability.addTarget(new TargetCreaturePermanent(0, 2, StaticFilters.FILTER_PERMANENT_CREATURES, false)); + ability.addTarget(new TargetCreaturePermanent(0, 2)); this.addAbility(ability); // -2: Tap up to two target nonland permanents. They don't untap during their controller's next untap step. diff --git a/Mage.Sets/src/mage/cards/t/TannukMemorialEnsign.java b/Mage.Sets/src/mage/cards/t/TannukMemorialEnsign.java new file mode 100644 index 00000000000..e6cb55e89ba --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TannukMemorialEnsign.java @@ -0,0 +1,47 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.LandfallAbility; +import mage.abilities.effects.common.DamagePlayersEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.IfAbilityHasResolvedXTimesEffect; +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.watchers.common.AbilityResolvedWatcher; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TannukMemorialEnsign extends CardImpl { + + public TannukMemorialEnsign(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{G}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.KAVU); + this.subtype.add(SubType.PILOT); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // Landfall - Whenever a land you control enters, Tannuk deals 1 damage to each opponent. If this is the second time this ability has resolved this turn, draw a card. + Ability ability = new LandfallAbility(new DamagePlayersEffect(1, TargetController.OPPONENT)); + ability.addEffect(new IfAbilityHasResolvedXTimesEffect(2, new DrawCardSourceControllerEffect(1))); + this.addAbility(ability, new AbilityResolvedWatcher()); + } + + private TannukMemorialEnsign(final TannukMemorialEnsign card) { + super(card); + } + + @Override + public TannukMemorialEnsign copy() { + return new TannukMemorialEnsign(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TapestryOfTheAges.java b/Mage.Sets/src/mage/cards/t/TapestryOfTheAges.java index f4743421a64..da974f65989 100644 --- a/Mage.Sets/src/mage/cards/t/TapestryOfTheAges.java +++ b/Mage.Sets/src/mage/cards/t/TapestryOfTheAges.java @@ -1,44 +1,39 @@ - package mage.cards.t; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; 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; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; /** - * * @author LevelX2 */ public final class TapestryOfTheAges extends CardImpl { public TapestryOfTheAges(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); // {2}, {T}: Draw a card. Activate this ability only if you've cast a noncreature spell this turn. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, - new DrawCardSourceControllerEffect(1), - new ManaCostsImpl<>("{2}"), - PlayerCastNonCreatureSpellCondition.instance); + new DrawCardSourceControllerEffect(1), + new GenericManaCost(2), PlayerCastNonCreatureSpellCondition.instance + ); ability.addCost(new TapSourceCost()); - this.addAbility(ability, new PlayerCastNonCreatureSpellWatcher()); - + this.addAbility(ability, new PlayerCastNonCreatureSpellWatcher()); } private TapestryOfTheAges(final TapestryOfTheAges card) { @@ -59,7 +54,7 @@ enum PlayerCastNonCreatureSpellCondition implements Condition { PlayerCastNonCreatureSpellWatcher watcher = game.getState().getWatcher(PlayerCastNonCreatureSpellWatcher.class); return watcher != null && watcher.playerDidCastNonCreatureSpellThisTurn(source.getControllerId()); } - + @Override public String toString() { return "you've cast a noncreature spell this turn"; diff --git a/Mage.Sets/src/mage/cards/t/TatsunariToadRider.java b/Mage.Sets/src/mage/cards/t/TatsunariToadRider.java index 214c00c68f3..d8938a0caff 100644 --- a/Mage.Sets/src/mage/cards/t/TatsunariToadRider.java +++ b/Mage.Sets/src/mage/cards/t/TatsunariToadRider.java @@ -7,7 +7,6 @@ import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.combat.CantBeBlockedByAllTargetEffect; import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; @@ -34,7 +33,7 @@ import java.util.UUID; */ public final class TatsunariToadRider extends CardImpl { - private static final FilterPermanent filter = new FilterControlledCreaturePermanent(); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("you don't control a creature named Keimi"); private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent(); private static final FilterPermanent filter3 = new FilterControlledPermanent(SubType.FROG); @@ -56,14 +55,10 @@ public final class TatsunariToadRider extends CardImpl { this.toughness = new MageInt(3); // Whenever you cast an enchantment spell, if you don't control a creature named Keimi, create Keimi, a legendary 3/3 black and green Frog creature token with "Whenever you cast an enchantment spell, each opponent loses 1 life and you gain 1 life." - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new SpellCastControllerTriggeredAbility( - new CreateTokenEffect(new KeimiToken()), - StaticFilters.FILTER_SPELL_AN_ENCHANTMENT, false - ), condition, "Whenever you cast an enchantment spell, if you don't control " + - "a creature named Keimi, create Keimi, a legendary 3/3 black and green Frog creature token with " + - "\"Whenever you cast an enchantment spell, each opponent loses 1 life and you gain 1 life.\"" - )); + this.addAbility(new SpellCastControllerTriggeredAbility( + new CreateTokenEffect(new KeimiToken()), + StaticFilters.FILTER_SPELL_AN_ENCHANTMENT, false + ).withInterveningIf(condition)); // {1}{G/U}: Tatsunari, Toad Rider and target Frog you control can't be blocked this turn except by creatures with flying or reach. Ability ability = new SimpleActivatedAbility( diff --git a/Mage.Sets/src/mage/cards/t/TatyovaStewardOfTides.java b/Mage.Sets/src/mage/cards/t/TatyovaStewardOfTides.java index 3128a146b85..b48c6db4d7c 100644 --- a/Mage.Sets/src/mage/cards/t/TatyovaStewardOfTides.java +++ b/Mage.Sets/src/mage/cards/t/TatyovaStewardOfTides.java @@ -2,13 +2,13 @@ package mage.cards.t; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.LandfallAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BecomesCreatureTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.hint.common.LandsYouControlHint; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; @@ -16,6 +16,7 @@ import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.FilterPermanent; import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledLandPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.game.permanent.token.custom.CreatureToken; import mage.target.TargetPermanent; @@ -34,7 +35,8 @@ public final class TatyovaStewardOfTides extends CardImpl { } private static final Condition condition = new PermanentsOnTheBattlefieldCondition( - StaticFilters.FILTER_LAND, ComparisonType.MORE_THAN, 6, true + new FilterControlledLandPermanent("you control seven or more lands"), + ComparisonType.MORE_THAN, 6, true ); public TatyovaStewardOfTides(UUID ownerId, CardSetInfo setInfo) { @@ -52,17 +54,13 @@ public final class TatyovaStewardOfTides extends CardImpl { ))); // Whenever a land you control enters, if you control seven or more lands, up to one target land you control becomes a 3/3 Elemental creature with haste. It's still a land. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldControlledTriggeredAbility(new BecomesCreatureTargetEffect( - new CreatureToken( - 3, 3, "3/3 Elemental creature with haste", SubType.ELEMENTAL - ).withAbility(HasteAbility.getInstance()), false, true, Duration.Custom - ), StaticFilters.FILTER_LAND_A), condition, "Whenever a land enters the battlefield " + - "under your control, if you control seven or more lands, up to one target land you control " + - "becomes a 3/3 Elemental creature with haste. It's still a land." - ); + Ability ability = new LandfallAbility( + new BecomesCreatureTargetEffect(new CreatureToken( + 3, 3, "3/3 Elemental creature with haste", SubType.ELEMENTAL + ).withAbility(HasteAbility.getInstance()), false, true, Duration.Custom) + ).withInterveningIf(condition); ability.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND)); - this.addAbility(ability); + this.addAbility(ability.setAbilityWord(null).addHint(LandsYouControlHint.instance)); } private TatyovaStewardOfTides(final TatyovaStewardOfTides card) { diff --git a/Mage.Sets/src/mage/cards/t/TauntingArbormage.java b/Mage.Sets/src/mage/cards/t/TauntingArbormage.java index ac01271ef3b..b38bc0bffd8 100644 --- a/Mage.Sets/src/mage/cards/t/TauntingArbormage.java +++ b/Mage.Sets/src/mage/cards/t/TauntingArbormage.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.combat.MustBeBlockedByAllTargetEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -33,11 +32,7 @@ public final class TauntingArbormage extends CardImpl { this.addAbility(new KickerAbility("{3}")); // When Taunting Arbormage enters the battlefield, if it was kicked, all creatures able to block target creature this turn do so. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new MustBeBlockedByAllTargetEffect(Duration.EndOfTurn)), - KickedCondition.ONCE, "When {this} enters, if it was kicked, " + - "all creatures able to block target creature this turn do so." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new MustBeBlockedByAllTargetEffect(Duration.EndOfTurn)).withInterveningIf(KickedCondition.ONCE); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TawnossWand.java b/Mage.Sets/src/mage/cards/t/TawnossWand.java index 34c1271b4e8..b209debabcf 100644 --- a/Mage.Sets/src/mage/cards/t/TawnossWand.java +++ b/Mage.Sets/src/mage/cards/t/TawnossWand.java @@ -14,6 +14,7 @@ import mage.constants.ComparisonType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -34,7 +35,7 @@ public final class TawnossWand extends CardImpl { // {2}, {tap}: Target creature with power 2 or less is unblockable this turn. Ability ability = new SimpleActivatedAbility(new CantBeBlockedTargetEffect(), new TapSourceCost()); ability.addCost(new ManaCostsImpl<>("{2}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TazeemRoilmage.java b/Mage.Sets/src/mage/cards/t/TazeemRoilmage.java index 77c3289f3da..567ea897247 100644 --- a/Mage.Sets/src/mage/cards/t/TazeemRoilmage.java +++ b/Mage.Sets/src/mage/cards/t/TazeemRoilmage.java @@ -4,15 +4,13 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; import mage.abilities.keyword.KickerAbility; 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.filter.StaticFilters; import mage.target.common.TargetCardInYourGraveyard; import java.util.UUID; @@ -22,9 +20,6 @@ import java.util.UUID; */ public final class TazeemRoilmage extends CardImpl { - private static final FilterCard filter - = new FilterInstantOrSorceryCard("instant or sorcery card from your graveyard"); - public TazeemRoilmage(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); @@ -37,12 +32,8 @@ public final class TazeemRoilmage extends CardImpl { this.addAbility(new KickerAbility("{4}")); // When Tazeem Roilmage enters the battlefield, if it was kicked, return target instant or sorcery card from your graveyard to your hand. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect(), false), - KickedCondition.ONCE, "When {this} enters, if it was kicked, " + - "return target instant or sorcery card from your graveyard to your hand." - ); - ability.addTarget(new TargetCardInYourGraveyard(filter)); + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect()).withInterveningIf(KickedCondition.ONCE); + ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY_FROM_YOUR_GRAVEYARD)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TeamPennant.java b/Mage.Sets/src/mage/cards/t/TeamPennant.java index db08dfa9020..36d3e3fa5a3 100644 --- a/Mage.Sets/src/mage/cards/t/TeamPennant.java +++ b/Mage.Sets/src/mage/cards/t/TeamPennant.java @@ -14,18 +14,19 @@ import mage.constants.AttachmentType; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.permanent.TokenPredicate; +import mage.target.TargetPermanent; import java.util.UUID; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.target.common.TargetControlledCreaturePermanent; /** * @author TheElk801 */ public final class TeamPennant extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature token"); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("creature token"); static { filter.add(TokenPredicate.TRUE); @@ -48,11 +49,12 @@ public final class TeamPennant extends CardImpl { // Equip creature token {1} this.addAbility(new EquipAbility( - Outcome.BoostCreature, new GenericManaCost(1), new TargetControlledCreaturePermanent(filter), false + Outcome.BoostCreature, new GenericManaCost(1), + new TargetPermanent(filter), false )); // Equip {3} - this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(3), new TargetControlledCreaturePermanent(), false)); + this.addAbility(new EquipAbility(3, false)); } private TeamPennant(final TeamPennant card) { diff --git a/Mage.Sets/src/mage/cards/t/TearsOfValakut.java b/Mage.Sets/src/mage/cards/t/TearsOfValakut.java index 7fb39717873..5eeb74dc09a 100644 --- a/Mage.Sets/src/mage/cards/t/TearsOfValakut.java +++ b/Mage.Sets/src/mage/cards/t/TearsOfValakut.java @@ -10,6 +10,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -32,7 +33,7 @@ public final class TearsOfValakut extends CardImpl { // Tears of Valakut deals 5 damage to target creature with flying. this.getSpellAbility().addEffect(new DamageTargetEffect(5)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private TearsOfValakut(final TearsOfValakut card) { diff --git a/Mage.Sets/src/mage/cards/t/TectonicEdge.java b/Mage.Sets/src/mage/cards/t/TectonicEdge.java index 243bbc9cfb1..eb6f690d91e 100644 --- a/Mage.Sets/src/mage/cards/t/TectonicEdge.java +++ b/Mage.Sets/src/mage/cards/t/TectonicEdge.java @@ -1,6 +1,5 @@ package mage.cards.t; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.Condition; @@ -14,12 +13,12 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; -import mage.constants.Zone; import mage.filter.common.FilterLandPermanent; import mage.target.common.TargetNonBasicLandPermanent; +import java.util.UUID; + /** - * * @author BetaSteward_at_googlemail.com */ public final class TectonicEdge extends CardImpl { @@ -29,14 +28,14 @@ public final class TectonicEdge extends CardImpl { ); public TectonicEdge(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.LAND},null); + super(ownerId, setInfo, new CardType[]{CardType.LAND}, null); // Tap: Add 1. this.addAbility(new ColorlessManaAbility()); // {1}, {T}, Sacrifice Tectonic Edge: Destroy target nonbasic land. Activate only if an opponent controls four or more lands. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new DestroyTargetEffect(), new GenericManaCost(1), condition + new DestroyTargetEffect(), new GenericManaCost(1), condition ); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); diff --git a/Mage.Sets/src/mage/cards/t/TeganJovanka.java b/Mage.Sets/src/mage/cards/t/TeganJovanka.java index 0ea46909739..760b4a9ff55 100644 --- a/Mage.Sets/src/mage/cards/t/TeganJovanka.java +++ b/Mage.Sets/src/mage/cards/t/TeganJovanka.java @@ -15,6 +15,7 @@ import mage.constants.SuperType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.HistoricPredicate; import mage.filter.predicate.permanent.AttackingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -45,7 +46,7 @@ public final class TeganJovanka extends CardImpl { .setText("target attacking historic creature gets +1/+1"), 1 ); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); ability.addEffect(new GainAbilityTargetEffect(IndestructibleAbility.getInstance()) .setText("and gains indestructible until end of turn")); this.addAbility(ability.withFlavorWord("Brave Heart")); diff --git a/Mage.Sets/src/mage/cards/t/TegwyllsScouring.java b/Mage.Sets/src/mage/cards/t/TegwyllsScouring.java index b01786f5bbe..f5b263069dc 100644 --- a/Mage.Sets/src/mage/cards/t/TegwyllsScouring.java +++ b/Mage.Sets/src/mage/cards/t/TegwyllsScouring.java @@ -16,7 +16,6 @@ import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; import mage.filter.predicate.permanent.TappedPredicate; import mage.game.permanent.token.FaerieRogueToken; -import mage.target.common.TargetControlledCreaturePermanent; import java.util.UUID; @@ -24,6 +23,7 @@ import java.util.UUID; * @author karapuzz14 */ public final class TegwyllsScouring extends CardImpl { + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control with flying"); static { @@ -34,11 +34,9 @@ public final class TegwyllsScouring extends CardImpl { public TegwyllsScouring(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{B}{B}"); - // You may cast Tegwyll's Scouring as though it had flash by tapping three untapped creatures you control with flying in addition to paying its other costs. - Cost asThoughCost = new TapTargetCost(new TargetControlledCreaturePermanent(3, 3, filter, true)).setText(""); CostsImpl costs = new CostsImpl<>().setText("tapping three untapped creatures you control with flying"); - costs.add(asThoughCost); + costs.add(new TapTargetCost(3, filter).setText("")); Ability ability = new PayMoreToCastAsThoughtItHadFlashAbility(this, costs); ability.addEffect(new DestroyAllEffect(StaticFilters.FILTER_PERMANENT_CREATURES)); @@ -60,4 +58,4 @@ public final class TegwyllsScouring extends CardImpl { public TegwyllsScouring copy() { return new TegwyllsScouring(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/t/Telethopter.java b/Mage.Sets/src/mage/cards/t/Telethopter.java index 14ffaeed362..b61ade45608 100644 --- a/Mage.Sets/src/mage/cards/t/Telethopter.java +++ b/Mage.Sets/src/mage/cards/t/Telethopter.java @@ -1,7 +1,5 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapTargetCost; @@ -10,30 +8,27 @@ 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.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.constants.SubType; +import mage.filter.StaticFilters; + +import java.util.UUID; /** * @author Loki */ public final class Telethopter extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); - - static { - filter.add(TappedPredicate.UNTAPPED); - } - public Telethopter(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.THOPTER); this.power = new MageInt(3); this.toughness = new MageInt(1); - this.addAbility(new SimpleActivatedAbility(new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, false)))); + + this.addAbility(new SimpleActivatedAbility( + new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), + new TapTargetCost(StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURE) + )); } private Telethopter(final Telethopter card) { diff --git a/Mage.Sets/src/mage/cards/t/TemmetVizierOfNaktamun.java b/Mage.Sets/src/mage/cards/t/TemmetVizierOfNaktamun.java index 98f060d1a8e..91a561a03d9 100644 --- a/Mage.Sets/src/mage/cards/t/TemmetVizierOfNaktamun.java +++ b/Mage.Sets/src/mage/cards/t/TemmetVizierOfNaktamun.java @@ -1,32 +1,30 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.combat.CantBeBlockedTargetEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.keyword.EmbalmAbility; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; 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.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.permanent.TokenPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author fireshoes */ public final class TemmetVizierOfNaktamun extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature token you control"); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("creature token you control"); static { filter.add(TokenPredicate.TRUE); @@ -42,11 +40,9 @@ public final class TemmetVizierOfNaktamun extends CardImpl { this.toughness = new MageInt(2); // At the beginning of combat on your turn, target creature token you control gets +1/+1 until end of turn and can't be blocked this turn. - Ability ability = new BeginningOfCombatTriggeredAbility(new BoostTargetEffect(1, 1, Duration.EndOfTurn)); - Effect effect = new CantBeBlockedTargetEffect(); - effect.setText(" and can't be blocked this turn"); - ability.addEffect(effect); - ability.addTarget(new TargetControlledCreaturePermanent(filter)); + Ability ability = new BeginningOfCombatTriggeredAbility(new BoostTargetEffect(1, 1)); + ability.addEffect(new CantBeBlockedTargetEffect().setText("and can't be blocked this turn")); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // Embalm {3}{W}{U} diff --git a/Mage.Sets/src/mage/cards/t/TempestOwl.java b/Mage.Sets/src/mage/cards/t/TempestOwl.java index 7355eeed445..54b6c534c7e 100644 --- a/Mage.Sets/src/mage/cards/t/TempestOwl.java +++ b/Mage.Sets/src/mage/cards/t/TempestOwl.java @@ -1,11 +1,9 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.KickerAbility; @@ -13,17 +11,18 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.target.TargetPermanent; +import java.util.UUID; + /** - * * @author Rafbill */ public final class TempestOwl extends CardImpl { public TempestOwl(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); @@ -36,9 +35,9 @@ public final class TempestOwl extends CardImpl { this.addAbility(new KickerAbility("{4}{U}")); // When Tempest Owl enters the battlefield, if it was kicked, tap up to three target permanents. - EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new TapTargetEffect(), false); - ability.addTarget(new TargetPermanent(0, 3, new FilterPermanent(), false)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.ONCE, "When {this} enters, if it was kicked, tap up to three target permanents.")); + Ability ability = new EntersBattlefieldTriggeredAbility(new TapTargetEffect(), false).withInterveningIf(KickedCondition.ONCE); + ability.addTarget(new TargetPermanent(0, 3, StaticFilters.FILTER_PERMANENTS)); + this.addAbility(ability); } private TempestOwl(final TempestOwl card) { diff --git a/Mage.Sets/src/mage/cards/t/TempleElder.java b/Mage.Sets/src/mage/cards/t/TempleElder.java index 38c9f2a4328..f243c79457c 100644 --- a/Mage.Sets/src/mage/cards/t/TempleElder.java +++ b/Mage.Sets/src/mage/cards/t/TempleElder.java @@ -1,9 +1,6 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.common.MyTurnBeforeAttackersDeclaredCondition; import mage.abilities.costs.common.TapSourceCost; @@ -12,25 +9,26 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; + +import java.util.UUID; /** - * * @author fireshoes */ public final class TempleElder extends CardImpl { public TempleElder(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.CLERIC); this.power = new MageInt(1); this.toughness = new MageInt(2); // {tap}: You gain 1 life. Activate this ability only during your turn, before attackers are declared. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new GainLifeEffect(1), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); - this.addAbility(ability); + this.addAbility(new ActivateIfConditionActivatedAbility( + new GainLifeEffect(1), new TapSourceCost(), + MyTurnBeforeAttackersDeclaredCondition.instance + )); } private TempleElder(final TempleElder card) { diff --git a/Mage.Sets/src/mage/cards/t/TempleOfCivilization.java b/Mage.Sets/src/mage/cards/t/TempleOfCivilization.java index ee18a2fb64a..0e5544cfd20 100644 --- a/Mage.Sets/src/mage/cards/t/TempleOfCivilization.java +++ b/Mage.Sets/src/mage/cards/t/TempleOfCivilization.java @@ -11,7 +11,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.TimingRule; -import mage.constants.Zone; import mage.game.Game; import mage.watchers.common.PlayerAttackedWatcher; @@ -33,12 +32,8 @@ public final class TempleOfCivilization extends CardImpl { // {2}{W}, {T}: Transform Temple of Civilization. Activate only if you attacked with three or more creatures this turn and only as a sorcery. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, - new TransformSourceEffect(), - new ManaCostsImpl<>("{2}{W}"), - TempleOfCivilizationCondition.instance, - TimingRule.SORCERY - ); + new TransformSourceEffect(), new ManaCostsImpl<>("{2}{W}"), TempleOfCivilizationCondition.instance + ).setTiming(TimingRule.SORCERY); ability.addCost(new TapSourceCost()); this.addAbility(ability, new PlayerAttackedWatcher()); } diff --git a/Mage.Sets/src/mage/cards/t/TempleOfCultivation.java b/Mage.Sets/src/mage/cards/t/TempleOfCultivation.java index 60d3c9327a3..bd991824891 100644 --- a/Mage.Sets/src/mage/cards/t/TempleOfCultivation.java +++ b/Mage.Sets/src/mage/cards/t/TempleOfCultivation.java @@ -2,20 +2,19 @@ package mage.cards.t; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; -import mage.abilities.condition.IntCompareCondition; +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.dynamicvalue.common.PermanentsYouControlCount; import mage.abilities.effects.common.TransformSourceEffect; -import mage.abilities.hint.ValueHint; +import mage.abilities.hint.common.PermanentsYouControlHint; import mage.abilities.mana.GreenManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.TimingRule; -import mage.constants.Zone; -import mage.game.Game; +import mage.filter.common.FilterControlledPermanent; import java.util.UUID; @@ -24,6 +23,10 @@ import java.util.UUID; */ public final class TempleOfCultivation extends CardImpl { + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPermanent("you control ten or more permanents"), ComparisonType.MORE_THAN, 9 + ); + public TempleOfCultivation(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); this.nightCard = true; @@ -35,15 +38,10 @@ public final class TempleOfCultivation extends CardImpl { // {2}{G}, {T}: Transform Temple of Cultivation. Activate only if you control ten or more permanents and only as a sorcery. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, - new TransformSourceEffect(), - new ManaCostsImpl<>("{2}{G}"), - new TempleOfCultivationCondition(), - TimingRule.SORCERY - ); + new TransformSourceEffect(), new ManaCostsImpl<>("{2}{G}"), condition + ).setTiming(TimingRule.SORCERY); ability.addCost(new TapSourceCost()); - ability.addHint(new ValueHint("controlled permanents", PermanentsYouControlCount.instance)); - this.addAbility(ability); + this.addAbility(ability.addHint(PermanentsYouControlHint.instance)); } private TempleOfCultivation(final TempleOfCultivation card) { @@ -55,20 +53,3 @@ public final class TempleOfCultivation extends CardImpl { return new TempleOfCultivation(this); } } - -class TempleOfCultivationCondition extends IntCompareCondition { - - TempleOfCultivationCondition() { - super(ComparisonType.OR_GREATER, 10); - } - - @Override - protected int getInputValue(Game game, Ability source) { - return PermanentsYouControlCount.instance.calculate(game, source, null); - } - - @Override - public String toString() { - return "if you control ten or more permanents"; - } -} diff --git a/Mage.Sets/src/mage/cards/t/TempleOfCyclicalTime.java b/Mage.Sets/src/mage/cards/t/TempleOfCyclicalTime.java index b5639028634..88fa042529e 100644 --- a/Mage.Sets/src/mage/cards/t/TempleOfCyclicalTime.java +++ b/Mage.Sets/src/mage/cards/t/TempleOfCyclicalTime.java @@ -14,7 +14,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.TimingRule; -import mage.constants.Zone; import mage.counters.CounterType; import java.util.UUID; @@ -39,9 +38,8 @@ public final class TempleOfCyclicalTime extends CardImpl { // {2}{U}, {T}: Transform Temple of Cyclical Time. Activate only if it has no time counters on it and only as a sorcery. ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new TransformSourceEffect(), - new ManaCostsImpl<>("{2}{U}"), condition, TimingRule.SORCERY - ); + new TransformSourceEffect(), new ManaCostsImpl<>("{2}{U}"), condition + ).setTiming(TimingRule.SORCERY); ability.addCost(new TapSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TempleOfPower.java b/Mage.Sets/src/mage/cards/t/TempleOfPower.java index 9056b7038f5..c6bb1dc614d 100644 --- a/Mage.Sets/src/mage/cards/t/TempleOfPower.java +++ b/Mage.Sets/src/mage/cards/t/TempleOfPower.java @@ -14,7 +14,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.TimingRule; import mage.constants.WatcherScope; -import mage.constants.Zone; import mage.game.Game; import mage.game.command.CommandObject; import mage.game.events.DamagedEvent; @@ -43,16 +42,10 @@ public final class TempleOfPower extends CardImpl { // {2}{R}, {T}: Transform Temple of Power. Activate only if red sources you controlled dealt 4 or more noncombat damage this turn and only as a sorcery. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, - new TransformSourceEffect(), - new ManaCostsImpl<>("{2}{R}"), - TempleOfPowerCondition.instance, - TimingRule.SORCERY - ); - ability.addWatcher(new TempleOfPowerWatcher()); + new TransformSourceEffect(), new ManaCostsImpl<>("{2}{R}"), TempleOfPowerCondition.instance + ).setTiming(TimingRule.SORCERY); ability.addCost(new TapSourceCost()); - ability.addHint(TempleOfPowerHint.instance); - this.addAbility(ability); + this.addAbility(ability.addHint(TempleOfPowerHint.instance), new TempleOfPowerWatcher()); } private TempleOfPower(final TempleOfPower card) { @@ -77,7 +70,7 @@ enum TempleOfPowerCondition implements Condition { @Override public String toString() { - return "if red sources you controlled dealt 4 or more noncombat damage this turn"; + return "red sources you controlled dealt 4 or more noncombat damage this turn"; } } diff --git a/Mage.Sets/src/mage/cards/t/TempleOfTheDead.java b/Mage.Sets/src/mage/cards/t/TempleOfTheDead.java index 8a4e7056961..0c63338958b 100644 --- a/Mage.Sets/src/mage/cards/t/TempleOfTheDead.java +++ b/Mage.Sets/src/mage/cards/t/TempleOfTheDead.java @@ -12,7 +12,10 @@ import mage.abilities.hint.Hint; import mage.abilities.mana.BlackManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.TargetController; +import mage.constants.TimingRule; import java.util.UUID; @@ -22,7 +25,7 @@ import java.util.UUID; public final class TempleOfTheDead extends CardImpl { private static final Condition condition = new CardsInHandCondition(ComparisonType.FEWER_THAN, 2, TargetController.ANY); - private static final Hint hint = new ConditionHint(condition, "a player has one or fewer cards in hand"); + private static final Hint hint = new ConditionHint(condition); public TempleOfTheDead(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); @@ -35,15 +38,10 @@ public final class TempleOfTheDead extends CardImpl { // {2}{B}, {T}: Transform Temple of the Dead. Activate only if a player has one or fewer cards in hand and only as a sorcery. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, - new TransformSourceEffect(), - new ManaCostsImpl<>("{2}{B}"), - condition, - TimingRule.SORCERY - ); + new TransformSourceEffect(), new ManaCostsImpl<>("{2}{B}"), condition + ).setTiming(TimingRule.SORCERY); ability.addCost(new TapSourceCost()); - ability.addHint(hint); - this.addAbility(ability); + this.addAbility(ability.addHint(hint)); } private TempleOfTheDead(final TempleOfTheDead card) { diff --git a/Mage.Sets/src/mage/cards/t/TemporaryInsanity.java b/Mage.Sets/src/mage/cards/t/TemporaryInsanity.java index 514db387a07..f6044020648 100644 --- a/Mage.Sets/src/mage/cards/t/TemporaryInsanity.java +++ b/Mage.Sets/src/mage/cards/t/TemporaryInsanity.java @@ -1,9 +1,5 @@ - package mage.cards.t; -import mage.MageObject; -import mage.abilities.Ability; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; @@ -12,10 +8,17 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.target.common.TargetCreaturePermanent; +import mage.players.Player; +import mage.target.TargetPermanent; +import java.util.HashSet; +import java.util.Optional; import java.util.UUID; /** @@ -23,22 +26,20 @@ import java.util.UUID; */ public final class TemporaryInsanity extends CardImpl { + private static final FilterPermanent filter = new FilterCreaturePermanent("creature with power less than the number of cards in your graveyard"); + public TemporaryInsanity(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{R}"); // Untap target creature with power less than the number of cards in your graveyard - this.getSpellAbility().addTarget(new TargetCreatureWithPowerLessThanNumberOfCardsInYourGraveyard()); this.getSpellAbility().addEffect(new UntapTargetEffect()); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); // and gain control of it until end of turn. - Effect effect = new GainControlTargetEffect(Duration.EndOfTurn); - effect.setText("and gain control of it until end of turn"); - this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.EndOfTurn).setText("and gain control of it until end of turn")); // That creature gains haste until end of turn. - effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn); - effect.setText("That creature gains haste until end of turn."); - this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn).setText("That creature gains haste until end of turn.")); } private TemporaryInsanity(final TemporaryInsanity card) { @@ -51,46 +52,17 @@ public final class TemporaryInsanity extends CardImpl { } } -class TargetCreatureWithPowerLessThanNumberOfCardsInYourGraveyard extends TargetCreaturePermanent { - - public TargetCreatureWithPowerLessThanNumberOfCardsInYourGraveyard() { - super(); - targetName = "creature with power less than the number of cards in your graveyard"; - } - - private TargetCreatureWithPowerLessThanNumberOfCardsInYourGraveyard(final TargetCreatureWithPowerLessThanNumberOfCardsInYourGraveyard target) { - super(target); - } +enum TemporaryInsanityPredicate implements ObjectSourcePlayerPredicate { + instance; @Override - public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) { - if (super.canTarget(controllerId, id, source, game)) { - Permanent target = game.getPermanent(id); - if (target != null) { - return target.getPower().getValue() < game.getPlayer(source.getControllerId()).getGraveyard().size(); - } - return false; - } - return false; - } - - @Override - public boolean canChoose(UUID sourceControllerId, Ability source, Game game) { - MageObject targetSource = game.getObject(source); - if (targetSource != null) { - for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) { - if (permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)) { - if (permanent.getPower().getValue() < game.getPlayer(sourceControllerId).getGraveyard().size()) { - return true; - } - } - } - } - return false; - } - - @Override - public TargetCreatureWithPowerLessThanNumberOfCardsInYourGraveyard copy() { - return new TargetCreatureWithPowerLessThanNumberOfCardsInYourGraveyard(this); + public boolean apply(ObjectSourcePlayer input, Game game) { + return Optional + .ofNullable(input.getPlayerId()) + .map(game::getPlayer) + .map(Player::getGraveyard) + .map(HashSet::size) + .filter(x -> input.getObject().getPower().getValue() < x) + .isPresent(); } } diff --git a/Mage.Sets/src/mage/cards/t/TemurAscendancy.java b/Mage.Sets/src/mage/cards/t/TemurAscendancy.java index 266e0613e78..4fa88b5809f 100644 --- a/Mage.Sets/src/mage/cards/t/TemurAscendancy.java +++ b/Mage.Sets/src/mage/cards/t/TemurAscendancy.java @@ -1,8 +1,6 @@ - package mage.cards.t; -import java.util.UUID; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; @@ -12,31 +10,37 @@ 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.FilterControlledCreaturePermanent; -import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class TemurAscendancy extends CardImpl { - final private static FilterCreaturePermanent filter = new FilterCreaturePermanent("a creature with power 4 or greater"); + final private static FilterPermanent filter = new FilterControlledCreaturePermanent("a creature you control with power 4 or greater"); + static { filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3)); } public TemurAscendancy(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{G}{U}{R}"); - + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{G}{U}{R}"); // Creatures you control have haste. - this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield, new FilterControlledCreaturePermanent("Creatures")))); - + this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect( + HasteAbility.getInstance(), Duration.WhileOnBattlefield, + StaticFilters.FILTER_PERMANENT_CREATURES + ))); + // Whenever a creature with power 4 or greater you control enters, you may draw a card. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), filter, true)); + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + new DrawCardSourceControllerEffect(1), filter, true + )); } private TemurAscendancy(final TemurAscendancy card) { diff --git a/Mage.Sets/src/mage/cards/t/TemurCharm.java b/Mage.Sets/src/mage/cards/t/TemurCharm.java index bc5ccdaf423..37dd4b3203f 100644 --- a/Mage.Sets/src/mage/cards/t/TemurCharm.java +++ b/Mage.Sets/src/mage/cards/t/TemurCharm.java @@ -16,12 +16,15 @@ import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.TargetSpell; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author LevelX2 */ @@ -44,7 +47,7 @@ public final class TemurCharm extends CardImpl { effect.setText("It fights target creature you don't control"); this.getSpellAbility().addEffect(effect); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - Target target = new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL); + Target target = new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL); this.getSpellAbility().addTarget(target); // Counter target spell unless its controller pays {3}. diff --git a/Mage.Sets/src/mage/cards/t/TemurWarShaman.java b/Mage.Sets/src/mage/cards/t/TemurWarShaman.java index 15f0ea0907c..0b9ded054cb 100644 --- a/Mage.Sets/src/mage/cards/t/TemurWarShaman.java +++ b/Mage.Sets/src/mage/cards/t/TemurWarShaman.java @@ -16,10 +16,13 @@ import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author LevelX2 */ @@ -37,7 +40,7 @@ public final class TemurWarShaman extends CardImpl { // Whenever a permanent you control is turned face up, if it is a creature, you may have it fight target creature you don't control. Ability ability = new TemurWarShamanTriggeredAbility(); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + ability.addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TenaciousTomeseeker.java b/Mage.Sets/src/mage/cards/t/TenaciousTomeseeker.java index a257eff3a7a..835e8e2547d 100644 --- a/Mage.Sets/src/mage/cards/t/TenaciousTomeseeker.java +++ b/Mage.Sets/src/mage/cards/t/TenaciousTomeseeker.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.BargainedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; import mage.abilities.hint.common.BargainCostWasPaidHint; import mage.abilities.keyword.BargainAbility; @@ -34,11 +33,7 @@ public final class TenaciousTomeseeker extends CardImpl { this.addAbility(new BargainAbility()); // When Tenacious Tomeseeker enters the battlefield, if it was bargained, return target instant or sorcery card from your graveyard to your hand. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect()), - BargainedCondition.instance, "When {this} enters, if it was bargained, " + - "return target instant or sorcery card from your graveyard to your hand." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect()).withInterveningIf(BargainedCondition.instance); ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY_FROM_YOUR_GRAVEYARD)); this.addAbility(ability.addHint(BargainCostWasPaidHint.instance)); } diff --git a/Mage.Sets/src/mage/cards/t/TerritorialAllosaurus.java b/Mage.Sets/src/mage/cards/t/TerritorialAllosaurus.java index 2a761be939e..2ab55d1ebef 100644 --- a/Mage.Sets/src/mage/cards/t/TerritorialAllosaurus.java +++ b/Mage.Sets/src/mage/cards/t/TerritorialAllosaurus.java @@ -1,24 +1,21 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.FightTargetSourceEffect; import mage.abilities.keyword.KickerAbility; 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.AnotherPredicate; -import mage.target.common.TargetCreaturePermanent; +import mage.filter.StaticFilters; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class TerritorialAllosaurus extends CardImpl { @@ -34,14 +31,11 @@ public final class TerritorialAllosaurus extends CardImpl { this.addAbility(new KickerAbility("{2}{G}")); // When Territorial Allosaurus enters the battlefield, if it was kicked, it fights another target creature. - EntersBattlefieldTriggeredAbility ability - = new EntersBattlefieldTriggeredAbility(new FightTargetSourceEffect()); - Ability conditionalAbility = new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.ONCE, - "When {this} enters, if it was kicked, it fights another target creature."); - FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(AnotherPredicate.instance); - conditionalAbility.addTarget(new TargetCreaturePermanent(filter)); - this.addAbility(conditionalAbility); + Ability ability = new EntersBattlefieldTriggeredAbility(new FightTargetSourceEffect()) + .withInterveningIf(KickedCondition.ONCE) + .withRuleTextReplacement(true); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + this.addAbility(ability); } private TerritorialAllosaurus(final TerritorialAllosaurus card) { diff --git a/Mage.Sets/src/mage/cards/t/TerritorialBoar.java b/Mage.Sets/src/mage/cards/t/TerritorialBoar.java index 69fc58b3bc5..7d423f35c28 100644 --- a/Mage.Sets/src/mage/cards/t/TerritorialBoar.java +++ b/Mage.Sets/src/mage/cards/t/TerritorialBoar.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.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.VigilanceAbility; @@ -13,7 +13,7 @@ import mage.constants.ComparisonType; import mage.constants.Duration; import mage.constants.SubType; import mage.filter.FilterPermanent; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; import java.util.UUID; @@ -24,7 +24,7 @@ import java.util.UUID; public final class TerritorialBoar extends CardImpl { private static final FilterPermanent filter - = new FilterCreaturePermanent("a creature with power 4 or greater"); + = new FilterControlledCreaturePermanent("a creature you control with power 4 or greater"); static { filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3)); @@ -38,7 +38,7 @@ public final class TerritorialBoar extends CardImpl { this.toughness = new MageInt(2); // Whenever a creature with power 4 or greater you control enters, Territorial Boar gets +1/+1 and gains vigilance until end of turn. - Ability ability = new EntersBattlefieldControlledTriggeredAbility(new BoostSourceEffect( + Ability ability = new EntersBattlefieldAllTriggeredAbility(new BoostSourceEffect( 1, 1, Duration.EndOfTurn ).setText("{this} gets +1/+1"), filter); ability.addEffect(new GainAbilitySourceEffect( diff --git a/Mage.Sets/src/mage/cards/t/TerritorialHammerskull.java b/Mage.Sets/src/mage/cards/t/TerritorialHammerskull.java index f03aa39f640..faabc50cb81 100644 --- a/Mage.Sets/src/mage/cards/t/TerritorialHammerskull.java +++ b/Mage.Sets/src/mage/cards/t/TerritorialHammerskull.java @@ -11,8 +11,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author TheElk801 @@ -28,7 +31,7 @@ public final class TerritorialHammerskull extends CardImpl { // Whenever Territorial Hammerskull attacks, tap target creature an opponent controls. Ability ability = new AttacksTriggeredAbility(new TapTargetEffect(), false); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TerritorialWitchstalker.java b/Mage.Sets/src/mage/cards/t/TerritorialWitchstalker.java index 15e0ca3a6d8..f67723fe5c9 100644 --- a/Mage.Sets/src/mage/cards/t/TerritorialWitchstalker.java +++ b/Mage.Sets/src/mage/cards/t/TerritorialWitchstalker.java @@ -1,31 +1,29 @@ package mage.cards.t; -import java.util.UUID; - import mage.MageInt; -import mage.abilities.TriggeredAbility; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; +import mage.abilities.Ability; import mage.abilities.condition.common.FerociousCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.combat.CanAttackAsThoughItDidntHaveDefenderSourceEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.hint.common.FerociousHint; import mage.abilities.keyword.DefenderAbility; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; 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 Xanderhall */ public final class TerritorialWitchstalker extends CardImpl { public TerritorialWitchstalker(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); - + this.subtype.add(SubType.WOLF); this.power = new MageInt(2); this.toughness = new MageInt(3); @@ -34,16 +32,11 @@ public final class TerritorialWitchstalker extends CardImpl { this.addAbility(DefenderAbility.getInstance()); // At the beginning of combat on your turn, if you control a creature with power 4 or greater, Territorial Witchstalker gets +1/+0 until end of turn and can attack this turn as though it didn't have defender. - TriggeredAbility ability = new BeginningOfCombatTriggeredAbility(new BoostSourceEffect(1, 0, Duration.EndOfTurn)); - ability.addEffect(new CanAttackAsThoughItDidntHaveDefenderSourceEffect(Duration.EndOfTurn)); - ability.addHint(FerociousHint.instance); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - ability, - FerociousCondition.instance, - "At the beginning of combat on your turn, if you control a creature with power 4 or greater, " - + "{this} gets +1/+0 until end of turn and can attack this turn as though it didn't have defender" - )); - + Ability ability = new BeginningOfCombatTriggeredAbility( + new BoostSourceEffect(1, 0, Duration.EndOfTurn) + ).withInterveningIf(FerociousCondition.instance); + ability.addEffect(new CanAttackAsThoughItDidntHaveDefenderSourceEffect(Duration.EndOfTurn, "and")); + this.addAbility(ability.addHint(FerociousHint.instance)); } private TerritorialWitchstalker(final TerritorialWitchstalker card) { diff --git a/Mage.Sets/src/mage/cards/t/TerritoryForge.java b/Mage.Sets/src/mage/cards/t/TerritoryForge.java index 50eea890d86..a17768652fd 100644 --- a/Mage.Sets/src/mage/cards/t/TerritoryForge.java +++ b/Mage.Sets/src/mage/cards/t/TerritoryForge.java @@ -5,7 +5,6 @@ import mage.abilities.ActivatedAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.CastFromEverywhereSourceCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.ExileTargetEffect; import mage.cards.Card; @@ -37,11 +36,8 @@ public final class TerritoryForge extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}{R}"); // When Territory Forge enters the battlefield, if you cast it, exile target artifact or land. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new ExileTargetEffect().setToSourceExileZone(true)), - CastFromEverywhereSourceCondition.instance, - "When {this} enters, if you cast it, exile target artifact or land." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new ExileTargetEffect().setToSourceExileZone(true)) + .withInterveningIf(CastFromEverywhereSourceCondition.instance); ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); @@ -89,7 +85,7 @@ class TerritoryForgeStaticEffect extends ContinuousEffectImpl { } for (Card card : exileZone.getCards(game)) { for (Ability ability : card.getAbilities(game)) { - if (ability.isActivatedAbility()){ + if (ability.isActivatedAbility()) { ActivatedAbility copyAbility = (ActivatedAbility) ability.copy(); permanent.addAbility(copyAbility, source.getSourceId(), game, true); } diff --git a/Mage.Sets/src/mage/cards/t/Terror.java b/Mage.Sets/src/mage/cards/t/Terror.java index ff4dfbb1d25..50616805905 100644 --- a/Mage.Sets/src/mage/cards/t/Terror.java +++ b/Mage.Sets/src/mage/cards/t/Terror.java @@ -10,6 +10,7 @@ import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -29,7 +30,7 @@ public final class Terror extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{B}"); // Destroy target nonartifact, nonblack creature. It can't be regenerated. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(FILTER)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER)); this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); } diff --git a/Mage.Sets/src/mage/cards/t/TestOfEndurance.java b/Mage.Sets/src/mage/cards/t/TestOfEndurance.java index de2584e22eb..4ba3ab56648 100644 --- a/Mage.Sets/src/mage/cards/t/TestOfEndurance.java +++ b/Mage.Sets/src/mage/cards/t/TestOfEndurance.java @@ -1,30 +1,29 @@ - package mage.cards.t; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.TriggeredAbility; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.LifeCompareCondition; import mage.abilities.effects.common.WinGameSourceControllerEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.game.Game; +import mage.constants.ComparisonType; +import mage.constants.TargetController; + +import java.util.UUID; /** - * * @author fireshoes */ public final class TestOfEndurance extends CardImpl { + private static final Condition condition = new LifeCompareCondition(TargetController.YOU, ComparisonType.OR_GREATER, 50); + public TestOfEndurance(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); // At the beginning of your upkeep, if you have 50 or more life, you win the game. - TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new FiftyOrMoreLifeCondition(), "At the beginning of your upkeep, if you have 50 or more life, you win the game.")); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect()).withInterveningIf(condition)); } private TestOfEndurance(final TestOfEndurance card) { @@ -36,12 +35,3 @@ public final class TestOfEndurance extends CardImpl { return new TestOfEndurance(this); } } - - -class FiftyOrMoreLifeCondition implements Condition { - - @Override - public boolean apply(Game game, Ability source) { - return game.getPlayer(source.getControllerId()).getLife() >= 50; - } -} diff --git a/Mage.Sets/src/mage/cards/t/TetsuoImperialChampion.java b/Mage.Sets/src/mage/cards/t/TetsuoImperialChampion.java index 5452d742939..7f250f63ebf 100644 --- a/Mage.Sets/src/mage/cards/t/TetsuoImperialChampion.java +++ b/Mage.Sets/src/mage/cards/t/TetsuoImperialChampion.java @@ -5,11 +5,9 @@ import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.EquippedSourceCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.cost.CastFromHandForFreeEffect; -import mage.abilities.hint.Hint; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -40,10 +38,9 @@ public final class TetsuoImperialChampion extends CardImpl { } static final GreatestAmongPermanentsValue xValue = new GreatestAmongPermanentsValue(GreatestAmongPermanentsValue.Quality.ManaValue, filterEquipment); - private static final Hint hint = xValue.getHint(); private static final FilterCard filter = new FilterInstantOrSorceryCard( "an instant or sorcery spell from your hand with mana value " + - "less than or equal to the highest mana value among Equipment attached to {this}" + "less than or equal to the greatest mana value among Equipment attached to {this}" ); static { @@ -61,19 +58,16 @@ public final class TetsuoImperialChampion extends CardImpl { // Whenever Tetsuo, Imperial Champion attacks, if it's equipped, choose one -- // * Tetsuo deals damage equal to the greatest mana value among Equipment attached to it to any target. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new DamageTargetEffect( - xValue, "it" - ).setText("{this} deals damage equal to the greatest mana value " + - "among Equipment attached to it to any target") - ).setTriggerPhrase("Whenever {this} attacks, if it's equipped, "), - EquippedSourceCondition.instance, null - ); + Ability ability = new AttacksTriggeredAbility( + new DamageTargetEffect(xValue, "it") + .setText("{this} deals damage equal to the greatest mana value " + + "among Equipment attached to it to any target") + ).withInterveningIf(EquippedSourceCondition.instance); ability.addTarget(new TargetAnyTarget()); // * You may cast an instant or sorcery spell from your hand with mana value less than or equal to the greatest mana value among Equipment attached to Tetsuo without paying its mana cost. ability.addMode(new Mode(new CastFromHandForFreeEffect(filter))); - this.addAbility(ability); + this.addAbility(ability.addHint(xValue.getHint())); } private TetsuoImperialChampion(final TetsuoImperialChampion card) { @@ -94,4 +88,4 @@ enum TetsuoImperialChampionPredicate implements ObjectSourcePlayerPredicate("{U}{B}{B}{R}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(creatureFilter)); + ability.addTarget(new TargetPermanent(creatureFilter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TezzeretCruelCaptain.java b/Mage.Sets/src/mage/cards/t/TezzeretCruelCaptain.java new file mode 100644 index 00000000000..6f00f74a9b7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TezzeretCruelCaptain.java @@ -0,0 +1,99 @@ +package mage.cards.t; + +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.GetEmblemEffect; +import mage.abilities.effects.common.UntapTargetEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.counters.CounterType; +import mage.filter.FilterCard; +import mage.filter.StaticFilters; +import mage.filter.common.FilterArtifactCard; +import mage.filter.predicate.mageobject.ManaValuePredicate; +import mage.game.Game; +import mage.game.command.emblems.TezzeretCruelCaptainEmblem; +import mage.target.TargetPermanent; +import mage.target.common.TargetCardInLibrary; + +import java.util.Optional; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TezzeretCruelCaptain extends CardImpl { + + private static final FilterCard filter = new FilterArtifactCard("an artifact card with mana value 1 or less"); + + static { + filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 2)); + } + + public TezzeretCruelCaptain(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{3}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.TEZZERET); + this.setStartingLoyalty(4); + + // Whenever an artifact you control enters, put a loyalty counter on Tezzeret. + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + new AddCountersSourceEffect(CounterType.LOYALTY.createInstance()), + StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT + )); + + // 0: Untap target artifact or creature. If it's an artifact creature, put a +1/+1 counter on it. + Ability ability = new LoyaltyAbility(new UntapTargetEffect(), 0); + ability.addEffect(new TezzeretCruelCaptainEffect()); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_CREATURE)); + this.addAbility(ability); + + // -3: Search your library for an artifact card with mana value 1 or less, reveal it, put it in your hand, then shuffle. + this.addAbility(new LoyaltyAbility(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter), true), -3)); + + // -7: You get an emblem with "At the beginning of combat on your turn, put three +1/+1 counters on target artifact you control. If it's not a creature, it becomes a 0/0 Robot artifact creature." + this.addAbility(new LoyaltyAbility(new GetEmblemEffect(new TezzeretCruelCaptainEmblem()), -7)); + } + + private TezzeretCruelCaptain(final TezzeretCruelCaptain card) { + super(card); + } + + @Override + public TezzeretCruelCaptain copy() { + return new TezzeretCruelCaptain(this); + } +} + +class TezzeretCruelCaptainEffect extends OneShotEffect { + + TezzeretCruelCaptainEffect() { + super(Outcome.Benefit); + staticText = "If it's an artifact creature, put a +1/+1 counter on it"; + } + + private TezzeretCruelCaptainEffect(final TezzeretCruelCaptainEffect effect) { + super(effect); + } + + @Override + public TezzeretCruelCaptainEffect copy() { + return new TezzeretCruelCaptainEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return Optional + .ofNullable(this.getTargetPointer().getFirst(game, source)) + .map(game::getPermanent) + .filter(permanent -> permanent.isArtifact(game) && permanent.isCreature(game)) + .filter(permanent -> permanent.addCounters(CounterType.P1P1.createInstance(), source, game)) + .isPresent(); + } +} diff --git a/Mage.Sets/src/mage/cards/t/ThaumaticCompass.java b/Mage.Sets/src/mage/cards/t/ThaumaticCompass.java index 9775d9890cd..9f87ab86bfc 100644 --- a/Mage.Sets/src/mage/cards/t/ThaumaticCompass.java +++ b/Mage.Sets/src/mage/cards/t/ThaumaticCompass.java @@ -1,33 +1,36 @@ - package mage.cards.t; -import java.util.UUID; - import mage.abilities.Ability; -import mage.abilities.TriggeredAbility; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; 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.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; +import mage.abilities.hint.common.LandsYouControlHint; import mage.abilities.keyword.TransformAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; 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.filter.common.FilterLandPermanent; import mage.target.common.TargetCardInLibrary; +import java.util.UUID; + /** * @author TheElk801 */ public final class ThaumaticCompass extends CardImpl { + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterLandPermanent("you control seven or more lands"), + ComparisonType.MORE_THAN, 6, true + ); + public ThaumaticCompass(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); this.secondSideCardClazz = mage.cards.s.SpiresOfOrazca.class; @@ -41,11 +44,8 @@ public final class ThaumaticCompass extends CardImpl { // At the beginning of your end step, if you control seven or more lands, transform Thaumatic Compass. this.addAbility(new TransformAbility()); - TriggeredAbility ability2 = new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - ability2, - new PermanentsOnTheBattlefieldCondition(new FilterLandPermanent(), ComparisonType.MORE_THAN, 6, true), - "At the beginning of your end step, if you control seven or more lands, transform {this}.")); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new TransformSourceEffect()) + .withInterveningIf(condition).addHint(LandsYouControlHint.instance)); } private ThaumaticCompass(final ThaumaticCompass card) { diff --git a/Mage.Sets/src/mage/cards/t/TheAbyss.java b/Mage.Sets/src/mage/cards/t/TheAbyss.java index 6dd1e11a16b..be31f6b28fa 100644 --- a/Mage.Sets/src/mage/cards/t/TheAbyss.java +++ b/Mage.Sets/src/mage/cards/t/TheAbyss.java @@ -1,35 +1,42 @@ - package mage.cards.t; -import java.util.UUID; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SuperType; -import mage.constants.Zone; +import mage.constants.TargetController; +import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; -import mage.game.events.GameEvent; -import mage.players.Player; import mage.target.Target; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; +import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetpointer.FirstTargetPointer; + +import java.util.UUID; /** - * * @author emerald000 */ public final class TheAbyss extends CardImpl { + private static final FilterPermanent filter = new FilterPermanent("nonartifact creature that player controls of their choice"); + public TheAbyss(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}"); this.supertype.add(SuperType.WORLD); // At the beginning of each player's upkeep, destroy target nonartifact creature that player controls of their choice. It can't be regenerated. - this.addAbility(new TheAbyssTriggeredAbility()); + Ability ability = new BeginningOfUpkeepTriggeredAbility(TargetController.EACH_PLAYER, + new DestroyTargetEffect(true), false).withTargetPointerSet(true); + ability.addTarget(new TargetPermanent(filter)); // Only used for text generation + ability.setTargetAdjuster(TheAbyssTargetAdjuster.instance); + this.addAbility(ability); } private TheAbyss(final TheAbyss card) { @@ -42,45 +49,25 @@ public final class TheAbyss extends CardImpl { } } -class TheAbyssTriggeredAbility extends TriggeredAbilityImpl { +enum TheAbyssTargetAdjuster implements TargetAdjuster { + instance; - TheAbyssTriggeredAbility() { - super(Zone.BATTLEFIELD, new DestroyTargetEffect(true), false); - } - - private TheAbyssTriggeredAbility(final TheAbyssTriggeredAbility ability) { - super(ability); + private static final FilterPermanent filter + = new FilterCreaturePermanent("nonartifact creature that player controls of their choice"); + static { + filter.add(Predicates.not(CardType.ARTIFACT.getPredicate())); } @Override - public TheAbyssTriggeredAbility copy() { - return new TheAbyssTriggeredAbility(this); - } + public void adjustTargets(Ability ability, Game game) { + UUID playerId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability); + ability.getTargets().clear(); + ability.getAllEffects().setTargetPointer(new FirstTargetPointer()); - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.UPKEEP_STEP_PRE; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - Player player = game.getPlayer(event.getPlayerId()); - if (player != null) { - FilterCreaturePermanent filter = new FilterCreaturePermanent("nonartifact creature you control"); - filter.add(Predicates.not(CardType.ARTIFACT.getPredicate())); - filter.add(new ControllerIdPredicate(player.getId())); - Target target = new TargetCreaturePermanent(filter); - target.setAbilityController(getControllerId()); - target.setTargetController(player.getId()); - this.getTargets().clear(); - this.getTargets().add(target); - return true; - } - return false; - } - - @Override - public String getRule() { - return "At the beginning of each player's upkeep, destroy target nonartifact creature that player controls of their choice. It can't be regenerated."; + FilterPermanent adjustedFilter = filter.copy(); + adjustedFilter.add(new ControllerIdPredicate(playerId)); + Target newTarget = new TargetPermanent(adjustedFilter); + newTarget.setTargetController(playerId); + ability.addTarget(newTarget); } } diff --git a/Mage.Sets/src/mage/cards/t/TheApprenticesFolly.java b/Mage.Sets/src/mage/cards/t/TheApprenticesFolly.java index d5c884bddb4..36ae2a78dd1 100644 --- a/Mage.Sets/src/mage/cards/t/TheApprenticesFolly.java +++ b/Mage.Sets/src/mage/cards/t/TheApprenticesFolly.java @@ -17,7 +17,7 @@ import mage.filter.predicate.mageobject.NamePredicate; import mage.filter.predicate.permanent.TokenPredicate; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -53,7 +53,7 @@ public final class TheApprenticesFolly extends CardImpl { .setText("choose target nontoken creature you control that doesn't have the same name as a " + "token you control. Create a token that's a copy of it, except it isn't legendary, " + "is a Reflection in addition to its other types, and has haste"), - new TargetControlledCreaturePermanent(filter) + new TargetPermanent(filter) ); // III -- Sacrifice all Reflections you control. @@ -88,4 +88,4 @@ enum TheApprenticesFollyPredicate implements ObjectSourcePlayerPredicate { } } -class TheLordOfPainTriggeredAbility extends SpellCastAllTriggeredAbility { - private static final FilterSpell filter = new FilterSpell("their first spell each turn"); - - static { - filter.add(TheLordOfPainPredicate.instance); - } - - public TheLordOfPainTriggeredAbility() { - super(new TheLordOfPainEffect(), filter, false, SetTargetPointer.PLAYER); - } - - protected TheLordOfPainTriggeredAbility(final TheLordOfPainTriggeredAbility ability) { - super(ability); - } +enum TheLordOfPainTargetAdjuster implements TargetAdjuster { + instance; @Override - public TheLordOfPainTriggeredAbility copy() { - return new TheLordOfPainTriggeredAbility(this); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (super.checkTrigger(event, game)) { - Player controller = game.getPlayer(getControllerId()); - Spell spell = (Spell)getEffects().get(0).getValue("spellCast"); - if (controller != null) { - FilterPlayer filter2 = new FilterPlayer("another target player"); - filter2.add(Predicates.not(new MageObjectReferencePredicate(spell.getControllerId(), game))); - TargetPlayer target = new TargetPlayer(1, 1, false, filter2); - controller.choose(Outcome.Damage, target, this, game); - getEffects().setTargetPointer(new FixedTarget(target.getFirstTarget())); - return true; - } - } - return false; + public void adjustTargets(Ability ability, Game game) { + UUID opponentId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability); + ability.getTargets().clear(); + ability.getAllEffects().setTargetPointer(new FirstTargetPointer()); + FilterPlayer filter = new FilterPlayer("another target player"); + filter.add(Predicates.not(new PlayerIdPredicate(opponentId))); + Target newTarget = new TargetPlayer(filter); + ability.addTarget(newTarget); } } -class TheLordOfPainEffect extends OneShotEffect { - - TheLordOfPainEffect() { - super(Outcome.Benefit); - staticText = "choose another target player. {this} deals damage equal to that spell's mana value to the chosen player"; - } - - private TheLordOfPainEffect(final TheLordOfPainEffect effect) { - super(effect); - } +enum TheLordOfPainValue implements DynamicValue { + instance; @Override - public TheLordOfPainEffect copy() { - return new TheLordOfPainEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Spell spell = (Spell)this.getValue("spellCast"); - if (spell != null) { - int cost = spell.getManaValue(); - Player target = game.getPlayer(getTargetPointer().getFirst(game, source)); - if (target != null) { - target.damage(cost, source.getSourceId(), source, game); - return true; - } + public int calculate(Game game, Ability sourceAbility, Effect effect) { + Object spell = effect.getValue("spellCast"); + if (spell instanceof Spell) { + return ((Spell) spell).getManaValue(); } - return false; } + return 0; + } + + @Override + public TheLordOfPainValue copy() { + return instance; + } + + @Override + public String getMessage() { + return "that spell's mana value"; + } } diff --git a/Mage.Sets/src/mage/cards/t/TheMyriadPools.java b/Mage.Sets/src/mage/cards/t/TheMyriadPools.java index 7d9e8b3e7f8..bcde9f4288f 100644 --- a/Mage.Sets/src/mage/cards/t/TheMyriadPools.java +++ b/Mage.Sets/src/mage/cards/t/TheMyriadPools.java @@ -1,38 +1,39 @@ package mage.cards.t; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.Effect; +import mage.abilities.common.CastSpellPaidBySourceTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CopyEffect; import mage.abilities.mana.BlueManaAbility; -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.SuperType; -import mage.constants.WatcherScope; -import mage.constants.Zone; +import mage.filter.FilterSpell; import mage.filter.StaticFilters; +import mage.filter.predicate.mageobject.PermanentPredicate; import mage.game.Game; -import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.permanent.PermanentCard; import mage.game.stack.Spell; import mage.players.Player; import mage.target.TargetPermanent; -import mage.target.targetpointer.FixedTarget; -import mage.watchers.Watcher; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public class TheMyriadPools extends CardImpl { + private static final FilterSpell filter = new FilterSpell("a permanent spell"); + + static { + filter.add(PermanentPredicate.instance); + } + public TheMyriadPools(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.LAND}, null); this.supertype.add(SuperType.LEGENDARY); @@ -41,11 +42,12 @@ public class TheMyriadPools extends CardImpl { this.nightCard = true; // {T}: Add {U}. - Ability ability = new BlueManaAbility(); - // Whenever you cast a permanent spell using mana produced by The Myriad Pools, up to one other target permanent you control becomes a copy of that spell until end of turn. - this.addAbility(ability, new TheMyriadPoolsWatcher(ability.getOriginalId().toString())); - this.addAbility(new TheMyriadPoolsTriggeredAbility()); + this.addAbility(new BlueManaAbility()); + // Whenever you cast a permanent spell using mana produced by The Myriad Pools, up to one other target permanent you control becomes a copy of that spell until end of turn. + Ability ability = new CastSpellPaidBySourceTriggeredAbility(new TheMyriadPoolsCopyEffect(), filter, false); + ability.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_CONTROLLED_ANOTHER_TARGET_PERMANENT)); + this.addAbility(ability); } private TheMyriadPools(final TheMyriadPools card) { @@ -58,90 +60,11 @@ public class TheMyriadPools extends CardImpl { } } -class TheMyriadPoolsWatcher extends Watcher { - - private UUID permanentId = UUID.randomUUID(); - private final String originalId; - - public TheMyriadPoolsWatcher(String originalId) { - super(WatcherScope.CARD); - this.originalId = originalId; - } - - public boolean manaUsedToCastPermanentPart(UUID id) { - return permanentId.equals(id); - } - - @Override - public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.MANA_PAID) { - if (event.getData() != null - && event.getData().equals(originalId)) { - Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell != null - && spell.isPermanent(game)) { - Card card = spell.getCard(); - permanentId = card.getId(); - } - } - } - } - - @Override - public void reset() { - super.reset(); - } -} - -class TheMyriadPoolsTriggeredAbility extends TriggeredAbilityImpl { - - public TheMyriadPoolsTriggeredAbility() { - super(Zone.BATTLEFIELD, new TheMyriadPoolsCopyEffect()); - } - - private TheMyriadPoolsTriggeredAbility(final TheMyriadPoolsTriggeredAbility ability) { - super(ability); - } - - @Override - public TheMyriadPoolsTriggeredAbility copy() { - return new TheMyriadPoolsTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.SPELL_CAST; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - TheMyriadPoolsWatcher watcher = game.getState().getWatcher(TheMyriadPoolsWatcher.class, this.getSourceId()); - if (watcher != null - && watcher.manaUsedToCastPermanentPart(event.getSourceId())) { - Spell spell = game.getSpell(event.getSourceId()); - if (spell != null - && spell.isControlledBy(getControllerId())) { - for (Effect effect : this.getEffects()) { - effect.setTargetPointer(new FixedTarget(event.getSourceId())); - } - return true; - } - } - return false; - } - - @Override - public String getRule() { - return "Whenever you cast a permanent spell using mana produced by {this}, up to one other target permanent you control becomes a copy of that spell until end of turn."; - } - -} - class TheMyriadPoolsCopyEffect extends OneShotEffect { TheMyriadPoolsCopyEffect() { super(Outcome.Neutral); - this.staticText = "copy of card on stack"; + this.staticText = "up to one other target permanent you control becomes a copy of that spell until end of turn"; } private TheMyriadPoolsCopyEffect(final TheMyriadPoolsCopyEffect effect) { @@ -155,28 +78,18 @@ class TheMyriadPoolsCopyEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent targetPermanentToCopyTo = null; + Permanent targetPermanentToCopyTo = game.getPermanent(getTargetPointer().getFirst(game, source)); Player controller = game.getPlayer(source.getControllerId()); - if (controller == null) { + Object spell = getValue("spellCast"); + if (controller == null || targetPermanentToCopyTo == null || !(spell instanceof Spell)) { return false; } - TargetPermanent target = new TargetPermanent(0, 1, StaticFilters.FILTER_CONTROLLED_ANOTHER_PERMANENT, false); - if (controller.choose(Outcome.Neutral, target, source, game)) { - targetPermanentToCopyTo = game.getPermanent(target.getFirstTarget()); - } - Card copyFromCardOnStack = game.getCard(getTargetPointer().getFirst(game, source)); - Permanent newBluePrint = null; - if (targetPermanentToCopyTo != null) { - if (copyFromCardOnStack != null) { - newBluePrint = new PermanentCard(copyFromCardOnStack, source.getControllerId(), game); - newBluePrint.assignNewId(); - CopyEffect copyEffect = new CopyEffect(Duration.EndOfTurn, newBluePrint, targetPermanentToCopyTo.getId()); - Ability newAbility = source.copy(); - copyEffect.init(newAbility, game); - game.addEffect(copyEffect, newAbility); - } - return true; - } - return false; + Permanent newBluePrint = new PermanentCard(((Spell)spell).getCard(), source.getControllerId(), game); + newBluePrint.assignNewId(); + CopyEffect copyEffect = new CopyEffect(Duration.EndOfTurn, newBluePrint, targetPermanentToCopyTo.getId()); + Ability newAbility = source.copy(); + copyEffect.init(newAbility, game); + game.addEffect(copyEffect, newAbility); + return true; } } diff --git a/Mage.Sets/src/mage/cards/t/TheNinthDoctor.java b/Mage.Sets/src/mage/cards/t/TheNinthDoctor.java index 9b791bfdeb7..eaa7ab95595 100644 --- a/Mage.Sets/src/mage/cards/t/TheNinthDoctor.java +++ b/Mage.Sets/src/mage/cards/t/TheNinthDoctor.java @@ -2,14 +2,16 @@ package mage.cards.t; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.condition.Condition; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.InspiredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -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.turn.TurnMod; import mage.game.turn.UpkeepStep; @@ -21,8 +23,6 @@ import java.util.UUID; */ public final class TheNinthDoctor extends CardImpl { - private static final Condition condition = new IsStepCondition(PhaseStep.UNTAP); - public TheNinthDoctor(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{R}"); this.supertype.add(SuperType.LEGENDARY); @@ -35,7 +35,7 @@ public final class TheNinthDoctor extends CardImpl { // Into the TARDIS — Whenever The Ninth Doctor becomes untapped during your untap step, you get an additional upkeep step after this step. this.addAbility(new InspiredAbility(new TheNinthDoctorEffect(), false, false) - .withTriggerCondition(condition) + .withTriggerCondition(IsStepCondition.getMyUpkeep()) .withFlavorWord("Into the TARDIS")); } diff --git a/Mage.Sets/src/mage/cards/t/TheOneRing.java b/Mage.Sets/src/mage/cards/t/TheOneRing.java index d587e77731a..3f002df56fc 100644 --- a/Mage.Sets/src/mage/cards/t/TheOneRing.java +++ b/Mage.Sets/src/mage/cards/t/TheOneRing.java @@ -1,12 +1,10 @@ package mage.cards.t; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.CastFromEverywhereSourceCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.DrawCardSourceControllerEffect; @@ -15,6 +13,7 @@ import mage.abilities.effects.common.continuous.GainAbilityControllerEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.IndestructibleAbility; import mage.abilities.keyword.ProtectionFromEverythingAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -40,17 +39,12 @@ public final class TheOneRing extends CardImpl { this.addAbility(IndestructibleAbility.getInstance()); // When The One Ring enters the battlefield, if you cast it, you gain protection from everything until your next turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new GainAbilityControllerEffect( - new ProtectionFromEverythingAbility(), Duration.UntilYourNextTurn - )), CastFromEverywhereSourceCondition.instance, "When {this} enters, " + - "if you cast it, you gain protection from everything until your next turn." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new GainAbilityControllerEffect(new ProtectionFromEverythingAbility(), Duration.UntilYourNextTurn) + ).withInterveningIf(CastFromEverywhereSourceCondition.instance)); // At the beginning of your upkeep, you lose 1 life for each burden counter on The One Ring. - this.addAbility(new BeginningOfUpkeepTriggeredAbility( - new LoseLifeSourceControllerEffect(xValue) - )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new LoseLifeSourceControllerEffect(xValue))); // {T}: Put a burden counter on The One Ring, then draw a card for each burden counter on The One Ring. Ability ability = new SimpleActivatedAbility( diff --git a/Mage.Sets/src/mage/cards/t/TheOzolith.java b/Mage.Sets/src/mage/cards/t/TheOzolith.java index 54fece77667..5e2df719542 100644 --- a/Mage.Sets/src/mage/cards/t/TheOzolith.java +++ b/Mage.Sets/src/mage/cards/t/TheOzolith.java @@ -1,11 +1,10 @@ package mage.cards.t; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.common.LeavesBattlefieldAllTriggeredAbility; import mage.abilities.condition.common.SourceHasCountersCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -36,12 +35,9 @@ public final class TheOzolith extends CardImpl { this.addAbility(new TheOzolithTriggeredAbility()); // At the beginning of combat on your turn, if The Ozolith has counters on it, you may move all counters from The Ozolith onto target creature. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility( - new TheOzolithMoveCountersEffect(), true - ), SourceHasCountersCondition.instance, "At the beginning of combat on your turn, " + - "if {this} has counters on it, you may move all counters from {this} onto target creature." - ); + Ability ability = new BeginningOfCombatTriggeredAbility( + new TheOzolithMoveCountersEffect(), true + ).withInterveningIf(SourceHasCountersCondition.instance); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } @@ -126,6 +122,7 @@ class TheOzolithMoveCountersEffect extends OneShotEffect { TheOzolithMoveCountersEffect() { super(Outcome.Benefit); + staticText = "you may move all counters from {this} onto target creature"; } private TheOzolithMoveCountersEffect(final TheOzolithMoveCountersEffect effect) { diff --git a/Mage.Sets/src/mage/cards/t/ThePrydwenSteelFlagship.java b/Mage.Sets/src/mage/cards/t/ThePrydwenSteelFlagship.java index 153f2d8d125..f800f0fbea7 100644 --- a/Mage.Sets/src/mage/cards/t/ThePrydwenSteelFlagship.java +++ b/Mage.Sets/src/mage/cards/t/ThePrydwenSteelFlagship.java @@ -1,29 +1,30 @@ package mage.cards.t; -import java.util.UUID; - import mage.MageInt; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; -import mage.constants.SubType; -import mage.constants.SuperType; -import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.CrewAbility; +import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.common.FilterArtifactPermanent; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledArtifactPermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.permanent.TokenPredicate; import mage.game.permanent.token.ThePrydwenSteelFlagshipHumanKnightToken; import mage.watchers.common.ArtifactEnteredControllerWatcher; +import java.util.UUID; + /** * @author Cguy7777 */ public final class ThePrydwenSteelFlagship extends CardImpl { - private static final FilterArtifactPermanent filter = new FilterArtifactPermanent("another nontoken artifact"); + private static final FilterPermanent filter = new FilterControlledArtifactPermanent("another nontoken artifact you control"); static { filter.add(AnotherPredicate.instance); @@ -44,14 +45,12 @@ public final class ThePrydwenSteelFlagship extends CardImpl { // Whenever another nontoken artifact you control enters, // create a 2/2 white Human Knight creature token with // "This creature gets +2/+2 as long as an artifact entered the battlefield under your control this turn." - this.addAbility( - new EntersBattlefieldControlledTriggeredAbility( - new CreateTokenEffect(new ThePrydwenSteelFlagshipHumanKnightToken()), filter), - new ArtifactEnteredControllerWatcher()); + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + new CreateTokenEffect(new ThePrydwenSteelFlagshipHumanKnightToken()), filter + ), new ArtifactEnteredControllerWatcher()); // Crew 2 this.addAbility(new CrewAbility(2)); - } private ThePrydwenSteelFlagship(final ThePrydwenSteelFlagship card) { diff --git a/Mage.Sets/src/mage/cards/t/TheRani.java b/Mage.Sets/src/mage/cards/t/TheRani.java index ee7a0524a4d..0b8a8845d3f 100644 --- a/Mage.Sets/src/mage/cards/t/TheRani.java +++ b/Mage.Sets/src/mage/cards/t/TheRani.java @@ -14,10 +14,13 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.GoadedPredicate; import mage.game.Game; import mage.game.permanent.token.MarkOfTheRaniToken; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_ANOTHER_CREATURE; + /** * * @author grimreap124 @@ -42,7 +45,7 @@ public final class TheRani extends CardImpl { // Whenever The Rani enters the battlefield or attacks, create a red Aura enchantment token named Mark of the Rani attached to another target creature. That token has enchant creature and "Enchanted creature gets +2/+2 and is goaded." Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility( new TheRaniEffect()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_CREATURE)); this.addAbility(ability); // Whenever a goaded creature deals combat damage to one of your opponents, investigate. diff --git a/Mage.Sets/src/mage/cards/t/TheRevelationsOfEzio.java b/Mage.Sets/src/mage/cards/t/TheRevelationsOfEzio.java index cc52367e98d..8be85eeb84c 100644 --- a/Mage.Sets/src/mage/cards/t/TheRevelationsOfEzio.java +++ b/Mage.Sets/src/mage/cards/t/TheRevelationsOfEzio.java @@ -21,6 +21,7 @@ import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; @@ -52,7 +53,7 @@ public final class TheRevelationsOfEzio extends CardImpl { this, SagaChapter.CHAPTER_I, SagaChapter.CHAPTER_I, ability -> { ability.addEffect(new DestroyTargetEffect()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); } ); // II -- Whenever an Assassin you control attacks this turn, put a +1/+1 counter on it. diff --git a/Mage.Sets/src/mage/cards/t/TheScorpionGod.java b/Mage.Sets/src/mage/cards/t/TheScorpionGod.java index 8a03884f9e0..67ecd405fac 100644 --- a/Mage.Sets/src/mage/cards/t/TheScorpionGod.java +++ b/Mage.Sets/src/mage/cards/t/TheScorpionGod.java @@ -29,9 +29,12 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * * @author spjspj @@ -51,7 +54,7 @@ public final class TheScorpionGod extends CardImpl { // {1}{B}{R}: Put a -1/-1 counter on another target creature. Ability ability = new SimpleActivatedAbility(new AddCountersTargetEffect(CounterType.M1M1.createInstance()), new ManaCostsImpl<>("{1}{B}{R}")); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); // When The Scorpion God dies, return it to its owner's hand at the beginning of the next end step. diff --git a/Mage.Sets/src/mage/cards/t/TheSeaDevils.java b/Mage.Sets/src/mage/cards/t/TheSeaDevils.java index 09a21f3471d..213074a76eb 100644 --- a/Mage.Sets/src/mage/cards/t/TheSeaDevils.java +++ b/Mage.Sets/src/mage/cards/t/TheSeaDevils.java @@ -21,6 +21,7 @@ import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.permanent.token.AlienSalamanderToken; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; import mage.util.GameLog; @@ -106,7 +107,7 @@ class TheSeaDevilsTrigger extends DelayedTriggeredAbility { this.getTargets().clear(); FilterCreaturePermanent filterTarget = new FilterCreaturePermanent("creature " + player.getName() + " controls"); filterTarget.add(new ControllerIdPredicate(player.getId())); - this.addTarget(new TargetCreaturePermanent(filterTarget)); + this.addTarget(new TargetPermanent(filterTarget)); int amount = event.getAmount(); @@ -175,4 +176,4 @@ class TheSeaDevilsEffect extends OneShotEffect { target.damage(amount, salamander.getId(), source, game); return true; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/t/TheSeedcore.java b/Mage.Sets/src/mage/cards/t/TheSeedcore.java index 3f84b2fb9a2..de8b134f54c 100644 --- a/Mage.Sets/src/mage/cards/t/TheSeedcore.java +++ b/Mage.Sets/src/mage/cards/t/TheSeedcore.java @@ -7,7 +7,7 @@ import mage.abilities.Ability; import mage.abilities.condition.common.CorruptedCondition; import mage.abilities.costs.Cost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.mana.ColorlessManaAbility; import mage.abilities.mana.ConditionalAnyColorManaAbility; @@ -20,6 +20,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; import mage.filter.predicate.mageobject.ToughnessPredicate; import mage.game.Game; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -43,16 +44,16 @@ public final class TheSeedcore extends CardImpl { // {T}: Add {C}. this.addAbility(new ColorlessManaAbility()); + // {T}: Add one mana of any color. Spend this mana only to cast Phyrexian creature spells. this.addAbility(new ConditionalAnyColorManaAbility(new TapSourceCost(), 1, new TheSeedcoreManaBuilder(), true)); + // Corrupted -- {T}: Target 1/1 creature gets +2/+1 until end of turn. Activate only if an opponent has three or more poison counters. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, + Ability ability = new ActivateIfConditionActivatedAbility( new BoostTargetEffect(2, 1, Duration.EndOfTurn), - new TapSourceCost(), - CorruptedCondition.instance + new TapSourceCost(), CorruptedCondition.instance ).setAbilityWord(AbilityWord.CORRUPTED).addHint(CorruptedCondition.getHint()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } @@ -103,4 +104,3 @@ class TheSeedcoreManaCondition extends CreatureCastManaCondition { return false; } } - diff --git a/Mage.Sets/src/mage/cards/t/TheTricksterGodsHeist.java b/Mage.Sets/src/mage/cards/t/TheTricksterGodsHeist.java index 6edf1d308f4..a4eb35e9231 100644 --- a/Mage.Sets/src/mage/cards/t/TheTricksterGodsHeist.java +++ b/Mage.Sets/src/mage/cards/t/TheTricksterGodsHeist.java @@ -22,6 +22,9 @@ import java.util.HashSet; import java.util.Set; import java.util.UUID; +import static mage.constants.Duration.EndOfGame; +import static mage.constants.SagaChapter.CHAPTER_I; + /** * @author TheElk801 */ @@ -37,9 +40,9 @@ public final class TheTricksterGodsHeist extends CardImpl { // I — You may exchange control of two target creatures. sagaAbility.addChapterEffect( - this, SagaChapter.CHAPTER_I, SagaChapter.CHAPTER_I, + this, CHAPTER_I, CHAPTER_I, new ExchangeControlTargetEffect( - Duration.EndOfGame, "exchange control of two target creatures" + EndOfGame, "exchange control of two target creatures" ), new TargetCreaturePermanent(2), true ); diff --git a/Mage.Sets/src/mage/cards/t/TheWanderingEmperor.java b/Mage.Sets/src/mage/cards/t/TheWanderingEmperor.java index c2b5457b276..94d5bdbeb56 100644 --- a/Mage.Sets/src/mage/cards/t/TheWanderingEmperor.java +++ b/Mage.Sets/src/mage/cards/t/TheWanderingEmperor.java @@ -83,7 +83,7 @@ class TheWanderingEmperorEffect extends AsThoughEffectImpl { TheWanderingEmperorEffect() { super(AsThoughEffectType.ACTIVATE_AS_INSTANT, Duration.WhileOnBattlefield, Outcome.Benefit); - staticText = "as long as {this} entered the battlefield this turn, " + + staticText = "as long as {this} entered this turn, " + "you may activate her loyalty abilities any time you could cast an instant"; } diff --git a/Mage.Sets/src/mage/cards/t/ThelonsCurse.java b/Mage.Sets/src/mage/cards/t/ThelonsCurse.java index f53d5f38a40..a1301f9215d 100644 --- a/Mage.Sets/src/mage/cards/t/ThelonsCurse.java +++ b/Mage.Sets/src/mage/cards/t/ThelonsCurse.java @@ -1,14 +1,13 @@ package mage.cards.t; -import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.Cost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DontUntapInControllersUntapStepAllEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -23,10 +22,11 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author spjspj & L_J */ public final class ThelonsCurse extends CardImpl { @@ -85,22 +85,23 @@ class ThelonsCurseEffect extends OneShotEffect { Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - if (player != null && sourcePermanent != null) { - int countBattlefield = game.getBattlefield().getAllActivePermanents(filter, game.getActivePlayerId(), game).size(); - while (player.canRespond() && countBattlefield > 0 && player.chooseUse(Outcome.AIDontUseIt, "Pay {U} and untap a tapped blue creature under your control?", source, game)) { - Target tappedCreatureTarget = new TargetControlledCreaturePermanent(1, 1, filter, true); - if (player.choose(Outcome.Detriment, tappedCreatureTarget, source, game)) { - Cost cost = new ManaCostsImpl<>("{U}"); - Permanent tappedCreature = game.getPermanent(tappedCreatureTarget.getFirstTarget()); - - if (cost.pay(source, game, source, player.getId(), false)) { - tappedCreature.untap(game); - } - } - countBattlefield = game.getBattlefield().getAllActivePermanents(filter, game.getActivePlayerId(), game).size(); - } - return true; + if (player == null || sourcePermanent == null) { + return false; } - return false; + int countBattlefield = game.getBattlefield().getAllActivePermanents(filter, game.getActivePlayerId(), game).size(); + while (player.canRespond() && countBattlefield > 0 && player.chooseUse(Outcome.AIDontUseIt, "Pay {U} and untap a tapped blue creature under your control?", source, game)) { + Target tappedCreatureTarget = new TargetPermanent(filter); + tappedCreatureTarget.withNotTarget(true); + if (player.choose(Outcome.Detriment, tappedCreatureTarget, source, game)) { + Cost cost = new ManaCostsImpl<>("{U}"); + Permanent tappedCreature = game.getPermanent(tappedCreatureTarget.getFirstTarget()); + + if (cost.pay(source, game, source, player.getId(), false)) { + tappedCreature.untap(game); + } + } + countBattlefield = game.getBattlefield().getAllActivePermanents(filter, game.getActivePlayerId(), game).size(); + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/t/ThermalDetonator.java b/Mage.Sets/src/mage/cards/t/ThermalDetonator.java index c10c5f6c530..780c65c7051 100644 --- a/Mage.Sets/src/mage/cards/t/ThermalDetonator.java +++ b/Mage.Sets/src/mage/cards/t/ThermalDetonator.java @@ -12,7 +12,7 @@ import mage.constants.CardType; import mage.filter.common.FilterCreatureOrPlayer; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; -import mage.target.common.TargetCreatureOrPlayer; +import mage.target.common.TargetPermanentOrPlayer; import java.util.UUID; @@ -33,7 +33,7 @@ public final class ThermalDetonator extends CardImpl { // {2}, Sacrifice Thermal Detonator: Thermal Detonator deals 2 damage to target creature without spaceflight or target player. Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(2), new ManaCostsImpl<>("{2}")); ability.addCost(new SacrificeSourceCost()); - ability.addTarget(new TargetCreatureOrPlayer(filter)); + ability.addTarget(new TargetPermanentOrPlayer(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/ThicketElemental.java b/Mage.Sets/src/mage/cards/t/ThicketElemental.java index f5e666398a6..87666a32b10 100644 --- a/Mage.Sets/src/mage/cards/t/ThicketElemental.java +++ b/Mage.Sets/src/mage/cards/t/ThicketElemental.java @@ -3,7 +3,6 @@ package mage.cards.t; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.RevealCardsFromLibraryUntilEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -30,13 +29,11 @@ public final class ThicketElemental extends CardImpl { this.addAbility(new KickerAbility("{1}{G}")); // When Thicket Elemental enters the battlefield, if it was kicked, you may reveal cards from the top of your library until you reveal a creature card. If you do, put that card onto the battlefield and shuffle all other cards revealed this way into your library. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new RevealCardsFromLibraryUntilEffect( - StaticFilters.FILTER_CARD_CREATURE, PutCards.BATTLEFIELD, PutCards.SHUFFLE - )), KickedCondition.ONCE, "When {this} enters, if it was kicked, " + - "you may reveal cards from the top of your library until you reveal a creature card. If you do, " + - "put that card onto the battlefield and shuffle all other cards revealed this way into your library." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new RevealCardsFromLibraryUntilEffect( + StaticFilters.FILTER_CARD_CREATURE, PutCards.BATTLEFIELD, PutCards.SHUFFLE + ).setText("reveal cards from the top of your library until you reveal a creature card. If you do, " + + "put that card onto the battlefield and shuffle all other cards revealed this way into your library"), true + ).withInterveningIf(KickedCondition.ONCE)); } private ThicketElemental(final ThicketElemental card) { diff --git a/Mage.Sets/src/mage/cards/t/ThievingSkydiver.java b/Mage.Sets/src/mage/cards/t/ThievingSkydiver.java index aa40f5be1ca..6ff74d9076a 100644 --- a/Mage.Sets/src/mage/cards/t/ThievingSkydiver.java +++ b/Mage.Sets/src/mage/cards/t/ThievingSkydiver.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.abilities.keyword.FlyingAbility; @@ -44,12 +43,8 @@ public final class ThievingSkydiver extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When Thieving Skydiver enters the battlefield, if it was kicked, gain control of target artifact with converted mana cost X or less. If that artifact is an Equipment, attach it to Thieving Skydiver. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new GainControlTargetEffect(Duration.Custom), false), - KickedCondition.ONCE, "When {this} enters, if it was kicked, " + - "gain control of target artifact with mana value X or less. " + - "If that artifact is an Equipment, attach it to {this}." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new GainControlTargetEffect(Duration.Custom) + .setText("gain control of target artifact with mana value X or less")).withInterveningIf(KickedCondition.ONCE); ability.addEffect(new ThievingSkydiverEffect()); ability.addTarget(new TargetArtifactPermanent()); ability.setTargetAdjuster(new XManaValueTargetAdjuster(ComparisonType.OR_LESS)); @@ -70,6 +65,7 @@ class ThievingSkydiverEffect extends OneShotEffect { ThievingSkydiverEffect() { super(Outcome.Benefit); + staticText = "If that artifact is an Equipment, attach it to {this}"; } private ThievingSkydiverEffect(final ThievingSkydiverEffect effect) { @@ -84,11 +80,8 @@ class ThievingSkydiverEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent permanent = source.getSourcePermanentIfItStillExists(game); - Permanent artifact = game.getPermanent(source.getFirstTarget()); - if (permanent == null - || artifact == null - || !artifact.isArtifact(game) - || !artifact.hasSubtype(SubType.EQUIPMENT, game)) { + Permanent artifact = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (permanent == null || artifact == null || !artifact.hasSubtype(SubType.EQUIPMENT, game)) { return false; } game.processAction(); diff --git a/Mage.Sets/src/mage/cards/t/ThirstingAxe.java b/Mage.Sets/src/mage/cards/t/ThirstingAxe.java index bd7e6e56dad..04d3e254892 100644 --- a/Mage.Sets/src/mage/cards/t/ThirstingAxe.java +++ b/Mage.Sets/src/mage/cards/t/ThirstingAxe.java @@ -1,23 +1,18 @@ - package mage.cards.t; import mage.MageObjectReference; import mage.abilities.Ability; -import mage.abilities.TriggeredAbility; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.condition.CompoundCondition; import mage.abilities.condition.Condition; -import mage.abilities.condition.InvertCondition; -import mage.abilities.condition.common.AttachedCondition; -import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SacrificeEquippedEffect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.keyword.EquipAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.WatcherScope; import mage.game.Game; import mage.game.events.DamagedEvent; import mage.game.events.GameEvent; @@ -25,10 +20,9 @@ import mage.game.permanent.Permanent; import mage.watchers.Watcher; import java.util.HashSet; +import java.util.Optional; import java.util.Set; import java.util.UUID; -import mage.target.common.TargetControlledCreaturePermanent; - /** * @author Quercitron @@ -43,17 +37,12 @@ public final class ThirstingAxe extends CardImpl { this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(4, 0))); // At the beginning of your end step, if equipped creature didn't deal combat damage to a creature this turn, sacrifice it. - TriggeredAbility ability = new BeginningOfEndStepTriggeredAbility(new SacrificeEquippedEffect()); - Condition condition = new CompoundCondition( - AttachedCondition.instance, - new InvertCondition(new EquippedDealtCombatDamageToCreatureCondition())); - String triggeredAbilityText = "At the beginning of your end step, if equipped creature " + - "didn't deal combat damage to a creature this turn, sacrifice it."; - ConditionalInterveningIfTriggeredAbility sacrificeTriggeredAbility = new ConditionalInterveningIfTriggeredAbility(ability, condition, triggeredAbilityText); - this.addAbility(sacrificeTriggeredAbility, new CombatDamageToCreatureWatcher()); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + new SacrificeEquippedEffect().setText("sacrifice it") + ).withInterveningIf(ThirstingAxeCondition.instance), new ThirstingAxeWatcher()); // Equip {2} - this.addAbility(new EquipAbility(Outcome.BoostCreature, new GenericManaCost(2), new TargetControlledCreaturePermanent(), false)); + this.addAbility(new EquipAbility(2)); } private ThirstingAxe(final ThirstingAxe card) { @@ -66,43 +55,42 @@ public final class ThirstingAxe extends CardImpl { } } -class EquippedDealtCombatDamageToCreatureCondition implements Condition { +enum ThirstingAxeCondition implements Condition { + instance; @Override public boolean apply(Game game, Ability source) { - Permanent equipment = game.getPermanent(source.getSourceId()); - if (equipment != null && equipment.getAttachedTo() != null) { - CombatDamageToCreatureWatcher watcher = - game.getState().getWatcher(CombatDamageToCreatureWatcher.class); - return watcher != null && watcher.dealtDamage(equipment.getAttachedTo(), equipment.getAttachedToZoneChangeCounter(), game); - } - return false; + return Optional + .ofNullable(source.getSourcePermanentOrLKI(game)) + .map(Permanent::getAttachedTo) + .filter(uuid -> ThirstingAxeWatcher.checkCreature(uuid, game)) + .isPresent(); } + @Override + public String toString() { + return "equipped creature didn't deal combat damage to a creature this turn"; + } } -class CombatDamageToCreatureWatcher extends Watcher { +class ThirstingAxeWatcher extends Watcher { // which objects dealt combat damage to creature during the turn - private final Set dealtCombatDamageToCreature; + private final Set dealtCombatDamageToCreature = new HashSet<>(); - public CombatDamageToCreatureWatcher() { + public ThirstingAxeWatcher() { super(WatcherScope.GAME); - dealtCombatDamageToCreature = new HashSet<>(); } @Override public void watch(GameEvent event, Game game) { - if (event.getType() != GameEvent.EventType.DAMAGED_PERMANENT - || !((DamagedEvent) event).isCombatDamage()) { + if (event.getType() != GameEvent.EventType.DAMAGED_PERMANENT || !((DamagedEvent) event).isCombatDamage()) { return; } Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent == null || !permanent.isCreature(game)) { - return; + if (permanent != null && permanent.isCreature(game)) { + dealtCombatDamageToCreature.add(new MageObjectReference(event.getSourceId(), game)); } - MageObjectReference damageSource = new MageObjectReference(event.getSourceId(), game); - dealtCombatDamageToCreature.add(damageSource); } @Override @@ -111,9 +99,12 @@ class CombatDamageToCreatureWatcher extends Watcher { dealtCombatDamageToCreature.clear(); } - public boolean dealtDamage(UUID objectId, int zoneChangeCounter, Game game) { - MageObjectReference reference = new MageObjectReference(objectId, zoneChangeCounter, game); - return dealtCombatDamageToCreature.contains(reference); + static boolean checkCreature(UUID permanentId, Game game) { + return game + .getState() + .getWatcher(ThirstingAxeWatcher.class) + .dealtCombatDamageToCreature + .stream() + .anyMatch(mor -> mor.refersTo(permanentId, game)); } - } diff --git a/Mage.Sets/src/mage/cards/t/ThisIsHowItEnds.java b/Mage.Sets/src/mage/cards/t/ThisIsHowItEnds.java index 15b6ed745aa..b9aaf454eed 100644 --- a/Mage.Sets/src/mage/cards/t/ThisIsHowItEnds.java +++ b/Mage.Sets/src/mage/cards/t/ThisIsHowItEnds.java @@ -1,36 +1,40 @@ package mage.cards.t; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ShuffleIntoLibraryTargetEffect; -import mage.cards.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; import mage.choices.FaceVillainousChoice; import mage.choices.VillainousChoice; -import mage.constants.*; -import mage.game.Game; -import mage.filter.StaticFilters; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * - * @author padfoothelix + * @author padfoothelix */ public final class ThisIsHowItEnds extends CardImpl { public ThisIsHowItEnds(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{B}"); - - // Target creature's owner shuffles it into their library, then faces a villainous choice -- They lose 5 life, or they shuffle another creature they own into their library. - this.getSpellAbility().addEffect( - new ShuffleIntoLibraryTargetEffect() - .setText("target creature's owner shuffles it into their library,") - ); - this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - this.getSpellAbility().addEffect(new ThisIsHowItEndsEffect()); + // Target creature's owner shuffles it into their library, then faces a villainous choice -- They lose 5 life, or they shuffle another creature they own into their library. + this.getSpellAbility().addEffect( + new ShuffleIntoLibraryTargetEffect() + .setText("target creature's owner shuffles it into their library,") + ); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addEffect(new ThisIsHowItEndsEffect()); } private ThisIsHowItEnds(final ThisIsHowItEnds card) { @@ -46,26 +50,26 @@ public final class ThisIsHowItEnds extends CardImpl { class ThisIsHowItEndsEffect extends OneShotEffect { private static final FaceVillainousChoice choice = new FaceVillainousChoice( - Outcome.Removal, new ThisIsHowItEndsFirstChoice(), new ThisIsHowItEndsSecondChoice() - ); + Outcome.Removal, new ThisIsHowItEndsFirstChoice(), new ThisIsHowItEndsSecondChoice() + ); ThisIsHowItEndsEffect() { - super(Outcome.Benefit); - staticText = "then " + choice.generateRule(); + super(Outcome.Benefit); + staticText = "then " + choice.generateRule(); } private ThisIsHowItEndsEffect(final ThisIsHowItEndsEffect effect) { - super(effect); + super(effect); } @Override public ThisIsHowItEndsEffect copy() { - return new ThisIsHowItEndsEffect(this); + return new ThisIsHowItEndsEffect(this); } @Override public boolean apply(Game game, Ability source) { - UUID targetOwnerId = game.getOwnerId(getTargetPointer().getFirst(game, source)); + UUID targetOwnerId = game.getOwnerId(getTargetPointer().getFirst(game, source)); Player targetOwner = game.getPlayer(targetOwnerId); choice.faceChoice(targetOwner, game, source); return true; @@ -74,13 +78,13 @@ class ThisIsHowItEndsEffect extends OneShotEffect { class ThisIsHowItEndsFirstChoice extends VillainousChoice { ThisIsHowItEndsFirstChoice() { - super("They lose 5 life","You lose 5 life"); + super("They lose 5 life", "You lose 5 life"); } @Override public boolean doChoice(Player player, Game game, Ability source) { player.loseLife(5, game, source, false); - return true; + return true; } } @@ -89,7 +93,7 @@ class ThisIsHowItEndsSecondChoice extends VillainousChoice { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you own"); static { - filter.add(TargetController.YOU.getOwnerPredicate()); + filter.add(TargetController.YOU.getOwnerPredicate()); } ThisIsHowItEndsSecondChoice() { @@ -98,11 +102,12 @@ class ThisIsHowItEndsSecondChoice extends VillainousChoice { @Override public boolean doChoice(Player player, Game game, Ability source) { - TargetCreaturePermanent target = new TargetCreaturePermanent(1, 1, filter, true); - target.withChooseHint("to shuffle into your library"); + TargetPermanent target = new TargetPermanent(filter); + target.withNotTarget(true); + target.withChooseHint("to shuffle into your library"); player.chooseTarget(Outcome.Detriment, target, source, game); - Cards cards = new CardsImpl(target.getTargets()); - player.shuffleCardsToLibrary(cards, game, source); - return true; + Cards cards = new CardsImpl(target.getTargets()); + player.shuffleCardsToLibrary(cards, game, source); + return true; } } diff --git a/Mage.Sets/src/mage/cards/t/ThopterAssembly.java b/Mage.Sets/src/mage/cards/t/ThopterAssembly.java index 19c2a15cc72..f1161f4ab40 100644 --- a/Mage.Sets/src/mage/cards/t/ThopterAssembly.java +++ b/Mage.Sets/src/mage/cards/t/ThopterAssembly.java @@ -2,13 +2,12 @@ package mage.cards.t; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.ReturnToHandSourceEffect; import mage.abilities.keyword.FlyingAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -25,7 +24,7 @@ import java.util.UUID; */ public final class ThopterAssembly extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent(SubType.THOPTER, ""); + private static final FilterPermanent filter = new FilterPermanent(SubType.THOPTER, "you control no Thopters other than {this}"); static { filter.add(AnotherPredicate.instance); @@ -44,15 +43,8 @@ public final class ThopterAssembly extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // At the beginning of your upkeep, if you control no Thopters other than Thopter Assembly, return Thopter Assembly to its owner's hand and create five 1/1 colorless Thopter artifact creature tokens with flying. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility( - new ReturnToHandSourceEffect(true), false - ), condition, "At the beginning of your upkeep, " + - "if you control no Thopters other than {this}, " + - "return {this} to its owner's hand and create five 1/1 colorless " + - "Thopter artifact creature tokens with flying." - ); - ability.addEffect(new CreateTokenEffect(new ThopterColorlessToken(), 5)); + Ability ability = new BeginningOfUpkeepTriggeredAbility(new ReturnToHandSourceEffect(true)).withInterveningIf(condition); + ability.addEffect(new CreateTokenEffect(new ThopterColorlessToken(), 5).concatBy("and")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/ThornscapeBattlemage.java b/Mage.Sets/src/mage/cards/t/ThornscapeBattlemage.java index ecedd0964c9..05b2edec148 100644 --- a/Mage.Sets/src/mage/cards/t/ThornscapeBattlemage.java +++ b/Mage.Sets/src/mage/cards/t/ThornscapeBattlemage.java @@ -1,12 +1,10 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.KickedCostCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.KickerAbility; @@ -14,17 +12,21 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.target.common.TargetArtifactPermanent; import mage.target.common.TargetAnyTarget; +import mage.target.common.TargetArtifactPermanent; + +import java.util.UUID; /** - * * @author FenrisulfrX */ public final class ThornscapeBattlemage extends CardImpl { + private static final Condition condition = new KickedCostCondition("{R}"); + private static final Condition condition2 = new KickedCostCondition("{W}"); + public ThornscapeBattlemage(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); this.subtype.add(SubType.ELF); this.subtype.add(SubType.WIZARD); this.power = new MageInt(2); @@ -36,16 +38,16 @@ public final class ThornscapeBattlemage extends CardImpl { this.addAbility(kickerAbility); // When {this} enters, if it was kicked with its {R} kicker, it deals 2 damage to any target. - TriggeredAbility ability1 = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2, "it")); - ability1.addTarget(new TargetAnyTarget()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability1, new KickedCostCondition("{R}"), - "When {this} enters, if it was kicked with its {R} kicker, it deals 2 damage to any target.")); + Ability ability = new EntersBattlefieldTriggeredAbility( + new DamageTargetEffect(2, "it") + ).withInterveningIf(condition); + ability.addTarget(new TargetAnyTarget()); + this.addAbility(ability); // When {this} enters, if it was kicked with its {W} kicker, destroy target artifact. - TriggeredAbility ability2 = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()); - ability2.addTarget(new TargetArtifactPermanent()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability2, new KickedCostCondition("{W}"), - "When {this} enters, if it was kicked with its {W} kicker, destroy target artifact.")); + ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()).withInterveningIf(condition2); + ability.addTarget(new TargetArtifactPermanent()); + this.addAbility(ability); } private ThornscapeBattlemage(final ThornscapeBattlemage card) { diff --git a/Mage.Sets/src/mage/cards/t/ThoughtShucker.java b/Mage.Sets/src/mage/cards/t/ThoughtShucker.java index d5d62db6815..8a0641698dd 100644 --- a/Mage.Sets/src/mage/cards/t/ThoughtShucker.java +++ b/Mage.Sets/src/mage/cards/t/ThoughtShucker.java @@ -1,9 +1,9 @@ package mage.cards.t; import mage.MageInt; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.common.ThresholdCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; @@ -42,7 +42,7 @@ public final class ThoughtShucker extends CardImpl { } } -class ThoughtShuckerActivatedAbility extends ConditionalActivatedAbility { +class ThoughtShuckerActivatedAbility extends ActivateIfConditionActivatedAbility { ThoughtShuckerActivatedAbility() { super(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), new ManaCostsImpl<>("{1}{U}"), ThresholdCondition.instance); @@ -66,4 +66,4 @@ class ThoughtShuckerActivatedAbility extends ConditionalActivatedAbility { int len = rule.length(); return rule.substring(0, len - 1) + " and only once."; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/t/ThoughtboundPrimoc.java b/Mage.Sets/src/mage/cards/t/ThoughtboundPrimoc.java index f61dfdb8d02..c248535cb94 100644 --- a/Mage.Sets/src/mage/cards/t/ThoughtboundPrimoc.java +++ b/Mage.Sets/src/mage/cards/t/ThoughtboundPrimoc.java @@ -1,26 +1,28 @@ package mage.cards.t; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.abilities.keyword.FlyingAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author awjackson */ public final class ThoughtboundPrimoc extends CardImpl { @@ -37,12 +39,8 @@ public final class ThoughtboundPrimoc extends CardImpl { // At the beginning of your upkeep, if a player controls more Wizards than each other player, // the player who controls the most Wizards gains control of Thoughtbound Primoc. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new ThoughtboundPrimocEffect()), - OnePlayerHasTheMostWizards.instance, - "At the beginning of your upkeep, if a player controls more Wizards than each other player, the player who controls the most Wizards gains control of {this}" - )); - + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new ThoughtboundPrimocEffect()) + .withInterveningIf(OnePlayerHasTheMostWizards.instance)); } private ThoughtboundPrimoc(final ThoughtboundPrimoc card) { diff --git a/Mage.Sets/src/mage/cards/t/ThousandFacedShadow.java b/Mage.Sets/src/mage/cards/t/ThousandFacedShadow.java index e3d302ad786..275d60f349c 100644 --- a/Mage.Sets/src/mage/cards/t/ThousandFacedShadow.java +++ b/Mage.Sets/src/mage/cards/t/ThousandFacedShadow.java @@ -101,6 +101,6 @@ class ThousandFacedShadowTriggeredAbility extends TriggeredAbilityImpl { public String getRule() { return "When {this} enters from your hand, if it's attacking, " + "create a token that's a copy of another target attacking creature. " + - "The token enters the battlefield tapped and attacking."; + "The token enters tapped and attacking."; } } diff --git a/Mage.Sets/src/mage/cards/t/ThranQuarry.java b/Mage.Sets/src/mage/cards/t/ThranQuarry.java index 2b2fa0d2921..955dec45d33 100644 --- a/Mage.Sets/src/mage/cards/t/ThranQuarry.java +++ b/Mage.Sets/src/mage/cards/t/ThranQuarry.java @@ -1,36 +1,38 @@ - package mage.cards.t; -import java.util.UUID; -import mage.abilities.TriggeredAbility; -import mage.abilities.common.OnEventTriggeredAbility; -import mage.abilities.condition.common.CreatureCountCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.mana.AnyColorManaAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.ComparisonType; import mage.constants.TargetController; -import mage.game.events.GameEvent; +import mage.filter.common.FilterControlledCreaturePermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class ThranQuarry extends CardImpl { + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledCreaturePermanent("you control no creatures"), ComparisonType.EQUAL_TO, 0 + ); + public ThranQuarry(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.LAND},""); + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); // At the beginning of the end step, if you control no creatures, sacrifice Thran Quarry. - TriggeredAbility triggered = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new SacrificeSourceEffect()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(triggered, new CreatureCountCondition(0, TargetController.YOU), - "At the beginning of the end step, if you control no creatures, sacrifice {this}.")); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.NEXT, new SacrificeSourceEffect(), false, condition + )); // {tap}: Add one mana of any color. this.addAbility(new AnyColorManaAbility()); - } private ThranQuarry(final ThranQuarry card) { diff --git a/Mage.Sets/src/mage/cards/t/ThranTome.java b/Mage.Sets/src/mage/cards/t/ThranTome.java index ddf7b2cd564..974f50258b7 100644 --- a/Mage.Sets/src/mage/cards/t/ThranTome.java +++ b/Mage.Sets/src/mage/cards/t/ThranTome.java @@ -1,6 +1,5 @@ package mage.cards.t; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; @@ -13,11 +12,9 @@ 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; /** @@ -31,6 +28,7 @@ public final class ThranTome extends CardImpl { // 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()); + ability.addTarget(new TargetOpponent()); this.addAbility(ability); } @@ -62,35 +60,18 @@ class ThranTomeEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - // validate source and controller exist + // validate opponent and controller exist Player controller = game.getPlayer(source.getControllerId()); - MageObject sourceObject = game.getObject(source); + Player opponent = game.getPlayer(getTargetPointer().getFirst(game, source)); - if (sourceObject == null || controller == null) { + if (opponent == 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(), source, 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); + controller.revealCards(source, cards, game); if (cards.size() == 1) { cardToGraveyard = cards.getRandom(game); diff --git a/Mage.Sets/src/mage/cards/t/ThreadsOfDisloyalty.java b/Mage.Sets/src/mage/cards/t/ThreadsOfDisloyalty.java index ce924743d93..c4e82d6e750 100644 --- a/Mage.Sets/src/mage/cards/t/ThreadsOfDisloyalty.java +++ b/Mage.Sets/src/mage/cards/t/ThreadsOfDisloyalty.java @@ -38,7 +38,7 @@ public final class ThreadsOfDisloyalty extends CardImpl { this.subtype.add(SubType.AURA); // Enchant creature with converted mana cost 2 or less - TargetPermanent auraTarget = new TargetCreaturePermanent(filter); + TargetPermanent auraTarget = new TargetPermanent(filter); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.GainControl)); Ability ability = new EnchantAbility(auraTarget); diff --git a/Mage.Sets/src/mage/cards/t/ThroneOfEldraine.java b/Mage.Sets/src/mage/cards/t/ThroneOfEldraine.java index 5b503d04ec9..5d90e113827 100644 --- a/Mage.Sets/src/mage/cards/t/ThroneOfEldraine.java +++ b/Mage.Sets/src/mage/cards/t/ThroneOfEldraine.java @@ -11,9 +11,10 @@ import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ColoredManaCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.ChooseColorEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.mana.ManaEffect; import mage.abilities.mana.SimpleManaAbility; import mage.abilities.mana.builder.ConditionalManaBuilder; @@ -41,14 +42,12 @@ public final class ThroneOfEldraine extends CardImpl { this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new ThroneOfEldraineManaEffect(), new TapSourceCost())); // {3}, {T}: Draw two cards. Spend only mana of the chosen color to activate this ability. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, - new DrawCardSourceControllerEffect(2), - new GenericManaCost(3), - ThroneOfEldraineChosenColorCondition.instance, // disable the ability if no color was chosen or cost is actually {0}. - "{3}, {T}: Draw two cards. Spend only mana of the chosen color to activate this ability." - ); + Ability ability = new ActivateIfConditionActivatedAbility( + new DrawCardSourceControllerEffect(2), new GenericManaCost(3), + ThroneOfEldraineChosenColorCondition.instance // disable the ability if no color was chosen or cost is actually {0}. + ).hideCondition(); ability.addCost(new TapSourceCost()); + ability.addEffect(new InfoEffect("Spend only mana of the chosen color to activate this ability")); ability.setCostAdjuster(ThroneOfEldraineAdjuster.instance); this.addAbility(ability); } @@ -214,4 +213,4 @@ enum ThroneOfEldraineChosenColorCondition implements Condition { ObjectColor color = (ObjectColor) game.getState().getValue(source.getSourceId() + "_color"); return color != null || source.getManaCostsToPay().getMana().count() == 0; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/t/ThrowFromTheSaddle.java b/Mage.Sets/src/mage/cards/t/ThrowFromTheSaddle.java index e010cdcca59..c0de0f4535c 100644 --- a/Mage.Sets/src/mage/cards/t/ThrowFromTheSaddle.java +++ b/Mage.Sets/src/mage/cards/t/ThrowFromTheSaddle.java @@ -13,12 +13,15 @@ import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author Susucr */ @@ -29,7 +32,7 @@ public final class ThrowFromTheSaddle extends CardImpl { // Target creature you control gets +1/+1 until end of turn. Put a +1/+1 counter on it instead if it's a Mount. Then it deals damage equal to its power to target creature you don't control. this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.getSpellAbility().addEffect(new ThrowFromTheSaddleEffect()); this.getSpellAbility().addEffect(new DamageWithPowerFromOneToAnotherTargetEffect("it").concatBy("Then")); } diff --git a/Mage.Sets/src/mage/cards/t/Thumbscrews.java b/Mage.Sets/src/mage/cards/t/Thumbscrews.java index a022de33325..95459d549fd 100644 --- a/Mage.Sets/src/mage/cards/t/Thumbscrews.java +++ b/Mage.Sets/src/mage/cards/t/Thumbscrews.java @@ -1,37 +1,32 @@ - package mage.cards.t; -import java.util.UUID; import mage.abilities.TriggeredAbility; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInHandCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; import mage.target.common.TargetOpponentOrPlaneswalker; +import java.util.UUID; + /** - * * @author fireshoes */ public final class Thumbscrews extends CardImpl { + private static final Condition condition = new CardsInHandCondition(ComparisonType.MORE_THAN, 4); + public Thumbscrews(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); // At the beginning of your upkeep, if you have five or more cards in hand, Thumbscrews deals 1 damage to target opponent. - TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility( - new DamageTargetEffect(1)); + TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new DamageTargetEffect(1)).withInterveningIf(condition); ability.addTarget(new TargetOpponentOrPlaneswalker()); - CardsInHandCondition condition = new CardsInHandCondition(ComparisonType.MORE_THAN, 4); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - ability, condition, - "At the beginning of your upkeep, if you have five or more cards in hand, " - + "{this} deals 1 damage to target opponent or planeswalker." - )); + this.addAbility(ability); } private Thumbscrews(final Thumbscrews card) { diff --git a/Mage.Sets/src/mage/cards/t/ThunderBrute.java b/Mage.Sets/src/mage/cards/t/ThunderBrute.java index bd33753ca5a..e7049fce44f 100644 --- a/Mage.Sets/src/mage/cards/t/ThunderBrute.java +++ b/Mage.Sets/src/mage/cards/t/ThunderBrute.java @@ -1,12 +1,8 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.TributeNotPaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.TrampleAbility; @@ -14,17 +10,18 @@ import mage.abilities.keyword.TributeAbility; 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 java.util.UUID; /** - * * @author LevelX2 */ public final class ThunderBrute extends CardImpl { public ThunderBrute(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}{R}"); this.subtype.add(SubType.CYCLOPS); this.power = new MageInt(5); @@ -32,12 +29,14 @@ public final class ThunderBrute extends CardImpl { // Trample this.addAbility(TrampleAbility.getInstance()); - // Tribute 3
+ + // Tribute 3 this.addAbility(new TributeAbility(3)); + // When Thunder Brute enters the battlefield, if tribute wasn't paid, it gains haste until end of turn. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.EndOfTurn), false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, TributeNotPaidCondition.instance, - "When {this} enters, if tribute wasn't paid, it gains haste until end of turn.")); + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainAbilitySourceEffect( + HasteAbility.getInstance(), Duration.EndOfTurn + ).setText("it gains haste until end of turn")).withInterveningIf(TributeNotPaidCondition.instance)); } private ThunderBrute(final ThunderBrute card) { diff --git a/Mage.Sets/src/mage/cards/t/Thunderbolt.java b/Mage.Sets/src/mage/cards/t/Thunderbolt.java index 3f82a044ce4..453a29b60c2 100644 --- a/Mage.Sets/src/mage/cards/t/Thunderbolt.java +++ b/Mage.Sets/src/mage/cards/t/Thunderbolt.java @@ -10,6 +10,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetPlayerOrPlaneswalker; @@ -32,7 +33,7 @@ public final class Thunderbolt extends CardImpl { this.getSpellAbility().addEffect(new DamageTargetEffect(3)); this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker()); Mode mode = new Mode(new DamageTargetEffect(4)); - mode.addTarget(new TargetCreaturePermanent(filter)); + mode.addTarget(new TargetPermanent(filter)); this.getSpellAbility().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/t/ThunderscapeBattlemage.java b/Mage.Sets/src/mage/cards/t/ThunderscapeBattlemage.java index 522147150de..4fa6e8cc8ee 100644 --- a/Mage.Sets/src/mage/cards/t/ThunderscapeBattlemage.java +++ b/Mage.Sets/src/mage/cards/t/ThunderscapeBattlemage.java @@ -1,12 +1,10 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.KickedCostCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.abilities.keyword.KickerAbility; @@ -17,14 +15,18 @@ import mage.constants.SubType; import mage.target.TargetPlayer; import mage.target.common.TargetEnchantmentPermanent; +import java.util.UUID; + /** - * * @author FenrisulfrX */ public final class ThunderscapeBattlemage extends CardImpl { + private static final Condition condition = new KickedCostCondition("{1}{B}"); + private static final Condition condition2 = new KickedCostCondition("{G}"); + public ThunderscapeBattlemage(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WIZARD); this.power = new MageInt(2); @@ -36,16 +38,14 @@ public final class ThunderscapeBattlemage extends CardImpl { this.addAbility(kickerAbility); // When {this} enters, if it was kicked with its {1}{B} kicker, target player discards two cards. - TriggeredAbility ability1 = new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(2)); - ability1.addTarget(new TargetPlayer()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability1, new KickedCostCondition("{1}{B}"), - "When {this} enters, if it was kicked with its {1}{B} kicker, target player discards two cards.")); + Ability ability = new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(2)).withInterveningIf(condition); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); // When {this} enters, if it was kicked with its {G} kicker, destroy target enchantment. - TriggeredAbility ability2 = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()); - ability2.addTarget(new TargetEnchantmentPermanent()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability2, new KickedCostCondition("{G}"), - "When {this} enters, if it was kicked with its {G} kicker, destroy target enchantment.")); + ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()).withInterveningIf(condition2); + ability.addTarget(new TargetEnchantmentPermanent()); + this.addAbility(ability); } private ThunderscapeBattlemage(final ThunderscapeBattlemage card) { diff --git a/Mage.Sets/src/mage/cards/t/Tiamat.java b/Mage.Sets/src/mage/cards/t/Tiamat.java index c72966919ca..9f416373650 100644 --- a/Mage.Sets/src/mage/cards/t/Tiamat.java +++ b/Mage.Sets/src/mage/cards/t/Tiamat.java @@ -3,7 +3,6 @@ package mage.cards.t; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromEverywhereSourceCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -45,13 +44,9 @@ public final class Tiamat extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When Tiamat enters the battlefield, if you cast it, search your library for up to five Dragon cards named Tiama that each have different names, reveal them, put them into your hand, then shuffle. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility( - new SearchLibraryPutInHandEffect( - new TargetCardWithDifferentNameInLibrary(0, 5, filter), true - )), CastFromEverywhereSourceCondition.instance, "When {this} enters, " + - "if you cast it, search your library for up to five Dragon cards not named Tiamat " + - "that each have different names, reveal them, put them into your hand, then shuffle." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new SearchLibraryPutInHandEffect( + new TargetCardWithDifferentNameInLibrary(0, 5, filter), true + )).withInterveningIf(CastFromEverywhereSourceCondition.instance)); } private Tiamat(final Tiamat card) { diff --git a/Mage.Sets/src/mage/cards/t/TidalSurge.java b/Mage.Sets/src/mage/cards/t/TidalSurge.java index 0a0b749abad..2651c81d2bb 100644 --- a/Mage.Sets/src/mage/cards/t/TidalSurge.java +++ b/Mage.Sets/src/mage/cards/t/TidalSurge.java @@ -1,7 +1,5 @@ - package mage.cards.t; -import java.util.UUID; import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -10,10 +8,11 @@ import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author Quercitron */ public final class TidalSurge extends CardImpl { @@ -23,14 +22,13 @@ public final class TidalSurge extends CardImpl { static { filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class))); } - - public TidalSurge(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{U}"); + public TidalSurge(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}"); // Tap up to three target creatures without flying. this.getSpellAbility().addEffect(new TapTargetEffect("tap up to three target creatures without flying")); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 3, filter, false)); + this.getSpellAbility().addTarget(new TargetPermanent(0, 3, filter)); } private TidalSurge(final TidalSurge card) { diff --git a/Mage.Sets/src/mage/cards/t/TideShaper.java b/Mage.Sets/src/mage/cards/t/TideShaper.java index 985149c1f8b..9f5f6af0fe1 100644 --- a/Mage.Sets/src/mage/cards/t/TideShaper.java +++ b/Mage.Sets/src/mage/cards/t/TideShaper.java @@ -8,7 +8,6 @@ import mage.abilities.condition.Condition; import mage.abilities.condition.common.KickedCondition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BecomesBasicLandTargetEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.hint.ConditionHint; @@ -16,7 +15,10 @@ import mage.abilities.hint.Hint; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +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.target.common.TargetLandPermanent; @@ -50,11 +52,7 @@ public final class TideShaper extends CardImpl { this.addAbility(new KickerAbility("{1}")); // When Tide Shaper enters the battlefield, if it was kicked, target land becomes an Island for as long as Tide Shaper remains on the battlefield. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new TideShaperEffect()), - KickedCondition.ONCE, "When {this} enters, if it was kicked, " + - "target land becomes an Island for as long as {this} remains on the battlefield." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new TideShaperEffect()).withInterveningIf(KickedCondition.ONCE); ability.addTarget(new TargetLandPermanent()); this.addAbility(ability); @@ -79,6 +77,7 @@ class TideShaperEffect extends BecomesBasicLandTargetEffect { TideShaperEffect() { super(Duration.Custom, false, true, SubType.ISLAND); + staticText = "target land becomes an Island for as long as {this} remains on the battlefield"; } private TideShaperEffect(final TideShaperEffect effect) { diff --git a/Mage.Sets/src/mage/cards/t/TidebinderMage.java b/Mage.Sets/src/mage/cards/t/TidebinderMage.java index ebf8ae0c759..6741c857be3 100644 --- a/Mage.Sets/src/mage/cards/t/TidebinderMage.java +++ b/Mage.Sets/src/mage/cards/t/TidebinderMage.java @@ -16,6 +16,7 @@ import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -48,7 +49,7 @@ public final class TidebinderMage extends CardImpl { // That creature doesn't untap during its controller's untap step for as long as you control Tidebinder Mage. Ability ability = new EntersBattlefieldTriggeredAbility(new TapTargetEffect(), false); ability.addEffect(new DontUntapInControllersUntapStepTargetEffect(Duration.WhileControlled)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TidecallerMentor.java b/Mage.Sets/src/mage/cards/t/TidecallerMentor.java index 5100e75d776..53740be2f55 100644 --- a/Mage.Sets/src/mage/cards/t/TidecallerMentor.java +++ b/Mage.Sets/src/mage/cards/t/TidecallerMentor.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.ThresholdCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.abilities.keyword.MenaceAbility; import mage.cards.CardImpl; @@ -33,11 +32,7 @@ public final class TidecallerMentor extends CardImpl { this.addAbility(new MenaceAbility(false)); // Threshold -- When Tidecaller Mentor enters, if seven or more cards are in your graveyard, return up to one target nonland permanent to its owner's hand. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()), - ThresholdCondition.instance, "When {this} enters, if seven or more cards " + - "are in your graveyard, return up to one target nonland permanent to its owner's hand." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()).withInterveningIf(ThresholdCondition.instance); ability.addTarget(new TargetNonlandPermanent(0, 1)); this.addAbility(ability.setAbilityWord(AbilityWord.THRESHOLD)); } diff --git a/Mage.Sets/src/mage/cards/t/TideforceElemental.java b/Mage.Sets/src/mage/cards/t/TideforceElemental.java index f1028901dfd..2368549edc4 100644 --- a/Mage.Sets/src/mage/cards/t/TideforceElemental.java +++ b/Mage.Sets/src/mage/cards/t/TideforceElemental.java @@ -17,8 +17,11 @@ import mage.constants.SubType; import mage.constants.ColoredManaSymbol; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * * @author Loki @@ -37,7 +40,7 @@ public final class TideforceElemental extends CardImpl { new MayTapOrUntapTargetEffect(), new ColoredManaCost(ColoredManaSymbol.U)); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); // Landfall - Whenever a land you control enters, you may untap Tideforce Elemental. this.addAbility(new LandfallAbility(new UntapSourceEffect(), true)); diff --git a/Mage.Sets/src/mage/cards/t/TideshaperMystic.java b/Mage.Sets/src/mage/cards/t/TideshaperMystic.java index b5821d44d6e..59dd2ce550c 100644 --- a/Mage.Sets/src/mage/cards/t/TideshaperMystic.java +++ b/Mage.Sets/src/mage/cards/t/TideshaperMystic.java @@ -6,13 +6,11 @@ import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.common.continuous.BecomesBasicLandTargetEffect; -import mage.abilities.hint.common.MyTurnHint; 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.target.common.TargetLandPermanent; import java.util.UUID; @@ -30,10 +28,10 @@ public final class TideshaperMystic extends CardImpl { this.toughness = new MageInt(1); // {T}: Target land becomes the basic land type of your choice until end of turn. Activate this ability only during your turn. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new BecomesBasicLandTargetEffect(Duration.EndOfTurn), new TapSourceCost(), MyTurnCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new BecomesBasicLandTargetEffect(Duration.EndOfTurn), new TapSourceCost(), MyTurnCondition.instance + ); ability.addTarget(new TargetLandPermanent()); - ability.addHint(MyTurnHint.instance); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TillerEngine.java b/Mage.Sets/src/mage/cards/t/TillerEngine.java index bcc66d292a7..23b412e6b12 100644 --- a/Mage.Sets/src/mage/cards/t/TillerEngine.java +++ b/Mage.Sets/src/mage/cards/t/TillerEngine.java @@ -11,6 +11,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; +import mage.filter.FilterPermanent; import mage.filter.StaticFilters; import mage.filter.common.FilterControlledLandPermanent; import mage.filter.predicate.permanent.TappedPredicate; @@ -25,7 +26,7 @@ import java.util.UUID; */ public final class TillerEngine extends CardImpl { - private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent(); + private static final FilterPermanent filter = new FilterControlledLandPermanent(); static { filter.add(TappedPredicate.TAPPED); @@ -40,7 +41,7 @@ public final class TillerEngine extends CardImpl { // Whenever a land enters the battlefield tapped and under your control, choose one — // • Untap that land. Ability ability = new EntersBattlefieldControlledTriggeredAbility(new TillerEngineUntapEffect(), filter) - .setTriggerPhrase("Whenever a land enters the battlefield tapped and under your control, "); + .setTriggerPhrase("Whenever a land you control enters tapped, "); // • Tap target nonland permanent an opponent controls. Mode mode = new Mode(new TapTargetEffect()); diff --git a/Mage.Sets/src/mage/cards/t/TilonallisKnight.java b/Mage.Sets/src/mage/cards/t/TilonallisKnight.java index 4f3a8203a26..6aae7a35233 100644 --- a/Mage.Sets/src/mage/cards/t/TilonallisKnight.java +++ b/Mage.Sets/src/mage/cards/t/TilonallisKnight.java @@ -1,31 +1,27 @@ - package mage.cards.t; -import java.util.UUID; 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.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.FilterControlledPermanent; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class TilonallisKnight extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent(); - - static { - filter.add(SubType.DINOSAUR.getPredicate()); - } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPermanent(SubType.DINOSAUR, "you control a Dinosaur") + ); public TilonallisKnight(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}"); @@ -36,12 +32,7 @@ public final class TilonallisKnight extends CardImpl { this.toughness = new MageInt(2); // Whenever Tilonalli's Knight attacks, if you control a Dinosaur, Tilonalli's Knight gets +1/+1 until end of turn. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new BoostSourceEffect(1, 1, Duration.EndOfTurn), false), - new PermanentsOnTheBattlefieldCondition(filter), - "Whenever {this} attacks, if you control a Dinosaur, {this} gets +1/+1 until end of turn." - ); - this.addAbility(ability); + this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect(1, 1, Duration.EndOfTurn)).withInterveningIf(condition)); } private TilonallisKnight(final TilonallisKnight card) { diff --git a/Mage.Sets/src/mage/cards/t/TimeOfIce.java b/Mage.Sets/src/mage/cards/t/TimeOfIce.java index 4b66573aafb..816d39c49ce 100644 --- a/Mage.Sets/src/mage/cards/t/TimeOfIce.java +++ b/Mage.Sets/src/mage/cards/t/TimeOfIce.java @@ -15,10 +15,15 @@ import mage.constants.SubType; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.constants.SagaChapter.CHAPTER_I; +import static mage.constants.SagaChapter.CHAPTER_II; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * @author TheElk801 */ @@ -43,8 +48,8 @@ public final class TimeOfIce extends CardImpl { effects.add(new TapTargetEffect()); effects.add(new DontUntapInControllersUntapStepTargetEffect(Duration.WhileControlled, "It")); sagaAbility.addChapterEffect( - this, SagaChapter.CHAPTER_I, SagaChapter.CHAPTER_II, effects, - new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE) + this, CHAPTER_I, CHAPTER_II, effects, + new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE) ); // III — Return all tapped creatures to their owners' hands. diff --git a/Mage.Sets/src/mage/cards/t/TimeToReflect.java b/Mage.Sets/src/mage/cards/t/TimeToReflect.java index bd873cff303..1d0ea5e1497 100644 --- a/Mage.Sets/src/mage/cards/t/TimeToReflect.java +++ b/Mage.Sets/src/mage/cards/t/TimeToReflect.java @@ -63,7 +63,7 @@ enum TimeToReflectAdjuster implements TargetAdjuster { } filter.add(Predicates.or(creaturesThatBlockedOrWereBlockedByAZombie)); ability.getTargets().clear(); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); } } diff --git a/Mage.Sets/src/mage/cards/t/TimelyHordemate.java b/Mage.Sets/src/mage/cards/t/TimelyHordemate.java index 51548c4efeb..6a100c597ef 100644 --- a/Mage.Sets/src/mage/cards/t/TimelyHordemate.java +++ b/Mage.Sets/src/mage/cards/t/TimelyHordemate.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.hint.common.RaidHint; import mage.cards.CardImpl; @@ -40,13 +39,9 @@ public final class TimelyHordemate extends CardImpl { this.toughness = new MageInt(2); // Raid — When Timely Hordemate enters the battlefield, if you attacked this turn, return target creature card with converted mana cost 2 or less from your graveyard to the battlefield. - Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect()), RaidCondition.instance, - "When {this} enters, if you attacked this turn, return target creature card with mana value 2 or less from your graveyard to the battlefield."); + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect()).withInterveningIf(RaidCondition.instance); ability.addTarget(new TargetCardInYourGraveyard(filter)); - ability.setAbilityWord(AbilityWord.RAID); - ability.addHint(RaidHint.instance); - this.addAbility(ability, new PlayerAttackedWatcher()); - + this.addAbility(ability.setAbilityWord(AbilityWord.RAID).addHint(RaidHint.instance), new PlayerAttackedWatcher()); } private TimelyHordemate(final TimelyHordemate card) { diff --git a/Mage.Sets/src/mage/cards/t/TimestreamNavigator.java b/Mage.Sets/src/mage/cards/t/TimestreamNavigator.java index 2e53082b8fd..1a6567498b2 100644 --- a/Mage.Sets/src/mage/cards/t/TimestreamNavigator.java +++ b/Mage.Sets/src/mage/cards/t/TimestreamNavigator.java @@ -6,7 +6,7 @@ import mage.abilities.condition.common.CitysBlessingCondition; import mage.abilities.costs.common.PutSourceOnBottomOwnerLibraryCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.turn.AddExtraTurnControllerEffect; import mage.abilities.hint.common.CitysBlessingHint; import mage.abilities.keyword.AscendAbility; @@ -14,7 +14,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import java.util.UUID; @@ -36,15 +35,12 @@ public final class TimestreamNavigator extends CardImpl { this.addAbility(new AscendAbility()); // {2}{U}{U}, {T}, Put Timestream Navigator on the bottom of its owner's library: Take an extra turn after this one. Activate this ability only if you have the city's blessing. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, - new AddExtraTurnControllerEffect(), - new ManaCostsImpl<>("{2}{U}{U}"), - CitysBlessingCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new AddExtraTurnControllerEffect(), new ManaCostsImpl<>("{2}{U}{U}"), CitysBlessingCondition.instance + ); ability.addCost(new TapSourceCost()); ability.addCost(new PutSourceOnBottomOwnerLibraryCost()); - ability.addHint(CitysBlessingHint.instance); - this.addAbility(ability); - + this.addAbility(ability.addHint(CitysBlessingHint.instance)); } private TimestreamNavigator(final TimestreamNavigator card) { diff --git a/Mage.Sets/src/mage/cards/t/TinStreetHooligan.java b/Mage.Sets/src/mage/cards/t/TinStreetHooligan.java index d7b6814117d..afbff085379 100644 --- a/Mage.Sets/src/mage/cards/t/TinStreetHooligan.java +++ b/Mage.Sets/src/mage/cards/t/TinStreetHooligan.java @@ -1,28 +1,25 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.ManaWasSpentCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; 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.ColoredManaSymbol; import mage.target.common.TargetArtifactPermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class TinStreetHooligan extends CardImpl { public TinStreetHooligan(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.GOBLIN); this.subtype.add(SubType.ROGUE); @@ -30,10 +27,7 @@ public final class TinStreetHooligan extends CardImpl { this.toughness = new MageInt(1); // When Tin Street Hooligan enters the battlefield, if {G} was spent to cast Tin Street Hooligan, destroy target artifact. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()), - ManaWasSpentCondition.GREEN, - "When {this} enters, if {G} was spent to cast it, destroy target artifact."); + Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()).withInterveningIf(ManaWasSpentCondition.GREEN); ability.addTarget(new TargetArtifactPermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TinWingChimera.java b/Mage.Sets/src/mage/cards/t/TinWingChimera.java index 82860ddb9fc..ec1cb34f951 100644 --- a/Mage.Sets/src/mage/cards/t/TinWingChimera.java +++ b/Mage.Sets/src/mage/cards/t/TinWingChimera.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -45,7 +46,7 @@ public final class TinWingChimera extends CardImpl { Ability ability = new SimpleActivatedAbility(new AddCountersTargetEffect(CounterType.P2P2.createInstance()), new SacrificeSourceCost()); ability.addEffect(new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.WhileOnBattlefield) .setText("It gains flying. (This effect lasts indefinitely.)")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TinybonesTrinketThief.java b/Mage.Sets/src/mage/cards/t/TinybonesTrinketThief.java index 72189d70295..88169e2b04a 100644 --- a/Mage.Sets/src/mage/cards/t/TinybonesTrinketThief.java +++ b/Mage.Sets/src/mage/cards/t/TinybonesTrinketThief.java @@ -2,14 +2,13 @@ package mage.cards.t; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.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.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -37,14 +36,11 @@ public final class TinybonesTrinketThief extends CardImpl { 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( - TargetController.EACH_PLAYER, new DrawCardSourceControllerEffect(1), - 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 ability = new BeginningOfEndStepTriggeredAbility( + TargetController.ANY, new DrawCardSourceControllerEffect(1, true), + false, TinybonesTrinketThiefCondition.instance ); - ability.addEffect(new LoseLifeSourceControllerEffect(1)); + ability.addEffect(new LoseLifeSourceControllerEffect(1).concatBy("and")); this.addAbility(ability, new TinybonesTrinketThiefWatcher()); // {4}{B}{B}: Each opponent with no cards in hand loses 10 life. @@ -69,6 +65,11 @@ enum TinybonesTrinketThiefCondition implements Condition { TinybonesTrinketThiefWatcher watcher = game.getState().getWatcher(TinybonesTrinketThiefWatcher.class); return watcher != null && watcher.checkPlayer(source.getControllerId()); } + + @Override + public String toString() { + return "an opponent discarded a card this turn"; + } } class TinybonesTrinketThiefWatcher extends Watcher { diff --git a/Mage.Sets/src/mage/cards/t/TitanHunter.java b/Mage.Sets/src/mage/cards/t/TitanHunter.java index ad836e76bed..4697836741b 100644 --- a/Mage.Sets/src/mage/cards/t/TitanHunter.java +++ b/Mage.Sets/src/mage/cards/t/TitanHunter.java @@ -2,25 +2,22 @@ package mage.cards.t; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.MorbidCondition; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.hint.common.MorbidHint; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; 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.StaticFilters; -import mage.game.Game; import java.util.UUID; @@ -29,7 +26,7 @@ import java.util.UUID; */ public final class TitanHunter extends CardImpl { - private static final Condition condition = new InvertCondition(MorbidCondition.instance); + private static final Condition condition = new InvertCondition(MorbidCondition.instance, "no creatures died this turn"); public TitanHunter(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}"); @@ -40,11 +37,10 @@ public final class TitanHunter extends CardImpl { this.toughness = new MageInt(5); // At the beginning of each player's end step, if no creatures died this turn, Titan Hunter deals 4 damage to that player. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - TargetController.EACH_PLAYER, new TitanHunterEffect(), false - ), condition, "At the beginning of each player's end step, " + - "if no creatures died this turn, {this} deals 4 damage to that player." + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.EACH_PLAYER, + new DamageTargetEffect(4, true, "that player"), + false, condition ).addHint(MorbidHint.instance)); // {1}{B}, Sacrifice a creature: You gain 4 life. @@ -62,27 +58,3 @@ public final class TitanHunter extends CardImpl { return new TitanHunter(this); } } - -class TitanHunterEffect extends OneShotEffect { - - TitanHunterEffect() { - super(Outcome.Benefit); - } - - private TitanHunterEffect(final TitanHunterEffect effect) { - super(effect); - } - - @Override - public TitanHunterEffect copy() { - return new TitanHunterEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - return game.damagePlayerOrPermanent( - game.getActivePlayerId(), 4, source.getSourceId(), - source, game, false, true - ) > 0; - } -} diff --git a/Mage.Sets/src/mage/cards/t/TitaniaVoiceOfGaea.java b/Mage.Sets/src/mage/cards/t/TitaniaVoiceOfGaea.java index c7f8c3e5263..97edb8672ca 100644 --- a/Mage.Sets/src/mage/cards/t/TitaniaVoiceOfGaea.java +++ b/Mage.Sets/src/mage/cards/t/TitaniaVoiceOfGaea.java @@ -2,19 +2,21 @@ package mage.cards.t; import mage.MageInt; import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.CompoundCondition; import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInControllerGraveyardCondition; import mage.abilities.condition.common.MeldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.MeldEffect; import mage.abilities.keyword.ReachAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.Zone; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; @@ -28,6 +30,8 @@ import java.util.UUID; public final class TitaniaVoiceOfGaea extends CardImpl { private static final Condition condition = new CompoundCondition( + "there are four or more land cards in your graveyard and you " + + "both own and control {this} and a land named Argoth, Sanctum of Nature", new CardsInControllerGraveyardCondition(4, StaticFilters.FILTER_CARD_LAND), new MeldCondition("Argoth, Sanctum of Nature", CardType.LAND) ); @@ -50,13 +54,9 @@ public final class TitaniaVoiceOfGaea extends CardImpl { this.addAbility(new TitaniaVoiceOfGaeaTriggeredAbility()); // At the beginning of your upkeep, if there are four or more land cards in your graveyard and you both own and control Titania, Voice of Gaea and a land named Argoth, Sanctum of Nature, exile them, then meld them into Titania, Gaea Incarnate. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new MeldEffect( - "Argoth, Sanctum of Nature", "Titania, Gaea Incarnate" - )), condition, "At the beginning of your upkeep, " + - "if there are four or more land cards in your graveyard and you both own and control {this} " + - "and a land named Argoth, Sanctum of Nature, exile them, then meld them into Titania, Gaea Incarnate." - )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new MeldEffect( + "Argoth, Sanctum of Nature", "Titania, Gaea Incarnate" + )).withInterveningIf(condition)); } private TitaniaVoiceOfGaea(final TitaniaVoiceOfGaea card) { diff --git a/Mage.Sets/src/mage/cards/t/TitanicBrawl.java b/Mage.Sets/src/mage/cards/t/TitanicBrawl.java index e42199ec912..bb682069167 100644 --- a/Mage.Sets/src/mage/cards/t/TitanicBrawl.java +++ b/Mage.Sets/src/mage/cards/t/TitanicBrawl.java @@ -10,11 +10,14 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author TheElk801 */ @@ -33,7 +36,7 @@ public final class TitanicBrawl extends CardImpl { // Target creature you control fights target creature you don't control. this.getSpellAbility().addEffect(new FightTargetsEffect()); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); } private TitanicBrawl(final TitanicBrawl card) { diff --git a/Mage.Sets/src/mage/cards/t/ToTheSlaughter.java b/Mage.Sets/src/mage/cards/t/ToTheSlaughter.java index 0b441cf269c..b61f1451dfd 100644 --- a/Mage.Sets/src/mage/cards/t/ToTheSlaughter.java +++ b/Mage.Sets/src/mage/cards/t/ToTheSlaughter.java @@ -26,7 +26,7 @@ public final class ToTheSlaughter extends CardImpl { this.getSpellAbility().addEffect(new ConditionalOneShotEffect( new SacrificeEffect(new FilterCreatureOrPlaneswalkerPermanent(), 1, "Target player"), new InvertCondition(DeliriumCondition.instance), - "Target player sacrifices a creature or planeswalker.")); + "Target player sacrifices a creature or planeswalker of their choice.")); // Delirium — If there are four or more card types among cards in your graveyard, instead that player sacrifices a creature and a planeswalker. this.getSpellAbility().addEffect(new ConditionalOneShotEffect( @@ -35,7 +35,7 @@ public final class ToTheSlaughter extends CardImpl { "
Delirium — If there are four or more card types among cards in your graveyard, instead that player sacrifices a creature")); this.getSpellAbility().addEffect(new ConditionalOneShotEffect( new SacrificeEffect(StaticFilters.FILTER_PERMANENT_PLANESWALKER, 1, "Target player"), - DeliriumCondition.instance, "and a planeswalker.")); + DeliriumCondition.instance, "and a planeswalker of their choice.")); this.getSpellAbility().addTarget(new TargetPlayer()); this.getSpellAbility().addHint(CardTypesInGraveyardCount.YOU.getHint()); } diff --git a/Mage.Sets/src/mage/cards/t/Tolaria.java b/Mage.Sets/src/mage/cards/t/Tolaria.java index 3bec567d677..e913dd389ee 100644 --- a/Mage.Sets/src/mage/cards/t/Tolaria.java +++ b/Mage.Sets/src/mage/cards/t/Tolaria.java @@ -1,30 +1,31 @@ - package mage.cards.t; -import java.util.UUID; import mage.abilities.ActivatedAbilityImpl; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.continuous.LoseAbilityTargetEffect; import mage.abilities.keyword.BandingAbility; import mage.abilities.keyword.BandsWithOtherAbility; import mage.abilities.mana.BlueManaAbility; -import mage.constants.SuperType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.PhaseStep; -import mage.constants.Zone; +import mage.constants.SuperType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author L_J */ public final class Tolaria extends CardImpl { + private static final Condition condition = new IsStepCondition(PhaseStep.UPKEEP, false); + public Tolaria(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); this.supertype.add(SuperType.LEGENDARY); @@ -33,10 +34,15 @@ public final class Tolaria extends CardImpl { this.addAbility(new BlueManaAbility()); // {T}: Target creature loses banding and all "bands with other" abilities until end of turn. Activate this ability only during any upkeep step. - ActivatedAbilityImpl ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, - new LoseAbilityTargetEffect(BandingAbility.getInstance(), Duration.EndOfTurn), new TapSourceCost(), new IsStepCondition(PhaseStep.UPKEEP, false), - "{T}: Target creature loses banding and all \"bands with other\" abilities until end of turn. Activate only during any upkeep step."); - ability.addEffect(new LoseAbilityTargetEffect(new BandsWithOtherAbility(), Duration.EndOfTurn)); + ActivatedAbilityImpl ability = new ActivateIfConditionActivatedAbility( + new LoseAbilityTargetEffect( + BandingAbility.getInstance(), Duration.EndOfTurn + ).setText("target creature loses banding"), + new TapSourceCost(), condition + ); + ability.addEffect(new LoseAbilityTargetEffect( + new BandsWithOtherAbility(), Duration.EndOfTurn + ).setText("and all \"bands with other\" abilities until end of turn")); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TolarianEmissary.java b/Mage.Sets/src/mage/cards/t/TolarianEmissary.java index f43b025aa89..8ee277fecae 100644 --- a/Mage.Sets/src/mage/cards/t/TolarianEmissary.java +++ b/Mage.Sets/src/mage/cards/t/TolarianEmissary.java @@ -1,12 +1,9 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.KickerAbility; @@ -16,15 +13,15 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.target.common.TargetEnchantmentPermanent; -/** - * - * @author LoneFox +import java.util.UUID; +/** + * @author LoneFox */ public final class TolarianEmissary extends CardImpl { public TolarianEmissary(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.subtype.add(SubType.WIZARD); this.power = new MageInt(1); @@ -32,13 +29,14 @@ public final class TolarianEmissary extends CardImpl { // Kicker {1}{W} this.addAbility(new KickerAbility("{1}{W}")); + // Flying this.addAbility(FlyingAbility.getInstance()); + // When Tolarian Emissary enters the battlefield, if it was kicked, destroy target enchantment. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()); + Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()).withInterveningIf(KickedCondition.ONCE); ability.addTarget(new TargetEnchantmentPermanent()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.ONCE, - "When {this} enters, if it was kicked, destroy target enchantment.")); + this.addAbility(ability); } private TolarianEmissary(final TolarianEmissary card) { diff --git a/Mage.Sets/src/mage/cards/t/TolarianSerpent.java b/Mage.Sets/src/mage/cards/t/TolarianSerpent.java index 1825888bdf4..ad9cfedd168 100644 --- a/Mage.Sets/src/mage/cards/t/TolarianSerpent.java +++ b/Mage.Sets/src/mage/cards/t/TolarianSerpent.java @@ -1,32 +1,29 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.effects.common.MillCardsControllerEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.game.events.GameEvent.EventType; + +import java.util.UUID; /** - * * @author fireshoes */ public final class TolarianSerpent extends CardImpl { public TolarianSerpent(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(7); this.toughness = new MageInt(7); // At the beginning of your upkeep, put the top seven cards of your library into your graveyard. - this.addAbility(new OnEventTriggeredAbility(EventType.UPKEEP_STEP_PRE, - "beginning of your upkeep", - new MillCardsControllerEffect(7), false)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new MillCardsControllerEffect(7))); + } private TolarianSerpent(final TolarianSerpent card) { diff --git a/Mage.Sets/src/mage/cards/t/TolsimirMidnightsLight.java b/Mage.Sets/src/mage/cards/t/TolsimirMidnightsLight.java index 1a5ed067aa5..e1e848ec08d 100644 --- a/Mage.Sets/src/mage/cards/t/TolsimirMidnightsLight.java +++ b/Mage.Sets/src/mage/cards/t/TolsimirMidnightsLight.java @@ -1,24 +1,17 @@ package mage.cards.t; -import java.util.UUID; import mage.MageInt; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.AttacksAllTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.RequirementEffect; import mage.abilities.effects.common.CreateTokenEffect; -import mage.constants.Duration; -import mage.constants.SetTargetPointer; -import mage.constants.SubType; -import mage.constants.SuperType; import mage.abilities.keyword.LifelinkAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.TargetController; +import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; @@ -26,8 +19,9 @@ import mage.game.permanent.token.TolsimirMidnightsLightToken; import mage.target.common.TargetOpponentsCreaturePermanent; import mage.watchers.common.AttackedOrBlockedThisCombatWatcher; +import java.util.UUID; + /** - * * @author DominionSpy */ public final class TolsimirMidnightsLight extends CardImpl { @@ -54,10 +48,10 @@ public final class TolsimirMidnightsLight extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new TolsimirMidnightsLightToken()))); // Whenever a Wolf you control attacks, if Tolsimir attacked this combat, target creature an opponent controls blocks that Wolf this combat if able. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new AttacksAllTriggeredAbility(new TolsimirMidnightsLightEffect(), false, filter, SetTargetPointer.PERMANENT, false), - TolsimirMidnightsLightCondition.instance, - "Whenever a Wolf you control attacks, if {this} attacked this combat, target creature an opponent controls blocks that Wolf this combat if able."); + Ability ability = new AttacksAllTriggeredAbility( + new TolsimirMidnightsLightEffect(), false, filter, + SetTargetPointer.PERMANENT, false + ).withInterveningIf(TolsimirMidnightsLightCondition.instance); ability.addTarget(new TargetOpponentsCreaturePermanent()); this.addAbility(ability, new AttackedOrBlockedThisCombatWatcher()); } @@ -92,12 +86,18 @@ enum TolsimirMidnightsLightCondition implements Condition { } return false; } + + @Override + public String toString() { + return "{this} attacked this combat"; + } } class TolsimirMidnightsLightEffect extends RequirementEffect { TolsimirMidnightsLightEffect() { super(Duration.EndOfCombat); + staticText = "target creature an opponent controls blocks that Wolf this combat if able"; } private TolsimirMidnightsLightEffect(final TolsimirMidnightsLightEffect effect) { diff --git a/Mage.Sets/src/mage/cards/t/TombTyrant.java b/Mage.Sets/src/mage/cards/t/TombTyrant.java index 08e8b632ed3..e09f160fca7 100644 --- a/Mage.Sets/src/mage/cards/t/TombTyrant.java +++ b/Mage.Sets/src/mage/cards/t/TombTyrant.java @@ -19,7 +19,10 @@ import mage.abilities.hint.ValueHint; import mage.abilities.hint.common.MyTurnHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.StaticFilters; import mage.filter.common.FilterCreatureCard; @@ -44,7 +47,7 @@ public final class TombTyrant extends CardImpl { MyTurnCondition.instance, new CardsInControllerGraveyardCondition(3, filter2) ); private static final Hint hint = new ValueHint( - "Zombie creatures in your graveyard", new CardsInControllerGraveyardCount(filter2) + "Zombie creature cards in your graveyard", new CardsInControllerGraveyardCount(filter2) ); public TombTyrant(UUID ownerId, CardSetInfo setInfo) { @@ -62,7 +65,7 @@ public final class TombTyrant extends CardImpl { // {2}{B}, {T}, Sacrifice a creature: Return a Zombie creature card at random from your graveyard to the battlefield. Activate only during your turn and only if there are at least three Zombie creature cards in your graveyard. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new ReturnFromGraveyardAtRandomEffect(filter2, Zone.BATTLEFIELD), + new ReturnFromGraveyardAtRandomEffect(filter2, Zone.BATTLEFIELD), new ManaCostsImpl<>("{2}{B}"), condition ); ability.addCost(new TapSourceCost()); diff --git a/Mage.Sets/src/mage/cards/t/ToolcraftExemplar.java b/Mage.Sets/src/mage/cards/t/ToolcraftExemplar.java index 0dc88e49103..625984947c9 100644 --- a/Mage.Sets/src/mage/cards/t/ToolcraftExemplar.java +++ b/Mage.Sets/src/mage/cards/t/ToolcraftExemplar.java @@ -1,34 +1,37 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; -import mage.abilities.condition.LockedInCondition; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.MetalcraftCondition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalContinuousEffect; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.Effect; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.AddContinuousEffectToGame; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.hint.common.ArtifactYouControlHint; import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.ComparisonType; import mage.constants.Duration; +import mage.constants.SubType; import mage.filter.common.FilterControlledArtifactPermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class ToolcraftExemplar extends CardImpl { + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledArtifactPermanent("you control an artifact") + ); + public ToolcraftExemplar(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}"); this.subtype.add(SubType.DWARF); this.subtype.add(SubType.ARTIFICER); this.power = new MageInt(1); @@ -36,16 +39,13 @@ public final class ToolcraftExemplar extends CardImpl { // At the beginning of combat on your turn, if you control an artifact, Toolcraft Exemplar gets +2/+1 until end of turn. // If you control at least 3 artifacts, it also gains first strike until end of turn. - Effect effect = new ConditionalContinuousEffect( - new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), - new LockedInCondition(new PermanentsOnTheBattlefieldCondition(new FilterControlledArtifactPermanent(), ComparisonType.MORE_THAN, 2)), null); - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfCombatTriggeredAbility(new BoostSourceEffect(2, 1, Duration.EndOfTurn)), - new PermanentsOnTheBattlefieldCondition(new FilterControlledArtifactPermanent()), - "At the beginning of combat on your turn, if you control an artifact, {this} gets +2/+1 until end of turn." - + " If you control at least 3 artifacts, it also gains first strike until end of turn."); - ability.addEffect(effect); - this.addAbility(ability); + Ability ability = new BeginningOfCombatTriggeredAbility(new BoostSourceEffect( + 2, 1, Duration.EndOfTurn + )).withInterveningIf(condition); + ability.addEffect(new ConditionalOneShotEffect(new AddContinuousEffectToGame( + new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn) + ), MetalcraftCondition.instance, "If you control three or more artifacts, it also gains first strike until end of turn")); + this.addAbility(ability.addHint(ArtifactYouControlHint.instance)); } private ToolcraftExemplar(final ToolcraftExemplar card) { diff --git a/Mage.Sets/src/mage/cards/t/ToothCollector.java b/Mage.Sets/src/mage/cards/t/ToothCollector.java index 6e032980e2c..87753466bb7 100644 --- a/Mage.Sets/src/mage/cards/t/ToothCollector.java +++ b/Mage.Sets/src/mage/cards/t/ToothCollector.java @@ -1,34 +1,36 @@ package mage.cards.t; -import java.util.UUID; - import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.DeliriumCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.*; +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.game.events.GameEvent; -import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * @author fireshoes */ public final class ToothCollector extends CardImpl { + private static final FilterPermanent filter = new FilterCreaturePermanent("creature that player controls"); + + static { + filter.add(TargetController.ACTIVE.getControllerPredicate()); + } + public ToothCollector(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); this.subtype.add(SubType.HUMAN); @@ -38,18 +40,16 @@ public final class ToothCollector extends CardImpl { // When Tooth Collector enters the battlefield, target creature an opponent controls gets -1/-1 until end of turn. Ability ability = new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(-1, -1, Duration.EndOfTurn)); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); // {Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard, // target creature that player controls gets -1/-1 until end of turn. - ability = new ConditionalInterveningIfTriggeredAbility( - new ToothCollectorAbility(), - DeliriumCondition.instance, - "Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard, " - + "target creature that player controls gets -1/-1 until end of turn."); - ability.addHint(CardTypesInGraveyardCount.YOU.getHint()); - this.addAbility(ability); + ability = new BeginningOfUpkeepTriggeredAbility( + TargetController.OPPONENT, new BoostTargetEffect(-1, -1), false + ).withInterveningIf(DeliriumCondition.instance); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability.setAbilityWord(AbilityWord.DELIRIUM).addHint(CardTypesInGraveyardCount.YOU.getHint())); } private ToothCollector(final ToothCollector card) { @@ -61,45 +61,3 @@ public final class ToothCollector extends CardImpl { return new ToothCollector(this); } } - -class ToothCollectorAbility extends TriggeredAbilityImpl { - - public ToothCollectorAbility() { - super(Zone.BATTLEFIELD, new BoostTargetEffect(-1, -1, Duration.EndOfTurn)); - } - - private ToothCollectorAbility(final ToothCollectorAbility ability) { - super(ability); - } - - @Override - public ToothCollectorAbility copy() { - return new ToothCollectorAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.UPKEEP_STEP_PRE; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (game.getOpponents(controllerId).contains(event.getPlayerId())) { - Player opponent = game.getPlayer(event.getPlayerId()); - if (opponent != null) { - FilterCreaturePermanent FILTER = new FilterCreaturePermanent("creature " + opponent.getLogName() + " controls"); - FILTER.add(new ControllerIdPredicate(opponent.getId())); - this.getTargets().clear(); - this.addTarget(new TargetCreaturePermanent(FILTER)); - return true; - } - } - return false; - } - - @Override - public String getRule() { - return "Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard, " - + "target creature that player controls gets -1/-1 until end of turn."; - } -} diff --git a/Mage.Sets/src/mage/cards/t/TopanAscetic.java b/Mage.Sets/src/mage/cards/t/TopanAscetic.java index 6343817994c..fd469d319a9 100644 --- a/Mage.Sets/src/mage/cards/t/TopanAscetic.java +++ b/Mage.Sets/src/mage/cards/t/TopanAscetic.java @@ -1,7 +1,5 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapTargetCost; @@ -9,27 +7,19 @@ import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.constants.SubType; +import mage.filter.StaticFilters; + +import java.util.UUID; /** - * * @author Plopman */ public final class TopanAscetic extends CardImpl { - - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); - static{ - filter.add(TappedPredicate.UNTAPPED); - } - public TopanAscetic(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.MONK); @@ -37,7 +27,10 @@ public final class TopanAscetic extends CardImpl { this.toughness = new MageInt(2); // Tap an untapped creature you control: Topan Ascetic gets +1/+1 until end of turn. - this.addAbility(new SimpleActivatedAbility(new BoostSourceEffect(1, 1, Duration.EndOfTurn), new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, true)))); + this.addAbility(new SimpleActivatedAbility( + new BoostSourceEffect(1, 1, Duration.EndOfTurn), + new TapTargetCost(StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURE) + )); } private TopanAscetic(final TopanAscetic card) { diff --git a/Mage.Sets/src/mage/cards/t/Topple.java b/Mage.Sets/src/mage/cards/t/Topple.java index b5c3d5eb9c9..04b93b63c86 100644 --- a/Mage.Sets/src/mage/cards/t/Topple.java +++ b/Mage.Sets/src/mage/cards/t/Topple.java @@ -1,18 +1,18 @@ package mage.cards.t; -import mage.MageObject; -import mage.abilities.Ability; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.ExileTargetEffect; 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.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; -import java.util.HashSet; -import java.util.List; -import java.util.Set; import java.util.UUID; /** @@ -20,12 +20,19 @@ import java.util.UUID; */ public final class Topple extends CardImpl { + private static final FilterPermanent filter + = new FilterCreaturePermanent("creature with the greatest power among creatures on the battlefield"); + + static { + filter.add(TopplePredicate.instance); + } + public Topple(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{W}"); // Exile target creature with the greatest power among creatures on the battlefield. this.getSpellAbility().addEffect(new ExileTargetEffect()); - this.getSpellAbility().addTarget(new ToppleTargetCreature()); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private Topple(final Topple card) { @@ -38,65 +45,12 @@ public final class Topple extends CardImpl { } } -class ToppleTargetCreature extends TargetCreaturePermanent { - - public ToppleTargetCreature() { - super(); - withTargetName("creature with the greatest power among creatures on the battlefield"); - } - - private ToppleTargetCreature(final ToppleTargetCreature target) { - super(target); - } +enum TopplePredicate implements ObjectSourcePlayerPredicate { + instance; @Override - public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) { - if (super.canTarget(controllerId, id, source, game)) { - int maxPower = 0; - for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { - if (permanent.getPower().getValue() > maxPower) { - maxPower = permanent.getPower().getValue(); - } - } - Permanent targetPermanent = game.getPermanent(id); - if (targetPermanent != null) { - return targetPermanent.getPower().getValue() == maxPower; - } - } - return false; - } - - @Override - public Set possibleTargets(UUID sourceControllerId, Ability source, Game game) { - int maxPower = 0; - List activePermanents = game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game); - Set possibleTargets = new HashSet<>(); - MageObject targetSource = game.getObject(source); - if (targetSource == null) { - return possibleTargets; - } - for (Permanent permanent : activePermanents) { - if (permanent.getPower().getValue() > maxPower) { - maxPower = permanent.getPower().getValue(); - } - } - for (Permanent permanent : activePermanents) { - if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)) { - if (permanent.getPower().getValue() == maxPower) { - possibleTargets.add(permanent.getId()); - } - } - } - return possibleTargets; - } - - @Override - public boolean canChoose(UUID sourceControllerId, Ability source, Game game) { - return !possibleTargets(sourceControllerId, source, game).isEmpty(); - } - - @Override - public ToppleTargetCreature copy() { - return new ToppleTargetCreature(this); + public boolean apply(ObjectSourcePlayer input, Game game) { + return input.getObject().getPower().getValue() + >= GreatestAmongPermanentsValue.POWER_ALL_CREATURES.calculate(game, input.getSource(), null); } } diff --git a/Mage.Sets/src/mage/cards/t/Topplegeist.java b/Mage.Sets/src/mage/cards/t/Topplegeist.java index c7123946614..fc2727d38c3 100644 --- a/Mage.Sets/src/mage/cards/t/Topplegeist.java +++ b/Mage.Sets/src/mage/cards/t/Topplegeist.java @@ -1,34 +1,40 @@ package mage.cards.t; -import java.util.UUID; - import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.DeliriumCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.keyword.FlyingAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.constants.TargetController; +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.game.events.GameEvent; -import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * @author fireshoes */ public final class Topplegeist extends CardImpl { + private static final FilterPermanent filter = new FilterCreaturePermanent("creature that player controls"); + + static { + filter.add(TargetController.ACTIVE.getControllerPredicate()); + } + public Topplegeist(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}"); this.subtype.add(SubType.SPIRIT); @@ -40,18 +46,15 @@ public final class Topplegeist extends CardImpl { // When Topplegeist enters the battlefield, tap target creature an opponent controls. Ability ability = new EntersBattlefieldTriggeredAbility(new TapTargetEffect()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); // Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard, // tap target creature that player controls. - ability = new ConditionalInterveningIfTriggeredAbility( - new TopplegeistAbility(), - DeliriumCondition.instance, - "Delirium — At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard, " - + "tap target creature that player controls."); - ability.addHint(CardTypesInGraveyardCount.YOU.getHint()); - this.addAbility(ability); + ability = new BeginningOfUpkeepTriggeredAbility(TargetController.OPPONENT, new TapTargetEffect(), false) + .withInterveningIf(DeliriumCondition.instance); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability.setAbilityWord(AbilityWord.DELIRIUM).addHint(CardTypesInGraveyardCount.YOU.getHint())); } private Topplegeist(final Topplegeist card) { @@ -63,44 +66,3 @@ public final class Topplegeist extends CardImpl { return new Topplegeist(this); } } - -class TopplegeistAbility extends TriggeredAbilityImpl { - - public TopplegeistAbility() { - super(Zone.BATTLEFIELD, new TapTargetEffect()); - } - - private TopplegeistAbility(final TopplegeistAbility ability) { - super(ability); - } - - @Override - public TopplegeistAbility copy() { - return new TopplegeistAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.UPKEEP_STEP_PRE; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (game.getOpponents(controllerId).contains(event.getPlayerId())) { - Player opponent = game.getPlayer(event.getPlayerId()); - if (opponent != null) { - FilterCreaturePermanent FILTER = new FilterCreaturePermanent("creature " + opponent.getLogName() + " controls"); - FILTER.add(new ControllerIdPredicate(opponent.getId())); - this.getTargets().clear(); - this.addTarget(new TargetCreaturePermanent(FILTER)); - return true; - } - } - return false; - } - - @Override - public String getRule() { - return "At the beginning of each opponent's upkeep, if there are four or more card types among cards in your graveyard, tap target creature that player controls."; - } -} diff --git a/Mage.Sets/src/mage/cards/t/ToralfGodOfFury.java b/Mage.Sets/src/mage/cards/t/ToralfGodOfFury.java index 74aee9a3904..3c697cd96e6 100644 --- a/Mage.Sets/src/mage/cards/t/ToralfGodOfFury.java +++ b/Mage.Sets/src/mage/cards/t/ToralfGodOfFury.java @@ -35,6 +35,7 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetAnyTarget; import mage.target.common.TargetPermanentOrPlayer; +import mage.target.targetadjustment.DefineByTriggerTargetAdjuster; import java.util.UUID; @@ -98,6 +99,7 @@ class ToralfGodOfFuryTriggeredAbility extends TriggeredAbilityImpl implements Ba ToralfGodOfFuryTriggeredAbility() { super(Zone.BATTLEFIELD, null); + this.setTargetAdjuster(DefineByTriggerTargetAdjuster.instance); } private ToralfGodOfFuryTriggeredAbility(final ToralfGodOfFuryTriggeredAbility ability) { diff --git a/Mage.Sets/src/mage/cards/t/TorchSlinger.java b/Mage.Sets/src/mage/cards/t/TorchSlinger.java index 8baa54da394..5f7114699bb 100644 --- a/Mage.Sets/src/mage/cards/t/TorchSlinger.java +++ b/Mage.Sets/src/mage/cards/t/TorchSlinger.java @@ -1,11 +1,9 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -14,14 +12,15 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author North */ public final class TorchSlinger extends CardImpl { public TorchSlinger(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); this.subtype.add(SubType.GOBLIN); this.subtype.add(SubType.SHAMAN); @@ -31,11 +30,10 @@ public final class TorchSlinger extends CardImpl { // Kicker {1}{R} (You may pay an additional {1}{R} as you cast this spell.) this.addAbility(new KickerAbility("{1}{R}")); - // When Torch Slinger enters the battlefield, if it was kicked, it deals 2 damage to target creature. - EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2), false); + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(2, "it")).withInterveningIf(KickedCondition.ONCE); ability.addTarget(new TargetCreaturePermanent()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.ONCE, "When {this} enters, if it was kicked, it deals 2 damage to target creature.")); + this.addAbility(ability); } private TorchSlinger(final TorchSlinger card) { diff --git a/Mage.Sets/src/mage/cards/t/TotentanzSwarmPiper.java b/Mage.Sets/src/mage/cards/t/TotentanzSwarmPiper.java index ecbbdf204c0..b3104dc78ef 100644 --- a/Mage.Sets/src/mage/cards/t/TotentanzSwarmPiper.java +++ b/Mage.Sets/src/mage/cards/t/TotentanzSwarmPiper.java @@ -18,7 +18,7 @@ import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.permanent.AttackingPredicate; import mage.game.permanent.token.RatCantBlockToken; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -55,7 +55,7 @@ public final class TotentanzSwarmPiper extends CardImpl { new GainAbilityTargetEffect(DeathtouchAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{1}{B}") ); - ability.addTarget(new TargetControlledCreaturePermanent(filterRat)); + ability.addTarget(new TargetPermanent(filterRat)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TourachDreadCantor.java b/Mage.Sets/src/mage/cards/t/TourachDreadCantor.java index 4b7288f163b..ae65816330d 100644 --- a/Mage.Sets/src/mage/cards/t/TourachDreadCantor.java +++ b/Mage.Sets/src/mage/cards/t/TourachDreadCantor.java @@ -6,7 +6,6 @@ import mage.abilities.Ability; import mage.abilities.common.DiscardsACardOpponentTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.abilities.keyword.KickerAbility; @@ -47,11 +46,7 @@ public final class TourachDreadCantor extends CardImpl { )); // When Tourach enters the battelfield, if it was kicked, target opponent discards two cards at random. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(2, true)), - KickedCondition.ONCE, "When {this} enters, if it was kicked, " + - "target opponent discards two cards at random." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new DiscardTargetEffect(2, true)).withInterveningIf(KickedCondition.ONCE); ability.addTarget(new TargetOpponent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TourachsGate.java b/Mage.Sets/src/mage/cards/t/TourachsGate.java index b59271eef10..fe8268f12f0 100644 --- a/Mage.Sets/src/mage/cards/t/TourachsGate.java +++ b/Mage.Sets/src/mage/cards/t/TourachsGate.java @@ -1,85 +1,84 @@ package mage.cards.t; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.AttachedToMatchesFilterCondition; -import mage.abilities.costs.Cost; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.common.TapAttachedCost; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.SacrificeSourceEffect; import mage.abilities.effects.common.continuous.BoostAllEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; -import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; import mage.abilities.keyword.EnchantAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.Outcome; -import mage.constants.Duration; -import mage.constants.TargetController; -import mage.constants.Zone; +import mage.constants.*; import mage.counters.CounterType; import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.AttackingPredicate; import mage.filter.predicate.permanent.TappedPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; import mage.target.TargetPermanent; -import mage.target.common.TargetControlledPermanent; + +import java.util.UUID; /** - * * @author L_J */ public final class TourachsGate extends CardImpl { - private static final FilterControlledPermanent filterLand = new FilterControlledPermanent("land you control"); - static { - filterLand.add(CardType.LAND.getPredicate()); - } - - private static final FilterPermanent filterUntapped = new FilterPermanent("enchanted land is untapped"); - static { - filterUntapped.add(TappedPredicate.UNTAPPED); - } - private static final FilterCreaturePermanent filterAttackingCreatures = new FilterCreaturePermanent("attacking creatures you control"); + private static final FilterPermanent filterUntapped = new FilterPermanent("enchanted land is untapped"); + private static final FilterControlledPermanent filterThrull = new FilterControlledPermanent(SubType.THRULL, "a Thrull"); + static { filterAttackingCreatures.add(AttackingPredicate.instance); filterAttackingCreatures.add(TargetController.YOU.getControllerPredicate()); + filterUntapped.add(TappedPredicate.UNTAPPED); } - private static final FilterControlledPermanent filterThrull = new FilterControlledPermanent(SubType.THRULL, "a Thrull"); + private static final Condition condition = new SourceHasCounterCondition(CounterType.TIME, ComparisonType.EQUAL_TO, 0); + private static final Condition condition2 = new AttachedToMatchesFilterCondition(filterUntapped); public TourachsGate(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}{B}"); this.subtype.add(SubType.AURA); // Enchant land you control - TargetPermanent auraTarget = new TargetControlledPermanent(filterLand); + TargetPermanent auraTarget = new TargetPermanent(StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.AddAbility)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // Sacrifice a Thrull: Put three time counters on Tourach's Gate. - this.addAbility(new SimpleActivatedAbility(new AddCountersSourceEffect(CounterType.TIME.createInstance(3)), - new SacrificeTargetCost(filterThrull))); - + this.addAbility(new SimpleActivatedAbility( + new AddCountersSourceEffect(CounterType.TIME.createInstance(3)), + new SacrificeTargetCost(filterThrull) + )); + // At the beginning of your upkeep, remove a time counter from Tourach's Gate. If there are no time counters on Tourach's Gate, sacrifice it. - this.addAbility(new BeginningOfUpkeepTriggeredAbility(new TourachsGateUpkeepEffect())); + Ability ability = new BeginningOfUpkeepTriggeredAbility( + new RemoveCounterSourceEffect(CounterType.TIME.createInstance()) + ); + ability.addEffect(new ConditionalOneShotEffect( + new SacrificeSourceEffect(), condition, + "If there are no time counters on {this}, sacrifice it" + )); + this.addAbility(ability); // Tap enchanted land: Attacking creatures you control get +2/-1 until end of turn. Activate this ability only if enchanted land is untapped. - Cost cost = new TapAttachedCost(); - cost.setText("Tap enchanted land"); - this.addAbility(new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new BoostAllEffect(2, -1, Duration.EndOfTurn, filterAttackingCreatures, false), - cost, new AttachedToMatchesFilterCondition(filterUntapped))); + this.addAbility(new ActivateIfConditionActivatedAbility(new BoostAllEffect( + 2, -1, Duration.EndOfTurn, + filterAttackingCreatures, false + ), new TapAttachedCost().setText("tap enchanted land"), condition2)); } private TourachsGate(final TourachsGate card) { @@ -91,38 +90,3 @@ public final class TourachsGate extends CardImpl { return new TourachsGate(this); } } - -class TourachsGateUpkeepEffect extends OneShotEffect { - - TourachsGateUpkeepEffect() { - super(Outcome.Sacrifice); - staticText = "remove a time counter from {this}. If there are no time counters on {this}, sacrifice it"; - } - - private TourachsGateUpkeepEffect(final TourachsGateUpkeepEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - int amount = permanent.getCounters(game).getCount(CounterType.TIME); - if (amount > 0) { - permanent.removeCounters(CounterType.TIME.createInstance(), source, game); - } - // is supposed to function similar to Vanishing - amount = permanent.getCounters(game).getCount(CounterType.TIME); - if (amount == 0) { - permanent.sacrifice(source, game); - } - return true; - } - return false; - } - - @Override - public TourachsGateUpkeepEffect copy() { - return new TourachsGateUpkeepEffect(this); - } -} diff --git a/Mage.Sets/src/mage/cards/t/TovolarDireOverlord.java b/Mage.Sets/src/mage/cards/t/TovolarDireOverlord.java index caed280491a..38c837a9a2b 100644 --- a/Mage.Sets/src/mage/cards/t/TovolarDireOverlord.java +++ b/Mage.Sets/src/mage/cards/t/TovolarDireOverlord.java @@ -2,17 +2,16 @@ package mage.cards.t; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.hint.Hint; import mage.abilities.hint.ValueHint; import mage.abilities.keyword.DayboundAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -31,7 +30,7 @@ import java.util.UUID; */ public final class TovolarDireOverlord extends CardImpl { - private static final FilterPermanent filter = new FilterControlledPermanent("a Wolf or Werewolf you control"); + private static final FilterPermanent filter = new FilterControlledPermanent("you control three or more Wolves and/or Werewolves"); static { filter.add(Predicates.or( @@ -57,15 +56,10 @@ public final class TovolarDireOverlord extends CardImpl { this.addAbility(new DealsDamageToAPlayerAllTriggeredAbility( new DrawCardSourceControllerEffect(1), filter, false, SetTargetPointer.NONE, true - )); + ).setTriggerPhrase("Whenever a Wolf or Werewolf you control deals combat damage to a player, ")); // At the beginning of your upkeep, if you control three or more Wolves and/or Werewolves, it becomes night. Then transform any number of Human Werewolves you control. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility( - new TovolarDireOverlordEffect(), false - ), condition, "At the beginning of your upkeep, if you control three or more Wolves " + - "and/or Werewolves, it becomes night. Then transform any number of Human Werewolves you control." - )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new TovolarDireOverlordEffect()).withInterveningIf(condition).addHint(hint)); // Daybound this.addAbility(new DayboundAbility()); @@ -92,6 +86,7 @@ class TovolarDireOverlordEffect extends OneShotEffect { TovolarDireOverlordEffect() { super(Outcome.Benefit); + staticText = "it becomes night. Then transform any number of Human Werewolves you control"; } private TovolarDireOverlordEffect(final TovolarDireOverlordEffect effect) { diff --git a/Mage.Sets/src/mage/cards/t/TownGossipmonger.java b/Mage.Sets/src/mage/cards/t/TownGossipmonger.java index 50cbd67ab97..1ebe153eed6 100644 --- a/Mage.Sets/src/mage/cards/t/TownGossipmonger.java +++ b/Mage.Sets/src/mage/cards/t/TownGossipmonger.java @@ -1,8 +1,5 @@ - package mage.cards.t; -import java.util.UUID; - import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -14,22 +11,15 @@ 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.permanent.TappedPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.filter.StaticFilters; + +import java.util.UUID; /** * @author escplan9 (Derek Monturo - dmontur1 at gmail dot com) */ public final class TownGossipmonger extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creature you control"); - - static { - filter.add(TappedPredicate.UNTAPPED); - } - public TownGossipmonger(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}"); this.subtype.add(SubType.HUMAN); @@ -41,7 +31,7 @@ public final class TownGossipmonger extends CardImpl { // {T}, Tap an untapped creature you control: Transform Town Gossipmonger. this.addAbility(new TransformAbility()); Ability ability = new SimpleActivatedAbility(new TransformSourceEffect(), new TapSourceCost()); - ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, true))); + ability.addCost(new TapTargetCost(StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/ToxicStench.java b/Mage.Sets/src/mage/cards/t/ToxicStench.java index 444de87702e..3749e340633 100644 --- a/Mage.Sets/src/mage/cards/t/ToxicStench.java +++ b/Mage.Sets/src/mage/cards/t/ToxicStench.java @@ -10,10 +10,13 @@ import mage.cards.CardSetInfo; import mage.constants.AbilityWord; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * @author TheElk801 */ @@ -31,7 +34,7 @@ public final class ToxicStench extends CardImpl { AbilityWord.THRESHOLD.formatWord() + "If seven or more cards are in your graveyard, " + "instead destroy that creature. It can't be regenerated." )); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); } private ToxicStench(final ToxicStench card) { diff --git a/Mage.Sets/src/mage/cards/t/TradeCaravan.java b/Mage.Sets/src/mage/cards/t/TradeCaravan.java index a5d4e318f70..3205bd8e757 100644 --- a/Mage.Sets/src/mage/cards/t/TradeCaravan.java +++ b/Mage.Sets/src/mage/cards/t/TradeCaravan.java @@ -1,30 +1,29 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.CompoundCondition; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.condition.common.OnOpponentsTurnCondition; -import mage.abilities.decorator.ConditionalActivatedAbility; import mage.abilities.costs.common.RemoveCountersSourceCost; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.PhaseStep; +import mage.constants.SubType; import mage.constants.SuperType; -import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.common.FilterLandPermanent; import mage.target.TargetPermanent; +import java.util.UUID; + /** - * * @author L_J */ public final class TradeCaravan extends CardImpl { @@ -35,8 +34,14 @@ public final class TradeCaravan extends CardImpl { filter.add(SuperType.BASIC.getPredicate()); } + private static final Condition condition = new CompoundCondition( + "during an opponent's upkeep", + OnOpponentsTurnCondition.instance, + new IsStepCondition(PhaseStep.UPKEEP, false) + ); + public TradeCaravan(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.NOMAD); this.power = new MageInt(1); @@ -44,10 +49,11 @@ public final class TradeCaravan extends CardImpl { // At the beginning of your upkeep, put a currency counter on Trade Caravan. this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.CURRENCY.createInstance()))); + // Remove two currency counters from Trade Caravan: Untap target basic land. Activate this ability only during an opponent's upkeep. - Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new UntapTargetEffect(), new RemoveCountersSourceCost(CounterType.CURRENCY.createInstance(2)), - new CompoundCondition(OnOpponentsTurnCondition.instance, new IsStepCondition(PhaseStep.UPKEEP, false)), - "Remove two currency counters from {this}: Untap target basic land. Activate only during an opponent's upkeep."); + Ability ability = new ActivateIfConditionActivatedAbility( + new UntapTargetEffect(), new RemoveCountersSourceCost(CounterType.CURRENCY.createInstance(2)), condition + ); ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TradewindRider.java b/Mage.Sets/src/mage/cards/t/TradewindRider.java index f4263b54f89..652ef4bf5ad 100644 --- a/Mage.Sets/src/mage/cards/t/TradewindRider.java +++ b/Mage.Sets/src/mage/cards/t/TradewindRider.java @@ -1,7 +1,5 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -13,32 +11,27 @@ 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.permanent.TappedPredicate; +import mage.filter.StaticFilters; import mage.target.TargetPermanent; -import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; /** * @author Loki */ public final class TradewindRider extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped creatures you control"); - - static { - filter.add(TappedPredicate.UNTAPPED); - } - public TradewindRider(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); this.subtype.add(SubType.SPIRIT); this.power = new MageInt(1); this.toughness = new MageInt(4); + this.addAbility(FlyingAbility.getInstance()); + Ability ability = new SimpleActivatedAbility(new ReturnToHandTargetEffect(), new TapSourceCost()); - ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(2, 2, filter, false))); + ability.addCost(new TapTargetCost(2, StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURES)); ability.addTarget(new TargetPermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TraitorsRoar.java b/Mage.Sets/src/mage/cards/t/TraitorsRoar.java index 7b300ac518c..85f3c87571d 100644 --- a/Mage.Sets/src/mage/cards/t/TraitorsRoar.java +++ b/Mage.Sets/src/mage/cards/t/TraitorsRoar.java @@ -12,6 +12,7 @@ import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -31,7 +32,7 @@ public final class TraitorsRoar extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{B/R}"); // Tap target untapped creature. It deals damage equal to its power to its controller. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new TraitorsRoarEffect()); // Conspire diff --git a/Mage.Sets/src/mage/cards/t/Transpose.java b/Mage.Sets/src/mage/cards/t/Transpose.java index fd6a36e7dad..4f1c970d57b 100644 --- a/Mage.Sets/src/mage/cards/t/Transpose.java +++ b/Mage.Sets/src/mage/cards/t/Transpose.java @@ -57,7 +57,7 @@ enum TransposeCondition implements Condition { .map(Ability::getSourceId) .map(game::getSpell) .map(Spell::getFromZone) - .map(Zone.GRAVEYARD::match) + .map(Zone.HAND::match) .orElse(false); } diff --git a/Mage.Sets/src/mage/cards/t/TrapRunner.java b/Mage.Sets/src/mage/cards/t/TrapRunner.java index 1b009185d0f..b51e145b59d 100644 --- a/Mage.Sets/src/mage/cards/t/TrapRunner.java +++ b/Mage.Sets/src/mage/cards/t/TrapRunner.java @@ -7,18 +7,18 @@ import mage.abilities.condition.Condition; import mage.abilities.condition.common.AfterBlockersAreDeclaredCondition; import mage.abilities.condition.common.IsPhaseCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.BecomeBlockedTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.TurnPhase; -import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.AttackingPredicate; import mage.filter.predicate.permanent.BlockedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -50,10 +50,8 @@ public final class TrapRunner extends CardImpl { this.toughness = new MageInt(3); // {T}: Target unblocked attacking creature becomes blocked. Activate this ability only during combat after blockers are declared. - Ability ability = new ConditionalActivatedAbility( - Zone.BATTLEFIELD, new BecomeBlockedTargetEffect(), new TapSourceCost(), condition - ); - ability.addTarget(new TargetCreaturePermanent(filter)); + Ability ability = new ActivateIfConditionActivatedAbility(new BecomeBlockedTargetEffect(), new TapSourceCost(), condition); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TrenzaloreClocktower.java b/Mage.Sets/src/mage/cards/t/TrenzaloreClocktower.java index 6117c0403a5..734c2d9430e 100644 --- a/Mage.Sets/src/mage/cards/t/TrenzaloreClocktower.java +++ b/Mage.Sets/src/mage/cards/t/TrenzaloreClocktower.java @@ -8,7 +8,7 @@ import mage.abilities.costs.common.ExileSourceCost; import mage.abilities.costs.common.RemoveCountersSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -47,7 +47,7 @@ public final class TrenzaloreClocktower extends CardImpl { // {1}{U}, {T}, Remove twelve time counters from Trenzalore Clocktower and exile it: // Shuffle your graveyard and hand into your library, then draw seven cards. // Activate only if you control a Time Lord. - Ability wheelAbility = new ConditionalActivatedAbility( + Ability wheelAbility = new ActivateIfConditionActivatedAbility( new TrenzaloreClocktowerEffect(), new ManaCostsImpl<>("{1}{U}"), new PermanentsOnTheBattlefieldCondition(filter)); diff --git a/Mage.Sets/src/mage/cards/t/TriadOfFates.java b/Mage.Sets/src/mage/cards/t/TriadOfFates.java index 7018bf840ce..aefb03653b0 100644 --- a/Mage.Sets/src/mage/cards/t/TriadOfFates.java +++ b/Mage.Sets/src/mage/cards/t/TriadOfFates.java @@ -16,10 +16,13 @@ import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * @author LevelX2 */ @@ -43,21 +46,21 @@ public final class TriadOfFates extends CardImpl { // {1}, {T}: Put a fate counter on another target creature. Ability ability = new SimpleActivatedAbility(new AddCountersTargetEffect(CounterType.FATE.createInstance()), new ManaCostsImpl<>("{1}")); ability.addCost(new TapSourceCost()); - Target target = new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE); + Target target = new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE); ability.addTarget(target); this.addAbility(ability); // {W}, {T}: Exile target creature that has a fate counter on it, then return it to the battlefield under its owner's control. ability = new SimpleActivatedAbility(new ExileThenReturnTargetEffect(false, false), new ManaCostsImpl<>("{W}")); ability.addCost(new TapSourceCost()); - target = new TargetCreaturePermanent(filterCounter); + target = new TargetPermanent(filterCounter); ability.addTarget(target); this.addAbility(ability); // {B}, {T}: Exile target creature that has a fate counter on it. Its controller draws two cards. ability = new SimpleActivatedAbility(new ExileTargetEffect(), new ManaCostsImpl<>("{B}")); ability.addCost(new TapSourceCost()); - target = new TargetCreaturePermanent(filterCounter); + target = new TargetPermanent(filterCounter); ability.addTarget(target); ability.addEffect(new DrawCardTargetControllerEffect(2)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/t/TriangleOfWar.java b/Mage.Sets/src/mage/cards/t/TriangleOfWar.java index 00161dbaaf4..71aefc637b4 100644 --- a/Mage.Sets/src/mage/cards/t/TriangleOfWar.java +++ b/Mage.Sets/src/mage/cards/t/TriangleOfWar.java @@ -12,9 +12,12 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author fireshoes @@ -30,7 +33,7 @@ public final class TriangleOfWar extends CardImpl { new ManaCostsImpl<>("{2}")); ability.addCost(new SacrificeSourceCost()); ability.addTarget(new TargetControlledCreaturePermanent()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TriassicEgg.java b/Mage.Sets/src/mage/cards/t/TriassicEgg.java index efb88ddb034..ee831518ef7 100644 --- a/Mage.Sets/src/mage/cards/t/TriassicEgg.java +++ b/Mage.Sets/src/mage/cards/t/TriassicEgg.java @@ -8,7 +8,7 @@ import mage.abilities.condition.common.SourceHasCounterCondition; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.PutCardFromHandOntoBattlefieldEffect; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -39,7 +39,7 @@ public final class TriassicEgg extends CardImpl { this.addAbility(ability); // Sacrifice Triassic Egg: Choose one - You may put a creature card from your hand onto the battlefield; - ability = new ConditionalActivatedAbility( + ability = new ActivateIfConditionActivatedAbility( new PutCardFromHandOntoBattlefieldEffect(StaticFilters.FILTER_CARD_CREATURE_A), new SacrificeSourceCost(), condition ).hideCondition(); diff --git a/Mage.Sets/src/mage/cards/t/TrickShot.java b/Mage.Sets/src/mage/cards/t/TrickShot.java index 8bf34ed7989..9eeb2b6385f 100644 --- a/Mage.Sets/src/mage/cards/t/TrickShot.java +++ b/Mage.Sets/src/mage/cards/t/TrickShot.java @@ -7,6 +7,7 @@ import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.other.AnotherTargetPredicate; import mage.filter.predicate.permanent.TokenPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.SecondTargetPointer; @@ -29,7 +30,7 @@ public final class TrickShot extends CardImpl { // Trick Shot deals 6 damage to target creature and 2 damage to up to one other target creature token. this.getSpellAbility().addTarget(new TargetCreaturePermanent().setTargetTag(1)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 1, filter, false).setTargetTag(2)); + this.getSpellAbility().addTarget(new TargetPermanent(0, 1, filter).setTargetTag(2)); this.getSpellAbility().addEffect(new DamageTargetEffect(6, true, "", true)); this.getSpellAbility().addEffect( new DamageTargetEffect(2, true, "", true) diff --git a/Mage.Sets/src/mage/cards/t/TripWire.java b/Mage.Sets/src/mage/cards/t/TripWire.java index bdaa8cd194b..702896736fb 100644 --- a/Mage.Sets/src/mage/cards/t/TripWire.java +++ b/Mage.Sets/src/mage/cards/t/TripWire.java @@ -9,6 +9,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -26,7 +27,7 @@ public final class TripWire extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{G}"); // Destroy target creature with horsemanship. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); } diff --git a/Mage.Sets/src/mage/cards/t/Triskaidekaphile.java b/Mage.Sets/src/mage/cards/t/Triskaidekaphile.java index 4ba44009dff..fcd7a5df6fa 100644 --- a/Mage.Sets/src/mage/cards/t/Triskaidekaphile.java +++ b/Mage.Sets/src/mage/cards/t/Triskaidekaphile.java @@ -1,19 +1,21 @@ package mage.cards.t; import mage.MageInt; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInHandCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.WinGameSourceControllerEffect; import mage.abilities.effects.common.continuous.MaximumHandSizeControllerEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.Duration; +import mage.constants.SubType; import java.util.UUID; @@ -39,12 +41,7 @@ public final class Triskaidekaphile extends CardImpl { ))); // At the beginning of your upkeep, if you have exactly thirteen cards in your hand, you win the game. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility( - new WinGameSourceControllerEffect(), false - ), condition, "At the beginning of your upkeep, " + - "if you have exactly thirteen cards in your hand, you win the game." - )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new WinGameSourceControllerEffect()).withInterveningIf(condition)); // {3}{U}: Draw a card. this.addAbility(new SimpleActivatedAbility( diff --git a/Mage.Sets/src/mage/cards/t/Triskaidekaphobia.java b/Mage.Sets/src/mage/cards/t/Triskaidekaphobia.java index 56990c197fb..b85a311c838 100644 --- a/Mage.Sets/src/mage/cards/t/Triskaidekaphobia.java +++ b/Mage.Sets/src/mage/cards/t/Triskaidekaphobia.java @@ -1,33 +1,34 @@ - package mage.cards.t; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.Mode; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.GainLifeAllEffect; +import mage.abilities.effects.common.LoseLifeAllPlayersEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.players.PlayerList; + +import java.util.UUID; /** - * * @author fireshoes */ public final class Triskaidekaphobia extends CardImpl { public Triskaidekaphobia(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}"); // At the beginning of your upkeep, choose one - Each player with exactly 13 life loses the game, then each player gains 1 life. // Each player with exactly 13 life loses the game, then each player loses 1 life. Ability ability = new BeginningOfUpkeepTriggeredAbility(new TriskaidekaphobiaGainLifeEffect()); - Mode mode = new Mode(new TriskaidekaphobiaLoseLifeEffect()); - ability.addMode(mode); + ability.addEffect(new GainLifeAllEffect(1).concatBy(", then")); + ability.addMode(new Mode(new TriskaidekaphobiaGainLifeEffect()) + .addEffect(new LoseLifeAllPlayersEffect(1).concatBy(", then"))); this.addAbility(ability); } @@ -45,7 +46,7 @@ class TriskaidekaphobiaGainLifeEffect extends OneShotEffect { TriskaidekaphobiaGainLifeEffect() { super(Outcome.Neutral); - this.staticText = "Each player with exactly 13 life loses the game, then each player gains 1 life"; + this.staticText = "each player with exactly 13 life loses the game"; } private TriskaidekaphobiaGainLifeEffect(final TriskaidekaphobiaGainLifeEffect effect) { @@ -59,60 +60,10 @@ class TriskaidekaphobiaGainLifeEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - int life; - PlayerList playerList = game.getState().getPlayersInRange(source.getControllerId(), game); - for (UUID pid : playerList) { - Player player = game.getPlayer(pid); - if (player != null) { - life = player.getLife(); - if (life == 13) { - player.lost(game); - } - } - } - for (UUID pid : playerList) { - Player player = game.getPlayer(pid); - if (player != null) { - player.gainLife(1, game, source); - } - } - return true; - } -} - -class TriskaidekaphobiaLoseLifeEffect extends OneShotEffect { - - TriskaidekaphobiaLoseLifeEffect() { - super(Outcome.Neutral); - this.staticText = "Each player with exactly 13 life loses the game, then each player loses 1 life"; - } - - private TriskaidekaphobiaLoseLifeEffect(final TriskaidekaphobiaLoseLifeEffect effect) { - super(effect); - } - - @Override - public TriskaidekaphobiaLoseLifeEffect copy() { - return new TriskaidekaphobiaLoseLifeEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - int life; - PlayerList playerList = game.getState().getPlayersInRange(source.getControllerId(), game); - for (UUID pid : playerList) { - Player player = game.getPlayer(pid); - if (player != null) { - life = player.getLife(); - if (life == 13) { - player.lost(game); - } - } - } - for (UUID pid : playerList) { - Player player = game.getPlayer(pid); - if (player != null) { - player.loseLife(1, game, source, false); + for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null && player.getLife() == 13) { + player.lost(game); } } return true; diff --git a/Mage.Sets/src/mage/cards/t/TrollsOfTelJilad.java b/Mage.Sets/src/mage/cards/t/TrollsOfTelJilad.java index 157c8e61170..36f1de7621b 100644 --- a/Mage.Sets/src/mage/cards/t/TrollsOfTelJilad.java +++ b/Mage.Sets/src/mage/cards/t/TrollsOfTelJilad.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -37,7 +38,7 @@ public final class TrollsOfTelJilad extends CardImpl { this.power = new MageInt(5); this.toughness = new MageInt(6); Ability ability = new SimpleActivatedAbility(new RegenerateTargetEffect(), new ManaCostsImpl<>("{1}{G}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TrophyHunter.java b/Mage.Sets/src/mage/cards/t/TrophyHunter.java index 2c1fd9962de..260be60922e 100644 --- a/Mage.Sets/src/mage/cards/t/TrophyHunter.java +++ b/Mage.Sets/src/mage/cards/t/TrophyHunter.java @@ -17,6 +17,7 @@ import mage.constants.CardType; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -41,7 +42,7 @@ public final class TrophyHunter extends CardImpl { // {1}{G}: Trophy Hunter deals 1 damage to target creature with flying. Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(1), new ManaCostsImpl<>("{1}{G}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // Whenever a creature with flying dealt damage by Trophy Hunter this turn dies, put a +1/+1 counter on Trophy Hunter. diff --git a/Mage.Sets/src/mage/cards/t/TroublemakerOuphe.java b/Mage.Sets/src/mage/cards/t/TroublemakerOuphe.java index 942b154b3cc..f94ad556428 100644 --- a/Mage.Sets/src/mage/cards/t/TroublemakerOuphe.java +++ b/Mage.Sets/src/mage/cards/t/TroublemakerOuphe.java @@ -1,10 +1,9 @@ package mage.cards.t; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.BargainedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.keyword.BargainAbility; import mage.cards.CardImpl; @@ -44,13 +43,10 @@ public final class TroublemakerOuphe extends CardImpl { this.addAbility(new BargainAbility()); // When Troublemaker Ouphe enters the battlefield, if it was bargained, exile target artifact or enchantment an opponent controls. - TriggeredAbility trigger = new EntersBattlefieldTriggeredAbility(new ExileTargetEffect()); - trigger.addTarget(new TargetPermanent(filter)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - trigger, - BargainedCondition.instance, - "When {this} enters, if it was bargained, exile target artifact or enchantment an opponent controls." - )); + Ability ability = new EntersBattlefieldTriggeredAbility(new ExileTargetEffect()) + .withInterveningIf(BargainedCondition.instance); + ability.addTarget(new TargetPermanent(filter)); + this.addAbility(ability); } private TroublemakerOuphe(final TroublemakerOuphe card) { diff --git a/Mage.Sets/src/mage/cards/t/TsaboTavoc.java b/Mage.Sets/src/mage/cards/t/TsaboTavoc.java index 3d86fcb903b..68f4d62a453 100644 --- a/Mage.Sets/src/mage/cards/t/TsaboTavoc.java +++ b/Mage.Sets/src/mage/cards/t/TsaboTavoc.java @@ -17,6 +17,7 @@ import mage.constants.SubType; import mage.constants.SuperType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -49,7 +50,7 @@ public final class TsaboTavoc extends CardImpl { // {B}{B}, {tap}: Destroy target legendary creature. It can't be regenerated. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(true), new ManaCostsImpl<>("{B}{B}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filterDestroy)); + ability.addTarget(new TargetPermanent(filterDestroy)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TurretOgre.java b/Mage.Sets/src/mage/cards/t/TurretOgre.java index a15969c8797..a3cdae59dda 100644 --- a/Mage.Sets/src/mage/cards/t/TurretOgre.java +++ b/Mage.Sets/src/mage/cards/t/TurretOgre.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamagePlayersEffect; import mage.abilities.keyword.ReachAbility; import mage.cards.CardImpl; @@ -15,8 +14,8 @@ import mage.constants.SubType; import mage.constants.TargetController; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.mageobject.PowerPredicate; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.predicate.mageobject.PowerPredicate; import java.util.UUID; @@ -25,7 +24,7 @@ import java.util.UUID; */ public final class TurretOgre extends CardImpl { - private static final FilterPermanent filter = new FilterControlledCreaturePermanent(); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("you control another creature with power 4 or greater"); static { filter.add(AnotherPredicate.instance); @@ -46,13 +45,7 @@ public final class TurretOgre extends CardImpl { this.addAbility(ReachAbility.getInstance()); // When Turret Ogre enters the battlefield, if you control another creature with power 4 or greater, Turret Ogre deals 2 damage to each opponent. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility( - new DamagePlayersEffect(2, TargetController.OPPONENT) - ), condition, "When {this} enters, " + - "if you control another creature with power 4 or greater, " + - "{this} deals 2 damage to each opponent." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new DamagePlayersEffect(2, TargetController.OPPONENT)).withInterveningIf(condition)); } private TurretOgre(final TurretOgre card) { diff --git a/Mage.Sets/src/mage/cards/t/Twigwalker.java b/Mage.Sets/src/mage/cards/t/Twigwalker.java index 3951117db70..423bbc45daa 100644 --- a/Mage.Sets/src/mage/cards/t/Twigwalker.java +++ b/Mage.Sets/src/mage/cards/t/Twigwalker.java @@ -1,22 +1,21 @@ package mage.cards.t; -import java.util.UUID; 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.effects.common.continuous.BoostTargetEffect; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.filter.StaticFilters; +import mage.constants.SubType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class Twigwalker extends CardImpl { @@ -31,7 +30,7 @@ public final class Twigwalker extends CardImpl { // {1}{G}, Sacrifice Twigwalker: Two target creatures each get +2/+2 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(2, 2, Duration.EndOfTurn), new ManaCostsImpl<>("{1}{G}")); ability.addCost(new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(2, 2, StaticFilters.FILTER_PERMANENT_CREATURES, false)); + ability.addTarget(new TargetCreaturePermanent(2)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TwilightProphet.java b/Mage.Sets/src/mage/cards/t/TwilightProphet.java index 565213a33fa..47bd0e0711b 100644 --- a/Mage.Sets/src/mage/cards/t/TwilightProphet.java +++ b/Mage.Sets/src/mage/cards/t/TwilightProphet.java @@ -3,19 +3,21 @@ package mage.cards.t; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.condition.common.CitysBlessingCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.LoseLifeOpponentsEffect; import mage.abilities.hint.common.CitysBlessingHint; import mage.abilities.keyword.AscendAbility; import mage.abilities.keyword.FlyingAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.cards.CardsImpl; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; import mage.game.Game; import mage.players.Player; @@ -42,12 +44,8 @@ public final class TwilightProphet extends CardImpl { // At the beginning of your upkeep, if you have the city's blessing, reveal the top card of your library and put it into your hand. // Each opponent loses X life and you gain X life, where X is that card's converted mana cost. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfUpkeepTriggeredAbility( - new TwilightProphetEffect()), CitysBlessingCondition.instance, - "At the beginning of your upkeep, if you have the city's blessing, reveal the top card of your library and put it into your hand. " - + "Each opponent loses X life and you gain X life, where X is that card's mana value.") - .addHint(CitysBlessingHint.instance)); - + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new TwilightProphetEffect()) + .withInterveningIf(CitysBlessingCondition.instance).addHint(CitysBlessingHint.instance)); } private TwilightProphet(final TwilightProphet card) { @@ -64,7 +62,7 @@ class TwilightProphetEffect extends OneShotEffect { TwilightProphetEffect() { super(Outcome.Benefit); - this.staticText = "if you have the city's blessing, reveal the top card of your library and put it into your hand. " + this.staticText = "reveal the top card of your library and put it into your hand. " + "Each opponent loses X life and you gain X life, where X is that card's mana value."; } diff --git a/Mage.Sets/src/mage/cards/t/Twinflame.java b/Mage.Sets/src/mage/cards/t/Twinflame.java index c733b4fa07c..725090855ca 100644 --- a/Mage.Sets/src/mage/cards/t/Twinflame.java +++ b/Mage.Sets/src/mage/cards/t/Twinflame.java @@ -1,7 +1,6 @@ package mage.cards.t; import mage.abilities.Ability; -import mage.abilities.DelayedTriggeredAbility; import mage.abilities.abilityword.StriveAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.effects.OneShotEffect; @@ -11,7 +10,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; -import mage.filter.common.FilterControlledCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -36,8 +34,7 @@ public final class Twinflame extends CardImpl { // Choose any number of target creatures you control. For each of them, create a token that's a copy of that creature, except it has haste. Exile them at the beginning of the next end step. this.getSpellAbility().addEffect(new TwinflameCopyEffect()); - this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, new FilterControlledCreaturePermanent(), false)); - + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE)); } private Twinflame(final Twinflame card) { @@ -69,23 +66,22 @@ class TwinflameCopyEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - List toExile = new ArrayList<>(); - for (UUID creatureId : this.getTargetPointer().getTargets(game, source)) { - Permanent creature = game.getPermanentOrLKIBattlefield(creatureId); - if (creature != null) { - CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(source.getControllerId(), null, true); - effect.setTargetPointer(new FixedTarget(creature, game)); - effect.apply(game, source); - toExile.addAll(effect.getAddedPermanents()); - } - } - ExileTargetEffect exileEffect = new ExileTargetEffect(); - exileEffect.setTargetPointer(new FixedTargets(toExile, game)); - DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(exileEffect); - game.addDelayedTriggeredAbility(delayedAbility, source); - return true; + if (controller == null) { + return false; } - return false; + List toExile = new ArrayList<>(); + for (UUID creatureId : this.getTargetPointer().getTargets(game, source)) { + Permanent creature = game.getPermanentOrLKIBattlefield(creatureId); + if (creature != null) { + CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(source.getControllerId(), null, true); + effect.setTargetPointer(new FixedTarget(creature, game)); + effect.apply(game, source); + toExile.addAll(effect.getAddedPermanents()); + } + } + game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility( + new ExileTargetEffect().setTargetPointer(new FixedTargets(toExile, game)) + ), source); + return true; } } diff --git a/Mage.Sets/src/mage/cards/t/TwiningTwins.java b/Mage.Sets/src/mage/cards/t/TwiningTwins.java index b0406116218..cb8e36f28a1 100644 --- a/Mage.Sets/src/mage/cards/t/TwiningTwins.java +++ b/Mage.Sets/src/mage/cards/t/TwiningTwins.java @@ -12,6 +12,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TokenPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -46,7 +47,7 @@ public final class TwiningTwins extends AdventureCard { // Swift Spiral // Exile target nontoken creature. Return it to the battlefield under its owner’s control at the beginning of the next end step. this.getSpellCard().getSpellAbility().addEffect(new ExileReturnBattlefieldNextEndStepTargetEffect().withTextThatCard(false)); - this.getSpellCard().getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellCard().getSpellAbility().addTarget(new TargetPermanent(filter)); this.finalizeAdventure(); } diff --git a/Mage.Sets/src/mage/cards/t/TwinmawStormbrood.java b/Mage.Sets/src/mage/cards/t/TwinmawStormbrood.java index 41c021b2836..7a8d67bd10f 100644 --- a/Mage.Sets/src/mage/cards/t/TwinmawStormbrood.java +++ b/Mage.Sets/src/mage/cards/t/TwinmawStormbrood.java @@ -14,6 +14,7 @@ import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -44,7 +45,7 @@ public final class TwinmawStormbrood extends OmenCard { // Charring Bite // deals 5 damage to target creature without flying. this.getSpellCard().getSpellAbility().addEffect(new DamageTargetEffect(5)); - this.getSpellCard().getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellCard().getSpellAbility().addTarget(new TargetPermanent(filter)); this.finalizeOmen(); } diff --git a/Mage.Sets/src/mage/cards/t/TwistsAndTurns.java b/Mage.Sets/src/mage/cards/t/TwistsAndTurns.java index db69072bc66..76c33e1b534 100644 --- a/Mage.Sets/src/mage/cards/t/TwistsAndTurns.java +++ b/Mage.Sets/src/mage/cards/t/TwistsAndTurns.java @@ -4,8 +4,8 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.effects.keyword.ExploreTargetEffect; @@ -17,6 +17,7 @@ import mage.constants.ComparisonType; import mage.constants.Duration; import mage.constants.Outcome; import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledLandPermanent; import mage.game.Game; import mage.game.events.ExploreEvent; import mage.game.events.GameEvent; @@ -29,6 +30,11 @@ import java.util.UUID; */ public final class TwistsAndTurns extends CardImpl { + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledLandPermanent("you control seven or more lands"), + ComparisonType.MORE_THAN, 6, true + ); + public TwistsAndTurns(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{G}"); this.secondSideCardClazz = mage.cards.m.MycoidMaze.class; @@ -43,12 +49,9 @@ public final class TwistsAndTurns extends CardImpl { // When a land you control enters, if you control seven or more lands, transform Twists and Turns. this.addAbility(new TransformAbility()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldControlledTriggeredAbility(new TransformSourceEffect(), StaticFilters.FILTER_LAND), - new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_LANDS, ComparisonType.MORE_THAN, 6, true), - "When a land you control enters, if you control seven or more lands, transform {this}." - )); - + this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + new TransformSourceEffect(), StaticFilters.FILTER_LAND + ).withInterveningIf(condition).setTriggerPhrase("When a land you control enters, ")); } private TwistsAndTurns(final TwistsAndTurns card) { @@ -89,7 +92,7 @@ class TwistsAndTurnsReplacementEffect extends ReplacementEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - ExploreEvent exploreEvent = (ExploreEvent)event; + ExploreEvent exploreEvent = (ExploreEvent) event; exploreEvent.addScry(); return false; } diff --git a/Mage.Sets/src/mage/cards/t/TyrantOfValakut.java b/Mage.Sets/src/mage/cards/t/TyrantOfValakut.java index 57049a56d52..35063c1b7be 100644 --- a/Mage.Sets/src/mage/cards/t/TyrantOfValakut.java +++ b/Mage.Sets/src/mage/cards/t/TyrantOfValakut.java @@ -1,11 +1,9 @@ - package mage.cards.t; -import java.util.UUID; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.SurgedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.SurgeAbility; @@ -15,14 +13,15 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** - * * @author fireshoes */ public final class TyrantOfValakut extends CardImpl { public TyrantOfValakut(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{R}{R}"); this.subtype.add(SubType.DRAGON); this.power = new MageInt(5); this.toughness = new MageInt(4); @@ -34,10 +33,10 @@ public final class TyrantOfValakut extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When Tyrant of Valakut enters the battlefield, if its surge cost was paid, it deals 3 damage to any target. - EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(3), false); + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(3)) + .withInterveningIf(SurgedCondition.instance).withRuleTextReplacement(true); ability.addTarget(new TargetAnyTarget()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, SurgedCondition.instance, - "When {this} enters, if its surge cost was paid, it deals 3 damage to any target.")); + this.addAbility(ability); } private TyrantOfValakut(final TyrantOfValakut card) { diff --git a/Mage.Sets/src/mage/cards/u/UbulSarGatekeepers.java b/Mage.Sets/src/mage/cards/u/UbulSarGatekeepers.java index 68f61c73924..74d1985a17a 100644 --- a/Mage.Sets/src/mage/cards/u/UbulSarGatekeepers.java +++ b/Mage.Sets/src/mage/cards/u/UbulSarGatekeepers.java @@ -3,18 +3,14 @@ package mage.cards.u; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.condition.Condition; -import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.YouControlTwoOrMoreGatesCondition; import mage.abilities.effects.common.continuous.BoostTargetEffect; -import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.common.GatesYouControlHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.filter.StaticFilters; -import mage.filter.common.FilterControlledPermanent; -import mage.target.Target; -import mage.target.common.TargetCreaturePermanent; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.target.common.TargetOpponentsCreaturePermanent; import java.util.UUID; @@ -23,14 +19,6 @@ import java.util.UUID; */ public final class UbulSarGatekeepers extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent(); - - static { - filter.add(SubType.GATE.getPredicate()); - } - - private static final Condition gatesCondition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.MORE_THAN, 1); - public UbulSarGatekeepers(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); this.subtype.add(SubType.ZOMBIE); @@ -40,14 +28,10 @@ public final class UbulSarGatekeepers extends CardImpl { this.toughness = new MageInt(4); // Whenever Ubul Sar Gatekeepers enters the battlefield, if you control two or more Gates, target creature an opponent controls gets -2/-2 until end of turn. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(-2, -2, Duration.EndOfTurn)), - gatesCondition, - "When {this} enters, if you control two or more Gates, target creature an opponent controls gets -2/-2 until end of turn."); - Target target = new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE); - ability.addTarget(target); - ability.addHint(new ConditionHint(gatesCondition, "You control two or more Gates")); - this.addAbility(ability); + Ability ability = new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(-2, -2)) + .withInterveningIf(YouControlTwoOrMoreGatesCondition.instance); + ability.addTarget(new TargetOpponentsCreaturePermanent()); + this.addAbility(ability.addHint(GatesYouControlHint.instance)); } private UbulSarGatekeepers(final UbulSarGatekeepers card) { diff --git a/Mage.Sets/src/mage/cards/u/UlrichsKindred.java b/Mage.Sets/src/mage/cards/u/UlrichsKindred.java index 0f25d20d9e2..65cbf6f93b0 100644 --- a/Mage.Sets/src/mage/cards/u/UlrichsKindred.java +++ b/Mage.Sets/src/mage/cards/u/UlrichsKindred.java @@ -17,6 +17,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.AttackingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -44,7 +45,7 @@ public final class UlrichsKindred extends CardImpl { SimpleActivatedAbility ability = new SimpleActivatedAbility( new GainAbilityTargetEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{3}{G}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/u/UltimatePrice.java b/Mage.Sets/src/mage/cards/u/UltimatePrice.java index c1f7305f23e..4045f770743 100644 --- a/Mage.Sets/src/mage/cards/u/UltimatePrice.java +++ b/Mage.Sets/src/mage/cards/u/UltimatePrice.java @@ -8,6 +8,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.MonocoloredPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -26,7 +27,7 @@ public final class UltimatePrice extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{B}"); // Destroy target monocolored creature. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); } diff --git a/Mage.Sets/src/mage/cards/u/UlvenwaldBear.java b/Mage.Sets/src/mage/cards/u/UlvenwaldBear.java index 47756c0e6d1..9a37f7b8f43 100644 --- a/Mage.Sets/src/mage/cards/u/UlvenwaldBear.java +++ b/Mage.Sets/src/mage/cards/u/UlvenwaldBear.java @@ -1,12 +1,9 @@ - package mage.cards.u; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.MorbidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.hint.common.MorbidHint; import mage.cards.CardImpl; @@ -14,26 +11,27 @@ import mage.cards.CardSetInfo; import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Outcome; import mage.counters.CounterType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author Loki */ public final class UlvenwaldBear extends CardImpl { public UlvenwaldBear(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); this.subtype.add(SubType.BEAR); this.power = new MageInt(2); this.toughness = new MageInt(2); // Morbid — When Ulvenwald Bear enters the battlefield, if a creature died this turn, put two +1/+1 counters on target creature. - Ability ability = new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance(2), Outcome.BoostCreature)), - MorbidCondition.instance, "When {this} enters, if a creature died this turn, put two +1/+1 counters on target creature."); + Ability ability = new EntersBattlefieldTriggeredAbility( + new AddCountersTargetEffect(CounterType.P1P1.createInstance(2)) + ).withInterveningIf(MorbidCondition.instance); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability.addHint(MorbidHint.instance).setAbilityWord(AbilityWord.MORBID)); } diff --git a/Mage.Sets/src/mage/cards/u/UlvenwaldTracker.java b/Mage.Sets/src/mage/cards/u/UlvenwaldTracker.java index d45b79ca504..d07df3da42d 100644 --- a/Mage.Sets/src/mage/cards/u/UlvenwaldTracker.java +++ b/Mage.Sets/src/mage/cards/u/UlvenwaldTracker.java @@ -12,11 +12,14 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2; + /** * @author North */ @@ -36,7 +39,7 @@ public final class UlvenwaldTracker extends CardImpl { Target controlledTarget = new TargetControlledCreaturePermanent(); controlledTarget.setTargetTag(1); ability.addTarget(controlledTarget); - Target secondTarget = new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2); + Target secondTarget = new TargetPermanent(FILTER_ANOTHER_CREATURE_TARGET_2); secondTarget.setTargetTag(2); ability.addTarget(secondTarget); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/u/UndeadGladiator.java b/Mage.Sets/src/mage/cards/u/UndeadGladiator.java index 5ab3069888d..d0ec2c8720d 100644 --- a/Mage.Sets/src/mage/cards/u/UndeadGladiator.java +++ b/Mage.Sets/src/mage/cards/u/UndeadGladiator.java @@ -1,43 +1,41 @@ - package mage.cards.u; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.common.DiscardCardCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect; import mage.abilities.keyword.CyclingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.PhaseStep; import mage.constants.Zone; +import java.util.UUID; + /** - * * @author fireshoes */ public final class UndeadGladiator extends CardImpl { public UndeadGladiator(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.ZOMBIE); this.subtype.add(SubType.BARBARIAN); this.power = new MageInt(3); this.toughness = new MageInt(1); // {1}{B}, Discard a card: Return Undead Gladiator from your graveyard to your hand. Activate this ability only during your upkeep. - Ability ability = new ConditionalActivatedAbility(Zone.GRAVEYARD, - new ReturnSourceFromGraveyardToHandEffect(), - new ManaCostsImpl<>("{1}{B}"), - new IsStepCondition(PhaseStep.UPKEEP), null); + Ability ability = new ActivateIfConditionActivatedAbility( + Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(), + new ManaCostsImpl<>("{1}{B}"), IsStepCondition.getMyUpkeep() + ); ability.addCost(new DiscardCardCost()); this.addAbility(ability); - + // Cycling {1}{B} this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{1}{B}"))); } diff --git a/Mage.Sets/src/mage/cards/u/UndercellarSweep.java b/Mage.Sets/src/mage/cards/u/UndercellarSweep.java index 7e098e7423e..0c15fdedc41 100644 --- a/Mage.Sets/src/mage/cards/u/UndercellarSweep.java +++ b/Mage.Sets/src/mage/cards/u/UndercellarSweep.java @@ -4,7 +4,6 @@ import mage.abilities.Ability; import mage.abilities.common.AttacksWithCreaturesTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.TakeTheInitiativeEffect; import mage.abilities.hint.common.InitiativeHint; @@ -25,15 +24,14 @@ public final class UndercellarSweep extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{W}"); // When Undercellar Sweep enters the battlefield, you take the initiative. - this.addAbility(new EntersBattlefieldTriggeredAbility(new TakeTheInitiativeEffect()).addHint(InitiativeHint.instance)); + this.addAbility(new EntersBattlefieldTriggeredAbility(new TakeTheInitiativeEffect()) + .addHint(InitiativeHint.instance)); // Whenever you attack, if you or a player you're attacking has the initiative, you create two 1/1 white Soldier creature token that are tapped and attacking. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksWithCreaturesTriggeredAbility( - new CreateTokenEffect(new SoldierToken(), 2, true, true), 1 - ), UndercellarSweepCondition.instance, "Whenever you attack, if you or a player you're attacking " + - "has the initiative, you create two 1/1 white Soldier creature tokens that are tapped and attacking." - )); + this.addAbility(new AttacksWithCreaturesTriggeredAbility( + new CreateTokenEffect(new SoldierToken(), 2, true, true) + .setText("you create two 1/1 white Soldier creature tokens that are tapped and attacking"), 1 + ).withInterveningIf(UndercellarSweepCondition.instance)); } private UndercellarSweep(final UndercellarSweep card) { @@ -63,4 +61,9 @@ enum UndercellarSweepCondition implements Condition { .map(game.getCombat()::getDefenderId) .anyMatch(game.getInitiativeId()::equals); } + + @Override + public String toString() { + return "you or a player you're attacking has the initiative"; + } } diff --git a/Mage.Sets/src/mage/cards/u/UndercityScrounger.java b/Mage.Sets/src/mage/cards/u/UndercityScrounger.java index 56f6f20fbad..dfd6a8e25ac 100644 --- a/Mage.Sets/src/mage/cards/u/UndercityScrounger.java +++ b/Mage.Sets/src/mage/cards/u/UndercityScrounger.java @@ -3,14 +3,13 @@ package mage.cards.u; import mage.MageInt; import mage.abilities.condition.common.MorbidCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.hint.common.MorbidHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.game.permanent.token.TreasureToken; import java.util.UUID; @@ -29,9 +28,8 @@ public final class UndercityScrounger extends CardImpl { this.toughness = new MageInt(4); // {T}: Create a Treasure token. Activate only if a creature died this turn. - this.addAbility(new ConditionalActivatedAbility( - Zone.BATTLEFIELD, new CreateTokenEffect(new TreasureToken()), - new TapSourceCost(), MorbidCondition.instance + this.addAbility(new ActivateIfConditionActivatedAbility( + new CreateTokenEffect(new TreasureToken()), new TapSourceCost(), MorbidCondition.instance ).addHint(MorbidHint.instance)); } diff --git a/Mage.Sets/src/mage/cards/u/UndercityUprising.java b/Mage.Sets/src/mage/cards/u/UndercityUprising.java index a3758ace5ea..bd4739a4b42 100644 --- a/Mage.Sets/src/mage/cards/u/UndercityUprising.java +++ b/Mage.Sets/src/mage/cards/u/UndercityUprising.java @@ -8,11 +8,14 @@ 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 mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author TheElk801 */ @@ -30,7 +33,7 @@ public final class UndercityUprising extends CardImpl { .setText("Then target creature you control fights target creature you don't control. " + "(Each deals damage equal to its power to the other.)")); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); } private UndercityUprising(final UndercityUprising card) { diff --git a/Mage.Sets/src/mage/cards/u/UnderhandedDesigns.java b/Mage.Sets/src/mage/cards/u/UnderhandedDesigns.java index a49e49a5049..b4787b9c2e9 100644 --- a/Mage.Sets/src/mage/cards/u/UnderhandedDesigns.java +++ b/Mage.Sets/src/mage/cards/u/UnderhandedDesigns.java @@ -1,10 +1,9 @@ - package mage.cards.u; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.mana.GenericManaCost; @@ -17,31 +16,36 @@ 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.filter.common.FilterControlledArtifactPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class UnderhandedDesigns extends CardImpl { + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledArtifactPermanent("you control two or more artifacts"), + ComparisonType.MORE_THAN, 1 + ); + public UnderhandedDesigns(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}"); // Whenever an artifact you control enters, you may pay {1}. If you do, each opponent loses 1 life and you gain 1 life. - DoIfCostPaid doIfCostPaid = new DoIfCostPaid(new LoseLifeOpponentsEffect(1), new GenericManaCost(1)); - doIfCostPaid.addEffect(new GainLifeEffect(1).concatBy("and")); - this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, - doIfCostPaid, StaticFilters.FILTER_PERMANENT_ARTIFACT, false)); + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + new DoIfCostPaid(new LoseLifeOpponentsEffect(1), new GenericManaCost(1)) + .addEffect(new GainLifeEffect(1).concatBy("and")), + StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT + )); // {1}{B}, Sacrifice Underhanded Designs: Destroy target creature. Activate this ability only if you control two or more artifacts. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new DestroyTargetEffect(), - new ManaCostsImpl<>("{1}{B}"), - new PermanentsOnTheBattlefieldCondition(new FilterControlledArtifactPermanent("you control two or more artifacts"), ComparisonType.MORE_THAN, 1)); + Ability ability = new ActivateIfConditionActivatedAbility( + new DestroyTargetEffect(), new ManaCostsImpl<>("{1}{B}"), condition + ); ability.addCost(new SacrificeSourceCost()); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/u/Undo.java b/Mage.Sets/src/mage/cards/u/Undo.java index 7eaa6d0bceb..3eb44b312ec 100644 --- a/Mage.Sets/src/mage/cards/u/Undo.java +++ b/Mage.Sets/src/mage/cards/u/Undo.java @@ -1,21 +1,20 @@ - package mage.cards.u; -import java.util.UUID; 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 fireshoes */ public final class Undo extends CardImpl { public Undo(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}{U}"); // Return two target creatures to their owners' hands. this.getSpellAbility().addEffect(new ReturnToHandTargetEffect()); diff --git a/Mage.Sets/src/mage/cards/u/UnityOfTheDroids.java b/Mage.Sets/src/mage/cards/u/UnityOfTheDroids.java index 75da54f62b6..5f809955b8c 100644 --- a/Mage.Sets/src/mage/cards/u/UnityOfTheDroids.java +++ b/Mage.Sets/src/mage/cards/u/UnityOfTheDroids.java @@ -12,6 +12,7 @@ import mage.constants.Duration; import mage.constants.PutCards; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -34,7 +35,7 @@ public final class UnityOfTheDroids extends CardImpl { // Choose one - Prevent all damage that would be dealt to target artifact creature this turn. this.getSpellAbility().addEffect(new PreventDamageToTargetEffect(Duration.EndOfTurn)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(artifactCreatureFilter)); + this.getSpellAbility().addTarget(new TargetPermanent(artifactCreatureFilter)); // Look at the top four cards of your library. Put one of them into your hand and the rest into your graveyard. Mode mode = new Mode(new LookLibraryAndPickControllerEffect(4, 1, PutCards.HAND, PutCards.GRAVEYARD)); @@ -42,7 +43,7 @@ public final class UnityOfTheDroids extends CardImpl { // Destroy target nonartifact creature. mode = new Mode(new DestroyTargetEffect()); - mode.addTarget(new TargetCreaturePermanent(nonArtifactCreatureFilter)); + mode.addTarget(new TargetPermanent(nonArtifactCreatureFilter)); this.getSpellAbility().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/u/UnlikelyAlliance.java b/Mage.Sets/src/mage/cards/u/UnlikelyAlliance.java index 6c0a2e03eb6..ae647da8d25 100644 --- a/Mage.Sets/src/mage/cards/u/UnlikelyAlliance.java +++ b/Mage.Sets/src/mage/cards/u/UnlikelyAlliance.java @@ -15,6 +15,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.AttackingPredicate; import mage.filter.predicate.permanent.BlockingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -35,7 +36,7 @@ public final class UnlikelyAlliance extends CardImpl { // {1}{W}: Target nonattacking, nonblocking creature gets +0/+2 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(0, 2, Duration.EndOfTurn), new ManaCostsImpl<>("{1}{W}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/u/UnlivingPsychopath.java b/Mage.Sets/src/mage/cards/u/UnlivingPsychopath.java index 1e41474d493..66b30b179d0 100644 --- a/Mage.Sets/src/mage/cards/u/UnlivingPsychopath.java +++ b/Mage.Sets/src/mage/cards/u/UnlivingPsychopath.java @@ -21,6 +21,7 @@ import mage.filter.predicate.ObjectSourcePlayer; import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -49,7 +50,7 @@ public final class UnlivingPsychopath extends CardImpl { // {B}, {tap}: Destroy target creature with power less than Unliving Psychopath's power. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new ColoredManaCost(ColoredManaSymbol.B)); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/u/UnnaturalAggression.java b/Mage.Sets/src/mage/cards/u/UnnaturalAggression.java index cd97cbce9d8..12d8f02b206 100644 --- a/Mage.Sets/src/mage/cards/u/UnnaturalAggression.java +++ b/Mage.Sets/src/mage/cards/u/UnnaturalAggression.java @@ -10,10 +10,13 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.SecondTargetPointer; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -29,7 +32,7 @@ public final class UnnaturalAggression extends CardImpl { // Target creature you control fights target creature an opponent controls. this.getSpellAbility().addEffect(new FightTargetsEffect(false)); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); // If the creature an opponent controls would die this turn, exile it instead. Effect effect = new ExileTargetIfDiesEffect(); effect.setText("If the creature an opponent controls would die this turn, exile it instead"); diff --git a/Mage.Sets/src/mage/cards/u/UnquenchableThirst.java b/Mage.Sets/src/mage/cards/u/UnquenchableThirst.java index adf11e815aa..e914901281d 100644 --- a/Mage.Sets/src/mage/cards/u/UnquenchableThirst.java +++ b/Mage.Sets/src/mage/cards/u/UnquenchableThirst.java @@ -4,7 +4,6 @@ package mage.cards.u; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.DesertControlledOrGraveyardCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.DontUntapInControllersUntapStepEnchantedEffect; import mage.abilities.effects.common.TapEnchantedEffect; @@ -36,11 +35,8 @@ public final class UnquenchableThirst extends CardImpl { this.addAbility(new EnchantAbility(auraTarget)); // When Unquenchable Thirst enters the battlefield, if you control a Desert or there is a Desert card in your graveyard, tap enchanted creature. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new TapEnchantedEffect()), - DesertControlledOrGraveyardCondition.instance, "When {this} enters, " + - "if you control a Desert or there is a Desert card in your graveyard, tap enchanted creature." - ).addHint(DesertControlledOrGraveyardCondition.getHint())); + this.addAbility(new EntersBattlefieldTriggeredAbility(new TapEnchantedEffect()) + .withInterveningIf(DesertControlledOrGraveyardCondition.instance).addHint(DesertControlledOrGraveyardCondition.getHint())); // Enchanted creature doesn't untap during its controller's untap step. this.addAbility(new SimpleStaticAbility(new DontUntapInControllersUntapStepEnchantedEffect())); diff --git a/Mage.Sets/src/mage/cards/u/UnravelingMummy.java b/Mage.Sets/src/mage/cards/u/UnravelingMummy.java index 2badbfe8d63..d20d9886022 100644 --- a/Mage.Sets/src/mage/cards/u/UnravelingMummy.java +++ b/Mage.Sets/src/mage/cards/u/UnravelingMummy.java @@ -18,6 +18,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.AttackingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -44,14 +45,14 @@ public final class UnravelingMummy extends CardImpl { Effect effect = new GainAbilityTargetEffect(LifelinkAbility.getInstance(), Duration.EndOfTurn); effect.setText("Target attacking Zombie gains lifelink until end of turn."); Ability ability = new SimpleActivatedAbility(effect, new ManaCostsImpl<>("{1}{W}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // {1}{B}: Target attacking Zombie gains deathtouch until end of turn. effect = new GainAbilityTargetEffect(DeathtouchAbility.getInstance(), Duration.EndOfTurn); effect.setText("Target attacking Zombie gains deathtouch until end of turn. (Any amount of damage it deals to a creature is enough to destroy it.)"); ability = new SimpleActivatedAbility(effect, new ManaCostsImpl<>("{1}{B}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/u/UnrulyKrasis.java b/Mage.Sets/src/mage/cards/u/UnrulyKrasis.java index b48ac0fe224..0b54128017f 100644 --- a/Mage.Sets/src/mage/cards/u/UnrulyKrasis.java +++ b/Mage.Sets/src/mage/cards/u/UnrulyKrasis.java @@ -17,7 +17,7 @@ import mage.constants.SubType; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -40,7 +40,7 @@ public final class UnrulyKrasis extends CardImpl { // Whenever Unruly Krasis attacks, you may have the base power and toughness of another target creature you control become X/X until end of turn, where X is Unruly Krasis's power. Ability ability = new AttacksTriggeredAbility(new UnrulyKrasisEffect(), true); - ability.addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); this.addAbility(ability); // {3}{G}{U}: Adapt 3. @@ -87,4 +87,4 @@ class UnrulyKrasisEffect extends OneShotEffect { game.addEffect(effect, source); return true; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/u/UnrulySureshot.java b/Mage.Sets/src/mage/cards/u/UnrulySureshot.java index 6facccb4e29..1713ba71d8d 100644 --- a/Mage.Sets/src/mage/cards/u/UnrulySureshot.java +++ b/Mage.Sets/src/mage/cards/u/UnrulySureshot.java @@ -16,6 +16,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetOpponentsCreaturePermanent; @@ -45,7 +46,7 @@ public final class UnrulySureshot extends CardImpl { // {3}{R}: Unruly Sureshot deals 2 damage to target creature with a bounty counter on it. ability = new SimpleActivatedAbility(new DamageTargetEffect(2), new ManaCostsImpl<>("{3}{R}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/u/UnstableGlyphbridge.java b/Mage.Sets/src/mage/cards/u/UnstableGlyphbridge.java index 211b54eddcb..2115fe4af1a 100644 --- a/Mage.Sets/src/mage/cards/u/UnstableGlyphbridge.java +++ b/Mage.Sets/src/mage/cards/u/UnstableGlyphbridge.java @@ -3,7 +3,6 @@ package mage.cards.u; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromEverywhereSourceCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.CraftAbility; import mage.cards.CardImpl; @@ -20,12 +19,11 @@ import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; /** - * * @author notgreat */ public final class UnstableGlyphbridge extends CardImpl { @@ -35,12 +33,8 @@ public final class UnstableGlyphbridge extends CardImpl { this.secondSideCardClazz = mage.cards.s.SandswirlWanderglyph.class; // When Unstable Glyphbridge enters the battlefield, if you cast it, for each player, choose a creature with power 2 or less that player controls. Then destroy all creatures except creatures chosen this way. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility( - new UnstableGlyphbridgeEffect()), CastFromEverywhereSourceCondition.instance, - "When {this} enters, if you cast it, " + - "for each player, choose a creature with power 2 or less that player controls. " + - "Then destroy all creatures except creatures chosen this way." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new UnstableGlyphbridgeEffect()) + .withInterveningIf(CastFromEverywhereSourceCondition.instance)); // Craft with artifact {3}{W}{W} this.addAbility(new CraftAbility("{3}{W}{W}")); @@ -86,9 +80,9 @@ class UnstableGlyphbridgeEffect extends OneShotEffect { continue; } FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with power 2 or less"); - filter.add(new PowerPredicate(ComparisonType.OR_LESS,2)); + filter.add(new PowerPredicate(ComparisonType.OR_LESS, 2)); filter.add(new ControllerIdPredicate(playerId)); - TargetCreaturePermanent target = new TargetCreaturePermanent(filter); + TargetPermanent target = new TargetPermanent(filter); target.withNotTarget(true); target.withChooseHint(player.getName() + " controls"); diff --git a/Mage.Sets/src/mage/cards/u/UnstoppableSlasher.java b/Mage.Sets/src/mage/cards/u/UnstoppableSlasher.java index f3b3386bf50..a769af4e9e6 100644 --- a/Mage.Sets/src/mage/cards/u/UnstoppableSlasher.java +++ b/Mage.Sets/src/mage/cards/u/UnstoppableSlasher.java @@ -5,7 +5,6 @@ import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.LoseHalfLifeTargetEffect; import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldWithCounterEffect; import mage.abilities.keyword.DeathtouchAbility; @@ -39,9 +38,12 @@ public final class UnstoppableSlasher extends CardImpl { .setText("they lose half their life, rounded up"), false, true)); // When Unstoppable Slasher dies, if it had no counters on it, return it to the battlefield tapped under its owner's control with two stun counters on it. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new DiesSourceTriggeredAbility(new ReturnSourceFromGraveyardToBattlefieldWithCounterEffect( - CounterType.STUN.createInstance(2), true, true, false, false - ), false), UnstoppableSlasherCondition.instance, "When {this} dies, if it had no counters on it, return it to the battlefield tapped under its owner's control with two stun counters on it")); + this.addAbility(new DiesSourceTriggeredAbility( + new ReturnSourceFromGraveyardToBattlefieldWithCounterEffect( + CounterType.STUN.createInstance(2), + true, true, false, false + ).setText("return it to the battlefield tapped under its owner's control with two stun counters on it") + ).withInterveningIf(UnstoppableSlasherCondition.instance)); } private UnstoppableSlasher(final UnstoppableSlasher card) { @@ -60,14 +62,17 @@ enum UnstoppableSlasherCondition implements Condition { @Override public boolean apply(Game game, Ability source) { Permanent permanent = source.getSourcePermanentOrLKI(game); - if (permanent == null) { - return false; - } - return permanent + return permanent != null + && permanent .getCounters(game) .values() .stream() .mapToInt(Counter::getCount) .sum() == 0; } + + @Override + public String toString() { + return "it had no counters on it"; + } } diff --git a/Mage.Sets/src/mage/cards/u/Urabrask.java b/Mage.Sets/src/mage/cards/u/Urabrask.java index 1676c242257..899f4552ec6 100644 --- a/Mage.Sets/src/mage/cards/u/Urabrask.java +++ b/Mage.Sets/src/mage/cards/u/Urabrask.java @@ -6,7 +6,7 @@ import mage.abilities.Ability; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.ExileAndReturnSourceEffect; import mage.abilities.effects.mana.BasicManaEffect; @@ -51,7 +51,7 @@ public final class Urabrask extends CardImpl { // {R}: Exile Urabrask, then return it to the battlefield transformed under its owner's control. Activate only as a sorcery and only if you've cast three or more instant and/or sorcery spells this turn. this.addAbility(new TransformAbility()); - this.addAbility(new ConditionalActivatedAbility( + this.addAbility(new ActivateIfConditionActivatedAbility( new ExileAndReturnSourceEffect(PutCards.BATTLEFIELD_TRANSFORMED), new ManaCostsImpl<>("{R}"), UrabraskCondition.instance ).setTiming(TimingRule.SORCERY)); diff --git a/Mage.Sets/src/mage/cards/u/UrborgEmissary.java b/Mage.Sets/src/mage/cards/u/UrborgEmissary.java index dac2bf6755e..b4ec61712c9 100644 --- a/Mage.Sets/src/mage/cards/u/UrborgEmissary.java +++ b/Mage.Sets/src/mage/cards/u/UrborgEmissary.java @@ -1,12 +1,9 @@ - package mage.cards.u; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -15,15 +12,15 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.target.TargetPermanent; -/** - * - * @author LoneFox +import java.util.UUID; +/** + * @author LoneFox */ public final class UrborgEmissary extends CardImpl { public UrborgEmissary(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.HUMAN); this.subtype.add(SubType.WIZARD); this.power = new MageInt(3); @@ -31,11 +28,12 @@ public final class UrborgEmissary extends CardImpl { // Kicker {1}{U} this.addAbility(new KickerAbility("{1}{U}")); + // When Urborg Emissary enters the battlefield, if it was kicked, return target permanent to its owner's hand. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()); + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandTargetEffect()) + .withInterveningIf(KickedCondition.ONCE); ability.addTarget(new TargetPermanent()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.ONCE, - "When {this} enters, if it was kicked, return target permanent to its owner's hand.")); + this.addAbility(ability); } private UrborgEmissary(final UrborgEmissary card) { diff --git a/Mage.Sets/src/mage/cards/u/UrborgStalker.java b/Mage.Sets/src/mage/cards/u/UrborgStalker.java index cc0a2af87e7..e8550aaf34a 100644 --- a/Mage.Sets/src/mage/cards/u/UrborgStalker.java +++ b/Mage.Sets/src/mage/cards/u/UrborgStalker.java @@ -1,36 +1,37 @@ - package mage.cards.u; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; -import mage.constants.SubType; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.FilterNonlandPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class UrborgStalker extends CardImpl { - private static final FilterPermanent filter = new FilterPermanent(); + private static final FilterPermanent filter = new FilterNonlandPermanent("that player controls a nonblack, nonland permanent"); static { filter.add(TargetController.ACTIVE.getControllerPredicate()); filter.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK))); - filter.add(Predicates.not(CardType.LAND.getPredicate())); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); + public UrborgStalker(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); @@ -39,13 +40,9 @@ public final class UrborgStalker extends CardImpl { this.toughness = new MageInt(4); // At the beginning of each player's upkeep, if that player controls a nonblack, nonland permanent, Urborg Stalker deals 1 damage to that player. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(TargetController.ANY, new DamageTargetEffect(1), false), - new PermanentsOnTheBattlefieldCondition(filter), - "At the beginning of each player's upkeep, " - + "if that player controls a nonblack, nonland permanent, " - + "{this} deals 1 damage to that player." - )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + TargetController.EACH_PLAYER, new DamageTargetEffect(1, true, "that player"), false + ).withInterveningIf(condition)); } private UrborgStalker(final UrborgStalker card) { diff --git a/Mage.Sets/src/mage/cards/u/UrgeToFeed.java b/Mage.Sets/src/mage/cards/u/UrgeToFeed.java index bc572bc69ed..1d5f88995f1 100644 --- a/Mage.Sets/src/mage/cards/u/UrgeToFeed.java +++ b/Mage.Sets/src/mage/cards/u/UrgeToFeed.java @@ -1,7 +1,5 @@ - package mage.cards.u; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; @@ -13,17 +11,19 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class UrgeToFeed extends CardImpl { public UrgeToFeed(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}{B}"); // Target creature gets -3/-3 until end of turn. You may tap any number of untapped Vampire creatures you control. If you do, put a +1/+1 counter on each of those Vampires. this.getSpellAbility().addEffect(new BoostTargetEffect(-3, -3, Duration.EndOfTurn)); @@ -62,14 +62,13 @@ class UrgeToFeedEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - TargetCreaturePermanent target = new TargetCreaturePermanent(0, Integer.MAX_VALUE, filter, true); - if (target.canChoose(source.getControllerId(), source, game) && target.choose(Outcome.Tap, source.getControllerId(), source.getSourceId(), source, game)) { - for (UUID vampireId : target.getTargets()) { - Permanent vampire = game.getPermanent(vampireId); - if (vampire != null) { - vampire.tap(source, game); - vampire.addCounters(CounterType.P1P1.createInstance(), source.getControllerId(), source, game); - } + TargetPermanent target = new TargetPermanent(0, Integer.MAX_VALUE, filter, true); + target.choose(Outcome.Tap, source.getControllerId(), source.getSourceId(), source, game); + for (UUID vampireId : target.getTargets()) { + Permanent vampire = game.getPermanent(vampireId); + if (vampire != null) { + vampire.tap(source, game); + vampire.addCounters(CounterType.P1P1.createInstance(), source.getControllerId(), source, game); } } return true; diff --git a/Mage.Sets/src/mage/cards/u/UrtetRemnantOfMemnarch.java b/Mage.Sets/src/mage/cards/u/UrtetRemnantOfMemnarch.java index abc2a955b88..8b3bebeb2b6 100644 --- a/Mage.Sets/src/mage/cards/u/UrtetRemnantOfMemnarch.java +++ b/Mage.Sets/src/mage/cards/u/UrtetRemnantOfMemnarch.java @@ -3,7 +3,6 @@ package mage.cards.u; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; -import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.costs.common.TapSourceCost; @@ -11,10 +10,12 @@ import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.UntapAllControllerEffect; import mage.abilities.effects.common.counter.AddCountersAllEffect; -import mage.abilities.hint.common.MyTurnHint; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.counters.CounterType; import mage.filter.FilterSpell; import mage.filter.common.FilterControlledPermanent; @@ -49,9 +50,11 @@ public final class UrtetRemnantOfMemnarch extends CardImpl { this.addAbility(new BeginningOfCombatTriggeredAbility(new UntapAllControllerEffect(filter2, "untap each Myr you control"))); // {W}{U}{B}{R}{G}, {T}: Put three +1/+1 counters on each Myr you control. Activate only during your turn. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new AddCountersAllEffect(CounterType.P1P1.createInstance(3), filter2), new ManaCostsImpl<>("{W}{U}{B}{R}{G}"), MyTurnCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new AddCountersAllEffect(CounterType.P1P1.createInstance(3), filter2), + new ManaCostsImpl<>("{W}{U}{B}{R}{G}"), MyTurnCondition.instance + ); ability.addCost(new TapSourceCost()); - ability.addHint(MyTurnHint.instance); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/u/UvildaDeanOfPerfection.java b/Mage.Sets/src/mage/cards/u/UvildaDeanOfPerfection.java index e12ddb9f71c..0ebeb033f7a 100644 --- a/Mage.Sets/src/mage/cards/u/UvildaDeanOfPerfection.java +++ b/Mage.Sets/src/mage/cards/u/UvildaDeanOfPerfection.java @@ -5,16 +5,15 @@ import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.*; import mage.constants.*; import mage.counters.CounterType; @@ -58,9 +57,7 @@ public final class UvildaDeanOfPerfection extends ModalDoubleFacedCard { this.getRightHalfCard().setPT(4, 4); // At the beginning of your upkeep, exile the top card of each opponent's library. Until end of turn, you may cast spells from among those exiled cards, and you many spend mana as though it were mana of any color to cast those spells. - this.getRightHalfCard().addAbility(new BeginningOfUpkeepTriggeredAbility( - new NassariDeanOfExpressionEffect() - )); + this.getRightHalfCard().addAbility(new BeginningOfUpkeepTriggeredAbility(new NassariDeanOfExpressionEffect())); // Whenever you cast a spell from exile, put a +1/+1 counter on Nassari, Dean of Expression. this.getRightHalfCard().addAbility(SpellCastControllerTriggeredAbility.createWithFromZone( @@ -150,13 +147,11 @@ class UvildaDeanOfPerfectionGainAbilityEffect extends ContinuousEffectImpl { discard(); return true; } - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility( - Zone.EXILED, TargetController.YOU, new RemoveCounterSourceEffect(CounterType.HONE.createInstance()), - false - ), UvildaDeanOfPerfectionCondition.instance, "At the beginning of your upkeep, " + - "if this card is exiled, remove a hone counter from it." - ); + Ability ability = new BeginningOfUpkeepTriggeredAbility( + Zone.EXILED, TargetController.YOU, + new RemoveCounterSourceEffect(CounterType.HONE.createInstance()) + .setText("remove a hone counter from it"), false + ).withInterveningIf(UvildaDeanOfPerfectionCondition.instance); ability.setSourceId(card.getId()); ability.setControllerId(source.getControllerId()); game.getState().addOtherAbility(card, ability); @@ -175,6 +170,11 @@ enum UvildaDeanOfPerfectionCondition implements Condition { public boolean apply(Game game, Ability source) { return game.getState().getZone(source.getSourceId()) == Zone.EXILED; } + + @Override + public String toString() { + return "this card is exiled"; + } } class UvildaDeanOfPerfectionTriggeredAbility extends TriggeredAbilityImpl { diff --git a/Mage.Sets/src/mage/cards/v/VadersCommand.java b/Mage.Sets/src/mage/cards/v/VadersCommand.java index a1aa2db0f09..4e9181879af 100644 --- a/Mage.Sets/src/mage/cards/v/VadersCommand.java +++ b/Mage.Sets/src/mage/cards/v/VadersCommand.java @@ -51,7 +51,7 @@ public final class VadersCommand extends CardImpl { // Destroy target nonartifact creature. mode = new Mode(new DestroyTargetEffect()); - mode.addTarget(new TargetCreaturePermanent(filterNonArtifact)); + mode.addTarget(new TargetPermanent(filterNonArtifact)); this.getSpellAbility().addMode(mode); // Gain 5 life. diff --git a/Mage.Sets/src/mage/cards/v/VagrantPlowbeasts.java b/Mage.Sets/src/mage/cards/v/VagrantPlowbeasts.java index 86f874ec94f..59c5021cced 100644 --- a/Mage.Sets/src/mage/cards/v/VagrantPlowbeasts.java +++ b/Mage.Sets/src/mage/cards/v/VagrantPlowbeasts.java @@ -14,6 +14,7 @@ import mage.constants.ComparisonType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -38,7 +39,7 @@ public final class VagrantPlowbeasts extends CardImpl { SimpleActivatedAbility ability = new SimpleActivatedAbility( new RegenerateTargetEffect(), new ManaCostsImpl<>("{1}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/v/ValakutExploration.java b/Mage.Sets/src/mage/cards/v/ValakutExploration.java index a159e3e3cc7..796840a0131 100644 --- a/Mage.Sets/src/mage/cards/v/ValakutExploration.java +++ b/Mage.Sets/src/mage/cards/v/ValakutExploration.java @@ -1,17 +1,19 @@ package mage.cards.v; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.LandfallAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; 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.Zone; import mage.game.ExileZone; import mage.game.Game; import mage.game.permanent.Permanent; @@ -34,13 +36,8 @@ public final class ValakutExploration extends CardImpl { this.addAbility(new LandfallAbility(new ValakutExplorationExileEffect())); // At the beginning of your end step, if there are cards exiled with Valakut Exploration, put them into their owner's graveyard, then Valakut Exploration deals that much damage to each opponent. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - new ValakutExplorationDamageEffect() - ), ValakutExplorationCondition.instance, "At the beginning of your end step, " + - "if there are cards exiled with {this}, put them into their owner's graveyard, " + - "then {this} deals that much damage to each opponent." - )); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new ValakutExplorationDamageEffect()) + .withInterveningIf(ValakutExplorationCondition.instance)); } private ValakutExploration(final ValakutExploration card) { @@ -63,6 +60,11 @@ enum ValakutExplorationCondition implements Condition { )); return exileZone != null && !exileZone.isEmpty(); } + + @Override + public String toString() { + return "there are cards exiled with {this}"; + } } class ValakutExplorationExileEffect extends OneShotEffect { @@ -109,6 +111,7 @@ class ValakutExplorationDamageEffect extends OneShotEffect { ValakutExplorationDamageEffect() { super(Outcome.Benefit); + staticText = "put them into their owner's graveyard, then {this} deals that much damage to each opponent"; } private ValakutExplorationDamageEffect(final ValakutExplorationDamageEffect effect) { diff --git a/Mage.Sets/src/mage/cards/v/ValkyrieHarbinger.java b/Mage.Sets/src/mage/cards/v/ValkyrieHarbinger.java index 41758484d3d..86d46db191e 100644 --- a/Mage.Sets/src/mage/cards/v/ValkyrieHarbinger.java +++ b/Mage.Sets/src/mage/cards/v/ValkyrieHarbinger.java @@ -1,14 +1,13 @@ package mage.cards.v; import mage.MageInt; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.YouGainedLifeCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.ControllerGainedLifeCount; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.LifelinkAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -42,12 +41,8 @@ public final class ValkyrieHarbinger extends CardImpl { this.addAbility(LifelinkAbility.getInstance()); // At the beginning of each end step, if you gained 4 or more life this turn, create a 4/4 white Angel creature token with flying and vigilance. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - TargetController.ANY, new CreateTokenEffect(new AngelVigilanceToken()), - false - ), condition, "At the beginning of each end step, if you gained 4 or more life this turn, " + - "create a 4/4 white Angel creature token with flying and vigilance." + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.ANY, new CreateTokenEffect(new AngelVigilanceToken()), false, condition ).addHint(ControllerGainedLifeCount.getHint()), new PlayerGainedLifeWatcher()); } diff --git a/Mage.Sets/src/mage/cards/v/ValorousStance.java b/Mage.Sets/src/mage/cards/v/ValorousStance.java index 873f94cf3a4..bd1172f1687 100644 --- a/Mage.Sets/src/mage/cards/v/ValorousStance.java +++ b/Mage.Sets/src/mage/cards/v/ValorousStance.java @@ -14,6 +14,7 @@ import mage.constants.Duration; import mage.constants.Outcome; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ToughnessPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -39,7 +40,7 @@ public final class ValorousStance extends CardImpl { this.getSpellAbility().addTarget(new TargetCreaturePermanent()); // or destroy target creature with toughness 4 or greater. Mode mode1 = new Mode(new DestroyTargetEffect()); - mode1.addTarget(new TargetCreaturePermanent(filter)); + mode1.addTarget(new TargetPermanent(filter)); this.getSpellAbility().addMode(mode1); } diff --git a/Mage.Sets/src/mage/cards/v/ValorsFlagship.java b/Mage.Sets/src/mage/cards/v/ValorsFlagship.java index 4bc90315f4f..d72e3615232 100644 --- a/Mage.Sets/src/mage/cards/v/ValorsFlagship.java +++ b/Mage.Sets/src/mage/cards/v/ValorsFlagship.java @@ -1,8 +1,9 @@ package mage.cards.v; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.CycleTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.EffectKeyValue; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.*; import mage.cards.CardImpl; @@ -10,12 +11,7 @@ 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.game.permanent.token.PilotSaddleCrewToken; -import mage.game.stack.StackObject; -import mage.util.CardUtil; import java.util.UUID; @@ -48,7 +44,8 @@ public final class ValorsFlagship extends CardImpl { this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{X}{2}{W}"))); // When you cycle this card, create X 1/1 colorless Pilot creature tokens with "This token saddles Mounts and crews Vehicles as though its power were 2 greater." - this.addAbility(new ValorsFlagshipTriggeredAbility()); + this.addAbility(new CycleTriggeredAbility( + new CreateTokenEffect(new PilotSaddleCrewToken(), new EffectKeyValue("cycleXValue", "X")))); } private ValorsFlagship(final ValorsFlagship card) { @@ -60,45 +57,3 @@ public final class ValorsFlagship extends CardImpl { return new ValorsFlagship(this); } } - -class ValorsFlagshipTriggeredAbility extends TriggeredAbilityImpl { - - ValorsFlagshipTriggeredAbility() { - super(Zone.ALL, null); - } - - private ValorsFlagshipTriggeredAbility(final ValorsFlagshipTriggeredAbility ability) { - super(ability); - } - - @Override - public ValorsFlagshipTriggeredAbility copy() { - return new ValorsFlagshipTriggeredAbility(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.getSourceId().equals(this.getSourceId())) { - return false; - } - StackObject object = game.getStack().getStackObject(event.getSourceId()); - if (object == null || !(object.getStackAbility() instanceof CyclingAbility)) { - return false; - } - this.getEffects().clear(); - int amount = CardUtil.getSourceCostsTag(game, object.getStackAbility(), "X", 0); - this.addEffect(new CreateTokenEffect(new PilotSaddleCrewToken(), amount)); - return true; - } - - @Override - public String getRule() { - return "When you cycle this card, create X 1/1 colorless Pilot creature tokens with " + - "\"This token saddles Mounts and crews Vehicles as though its power were 2 greater.\""; - } -} diff --git a/Mage.Sets/src/mage/cards/v/VampireSocialite.java b/Mage.Sets/src/mage/cards/v/VampireSocialite.java index f3d3f1a725e..41b9b6d906b 100644 --- a/Mage.Sets/src/mage/cards/v/VampireSocialite.java +++ b/Mage.Sets/src/mage/cards/v/VampireSocialite.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.OpponentsLostLifeCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.decorator.ConditionalReplacementEffect; import mage.abilities.effects.common.EntersWithCountersControlledEffect; import mage.abilities.effects.common.counter.AddCountersAllEffect; @@ -43,11 +42,9 @@ public final class VampireSocialite extends CardImpl { this.addAbility(new MenaceAbility()); // When Vampire Socialite enters the battlefield, if an opponent lost life this turn, put a +1/+1 counter on each other Vampire you control. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new AddCountersAllEffect(CounterType.P1P1.createInstance(), filter)), - OpponentsLostLifeCondition.instance, - "When {this} enters, if an opponent lost life this turn, put a +1/+1 counter on each other Vampire you control." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new AddCountersAllEffect(CounterType.P1P1.createInstance(), filter) + ).withInterveningIf(OpponentsLostLifeCondition.instance)); // As long as an opponent lost life this turn, each other Vampire you control enters the battlefield with an additional +1/+1 counter on it. this.addAbility(new SimpleStaticAbility(new ConditionalReplacementEffect( @@ -55,7 +52,7 @@ public final class VampireSocialite extends CardImpl { filter, CounterType.P1P1.createInstance(), true ), OpponentsLostLifeCondition.instance ).setText("as long as an opponent lost life this turn, " + - "each other Vampire you control enters the battlefield with an additional +1/+1 counter on it"))); + "each other Vampire you control enters with an additional +1/+1 counter on it"))); } private VampireSocialite(final VampireSocialite card) { diff --git a/Mage.Sets/src/mage/cards/v/Vanquish.java b/Mage.Sets/src/mage/cards/v/Vanquish.java index b23f8e6ca95..2be4b3340fc 100644 --- a/Mage.Sets/src/mage/cards/v/Vanquish.java +++ b/Mage.Sets/src/mage/cards/v/Vanquish.java @@ -7,6 +7,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterBlockingCreature; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -21,7 +22,7 @@ public final class Vanquish extends CardImpl { // Destroy target blocking creature. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterBlockingCreature())); + this.getSpellAbility().addTarget(new TargetPermanent(new FilterBlockingCreature())); } private Vanquish(final Vanquish card) { diff --git a/Mage.Sets/src/mage/cards/v/VanquishTheFoul.java b/Mage.Sets/src/mage/cards/v/VanquishTheFoul.java index 9786d09d236..b132119e2d2 100644 --- a/Mage.Sets/src/mage/cards/v/VanquishTheFoul.java +++ b/Mage.Sets/src/mage/cards/v/VanquishTheFoul.java @@ -11,6 +11,7 @@ import mage.constants.ComparisonType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -30,7 +31,7 @@ public final class VanquishTheFoul extends CardImpl { // Destroy target creature with power 4 or greater. Scry 1. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - Target target = new TargetCreaturePermanent(filter); + Target target = new TargetPermanent(filter); this.getSpellAbility().addTarget(target); this.getSpellAbility().addEffect(new ScryEffect(1)); } diff --git a/Mage.Sets/src/mage/cards/v/VassalsDuty.java b/Mage.Sets/src/mage/cards/v/VassalsDuty.java index f1844c0b0a5..c5ac751485c 100644 --- a/Mage.Sets/src/mage/cards/v/VassalsDuty.java +++ b/Mage.Sets/src/mage/cards/v/VassalsDuty.java @@ -1,7 +1,5 @@ - package mage.cards.v; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.GenericManaCost; @@ -10,32 +8,25 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.SuperType; -import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; +import mage.target.TargetPermanent; import mage.target.TargetPlayer; -import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class VassalsDuty extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("legendary creature you control"); - - static { - filter.add(SuperType.LEGENDARY.getPredicate()); - } - public VassalsDuty(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}"); // {1}: The next 1 damage that would be dealt to target legendary creature you control this turn is dealt to you instead. - Ability ability = new SimpleActivatedAbility(new VassalsDutyPreventDamageTargetEffect(Duration.EndOfTurn, 1), new GenericManaCost(1)); - ability.addTarget(new TargetControlledCreaturePermanent(1, 1, filter, false)); + Ability ability = new SimpleActivatedAbility(new VassalsDutyPreventDamageTargetEffect(), new GenericManaCost(1)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_CONTROLLED_CREATURE_LEGENDARY)); this.addAbility(ability); } @@ -51,9 +42,9 @@ public final class VassalsDuty extends CardImpl { class VassalsDutyPreventDamageTargetEffect extends RedirectionEffect { - VassalsDutyPreventDamageTargetEffect(Duration duration, int amount) { - super(duration, amount, UsageType.ONE_USAGE_ABSOLUTE); - staticText = "The next " + amount + " damage that would be dealt to target legendary creature you control this turn is dealt to you instead"; + VassalsDutyPreventDamageTargetEffect() { + super(Duration.EndOfTurn, 1, UsageType.ONE_USAGE_ABSOLUTE); + staticText = "The next 1 damage that would be dealt to target legendary creature you control this turn is dealt to you instead"; } private VassalsDutyPreventDamageTargetEffect(final VassalsDutyPreventDamageTargetEffect effect) { @@ -67,13 +58,13 @@ class VassalsDutyPreventDamageTargetEffect extends RedirectionEffect { @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getTargetId().equals(getTargetPointer().getFirst(game, source))) { - TargetPlayer target = new TargetPlayer(); - target.add(source.getControllerId(), game); - redirectTarget = target; - return true; + if (!event.getTargetId().equals(getTargetPointer().getFirst(game, source))) { + return false; } - return false; + TargetPlayer target = new TargetPlayer(); + target.add(source.getControllerId(), game); + redirectTarget = target; + return true; } } diff --git a/Mage.Sets/src/mage/cards/v/Vault87ForcedEvolution.java b/Mage.Sets/src/mage/cards/v/Vault87ForcedEvolution.java index d5346befc1f..845eafcc52a 100644 --- a/Mage.Sets/src/mage/cards/v/Vault87ForcedEvolution.java +++ b/Mage.Sets/src/mage/cards/v/Vault87ForcedEvolution.java @@ -18,11 +18,15 @@ import mage.counters.CounterType; import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.constants.Duration.WhileControlled; +import static mage.constants.SagaChapter.CHAPTER_I; + /** * @author Cguy7777 */ @@ -54,9 +58,9 @@ public final class Vault87ForcedEvolution extends CardImpl { // I -- Gain control of target non-Mutant creature for as long as you control Vault 87. sagaAbility.addChapterEffect( this, - SagaChapter.CHAPTER_I, - new GainControlTargetEffect(Duration.WhileControlled), - new TargetCreaturePermanent(filterNonMutant)); + CHAPTER_I, + new GainControlTargetEffect(WhileControlled), + new TargetPermanent(filterNonMutant)); // II -- Put a +1/+1 counter on target creature you control. It becomes a Mutant in addition to its other types. sagaAbility.addChapterEffect( @@ -85,4 +89,4 @@ public final class Vault87ForcedEvolution extends CardImpl { public Vault87ForcedEvolution copy() { return new Vault87ForcedEvolution(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/v/VaultbornTyrant.java b/Mage.Sets/src/mage/cards/v/VaultbornTyrant.java index 5229e88a3e0..bb67b7d2e21 100644 --- a/Mage.Sets/src/mage/cards/v/VaultbornTyrant.java +++ b/Mage.Sets/src/mage/cards/v/VaultbornTyrant.java @@ -4,7 +4,8 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.SourceMatchesFilterCondition; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenCopyTargetEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; @@ -19,10 +20,9 @@ import mage.constants.SubType; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.filter.predicate.permanent.TokenPredicate; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.game.permanent.PermanentToken; -import mage.target.targetpointer.FixedTarget; import java.util.UUID; @@ -32,11 +32,15 @@ import java.util.UUID; public final class VaultbornTyrant extends CardImpl { private static final FilterPermanent filter = new FilterControlledCreaturePermanent("creature you control with power 4 or greater"); + private static final FilterPermanent filter2 = new FilterPermanent("it's not a token"); static { filter.add(new PowerPredicate(ComparisonType.OR_GREATER, 4)); + filter2.add(TokenPredicate.FALSE); } + private static final Condition condition = new SourceMatchesFilterCondition(filter2); + public VaultbornTyrant(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{G}{G}"); @@ -55,15 +59,7 @@ public final class VaultbornTyrant extends CardImpl { this.addAbility(ability); // When Vaultborn Tyrant dies, if it's not a token, create a token that's a copy of it, except it's an artifact in addition to its other types. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new DiesSourceTriggeredAbility( - new VaultbornTyrantCreateCopyEffect(), - false - ), - VaultbornTyrant::checkSource, - "When {this} dies, if it's not a token, create a token that's a copy of it, " - + "except it's an artifact in addition to its other types." - )); + this.addAbility(new DiesSourceTriggeredAbility(new VaultbornTyrantCreateCopyEffect()).withInterveningIf(condition)); } private VaultbornTyrant(final VaultbornTyrant card) { @@ -74,16 +70,13 @@ public final class VaultbornTyrant extends CardImpl { public VaultbornTyrant copy() { return new VaultbornTyrant(this); } - - static boolean checkSource(Game game, Ability source) { - return !(source.getSourcePermanentOrLKI(game) instanceof PermanentToken); - } } class VaultbornTyrantCreateCopyEffect extends OneShotEffect { VaultbornTyrantCreateCopyEffect() { super(Outcome.PutCreatureInPlay); + staticText = "create a token that's a copy of it, except it's an artifact in addition to its other types"; } private VaultbornTyrantCreateCopyEffect(final VaultbornTyrantCreateCopyEffect effect) { @@ -97,14 +90,9 @@ class VaultbornTyrantCreateCopyEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); - if (permanent == null) { - return false; - } - CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect( + Permanent permanent = source.getSourcePermanentOrLKI(game); + return permanent != null && new CreateTokenCopyTargetEffect( source.getControllerId(), CardType.ARTIFACT, false - ); - effect.setTargetPointer(new FixedTarget(source.getSourceId(), game)); - return effect.apply(game, source); + ).setSavedPermanent(permanent).apply(game, source); } } diff --git a/Mage.Sets/src/mage/cards/v/VedalkenCertarch.java b/Mage.Sets/src/mage/cards/v/VedalkenCertarch.java index 4c5a95f70d7..9e12a757502 100644 --- a/Mage.Sets/src/mage/cards/v/VedalkenCertarch.java +++ b/Mage.Sets/src/mage/cards/v/VedalkenCertarch.java @@ -12,14 +12,12 @@ import mage.cards.CardSetInfo; import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.FilterPermanent; import mage.filter.predicate.Predicates; import mage.target.TargetPermanent; import java.util.UUID; - /** * @author Loki */ @@ -41,11 +39,11 @@ public final class VedalkenCertarch extends CardImpl { this.toughness = new MageInt(1); // Metalcraft — {T}: Tap target artifact, creature, or land. Activate this ability only if you control three or more artifacts. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new TapSourceCost(), MetalcraftCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new TapTargetEffect(), new TapSourceCost(), MetalcraftCondition.instance + ); ability.addTarget(new TargetPermanent(filter)); - ability.setAbilityWord(AbilityWord.METALCRAFT); - ability.addHint(MetalcraftHint.instance); - this.addAbility(ability); + this.addAbility(ability.setAbilityWord(AbilityWord.METALCRAFT).addHint(MetalcraftHint.instance)); } private VedalkenCertarch(final VedalkenCertarch card) { @@ -56,5 +54,4 @@ public final class VedalkenCertarch extends CardImpl { public VedalkenCertarch copy() { return new VedalkenCertarch(this); } - } diff --git a/Mage.Sets/src/mage/cards/v/VedalkenHumiliator.java b/Mage.Sets/src/mage/cards/v/VedalkenHumiliator.java index d6741ad3893..eb0fbf9cc38 100644 --- a/Mage.Sets/src/mage/cards/v/VedalkenHumiliator.java +++ b/Mage.Sets/src/mage/cards/v/VedalkenHumiliator.java @@ -1,10 +1,9 @@ package mage.cards.v; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.MetalcraftCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.LoseAllAbilitiesAllEffect; import mage.abilities.effects.common.continuous.SetBasePowerToughnessAllEffect; import mage.abilities.hint.common.MetalcraftHint; @@ -32,25 +31,14 @@ public final class VedalkenHumiliator extends CardImpl { this.toughness = new MageInt(4); // Metalcraft — Whenever Vedalken Humiliator attacks, if you control three or more artifacts, creatures your opponents control lose all abilities and have base power and toughness 1/1 until end of turn. - TriggeredAbility ability = new AttacksTriggeredAbility( - new SetBasePowerToughnessAllEffect( - 1, 1, Duration.EndOfTurn, - StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE - ), false - ); - ability.addEffect(new LoseAllAbilitiesAllEffect( - StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE, - Duration.EndOfTurn - )); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - ability, MetalcraftCondition.instance, - "Whenever {this} attacks, " - + "if you control three or more artifacts, " - + "creatures your opponents control lose all abilities " - + "and have base power and toughness 1/1 until end of turn.") - .setAbilityWord(AbilityWord.METALCRAFT) - .addHint(MetalcraftHint.instance) - ); + Ability ability = new AttacksTriggeredAbility(new LoseAllAbilitiesAllEffect( + StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURES, Duration.EndOfTurn + ).setText("creatures your opponents control lose all abilities")).withInterveningIf(MetalcraftCondition.instance); + ability.addEffect(new SetBasePowerToughnessAllEffect( + 1, 1, Duration.EndOfTurn, + StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE + ).setText("and have base power and toughness 1/1 until end of turn")); + this.addAbility(ability.setAbilityWord(AbilityWord.METALCRAFT).addHint(MetalcraftHint.instance)); } private VedalkenHumiliator(final VedalkenHumiliator card) { diff --git a/Mage.Sets/src/mage/cards/v/VedalkenShackles.java b/Mage.Sets/src/mage/cards/v/VedalkenShackles.java index 7bf323c778e..81705dd6f62 100644 --- a/Mage.Sets/src/mage/cards/v/VedalkenShackles.java +++ b/Mage.Sets/src/mage/cards/v/VedalkenShackles.java @@ -22,6 +22,7 @@ import mage.filter.predicate.ObjectSourcePlayer; import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -48,7 +49,7 @@ public final class VedalkenShackles extends CardImpl { "Gain control of target creature with power less than or equal to the number of Islands you control for as long as {this} remains tapped"); Ability ability = new SimpleActivatedAbility(effect, new GenericManaCost(2)); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(controllableCreatures)); + ability.addTarget(new TargetPermanent(controllableCreatures)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/v/VeilOfBirds.java b/Mage.Sets/src/mage/cards/v/VeilOfBirds.java index 6cf073bbfe3..374b13ce618 100644 --- a/Mage.Sets/src/mage/cards/v/VeilOfBirds.java +++ b/Mage.Sets/src/mage/cards/v/VeilOfBirds.java @@ -1,11 +1,7 @@ package mage.cards.v; -import java.util.UUID; -import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; -import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.SourceIsEnchantmentCondition; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -13,26 +9,28 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.filter.FilterSpell; import mage.filter.StaticFilters; -import mage.game.permanent.token.TokenImpl; +import mage.game.permanent.token.custom.CreatureToken; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class VeilOfBirds extends CardImpl { - private static final FilterSpell filter = new FilterSpell(); - public VeilOfBirds(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}"); // When an opponent casts a spell, if Veil of Birds is an enchantment, Veil of Birds becomes a 1/1 Bird creature with flying. - TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new VeilOfBirdsToken(), null, Duration.WhileOnBattlefield), - filter, false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_PERMANENT_ENCHANTMENT), - "When an opponent casts a spell, if {this} is an enchantment, {this} becomes a 1/1 Bird creature with flying.")); + this.addAbility(new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect( + new CreatureToken( + 1, 1, "1/1 Bird creature with flying", SubType.BIRD + ).withAbility(FlyingAbility.getInstance()), null, Duration.WhileOnBattlefield + ), StaticFilters.FILTER_SPELL_A, false) + .withInterveningIf(SourceIsEnchantmentCondition.instance) + .withRuleTextReplacement(true) + .setTriggerPhrase("When an opponent casts a spell, ")); } private VeilOfBirds(final VeilOfBirds card) { @@ -44,23 +42,3 @@ public final class VeilOfBirds extends CardImpl { return new VeilOfBirds(this); } } - -class VeilOfBirdsToken extends TokenImpl { - - public VeilOfBirdsToken() { - super("Bird", "1/1 creature with flying"); - cardType.add(CardType.CREATURE); - subtype.add(SubType.BIRD); - power = new MageInt(1); - toughness = new MageInt(1); - this.addAbility(FlyingAbility.getInstance()); - } - - private VeilOfBirdsToken(final VeilOfBirdsToken token) { - super(token); - } - - public VeilOfBirdsToken copy() { - return new VeilOfBirdsToken(this); - } -} diff --git a/Mage.Sets/src/mage/cards/v/VeilOfSecrecy.java b/Mage.Sets/src/mage/cards/v/VeilOfSecrecy.java index c4829438b5e..dbf44a7a14b 100644 --- a/Mage.Sets/src/mage/cards/v/VeilOfSecrecy.java +++ b/Mage.Sets/src/mage/cards/v/VeilOfSecrecy.java @@ -2,7 +2,6 @@ package mage.cards.v; import mage.ObjectColor; import mage.abilities.costs.common.ReturnToHandChosenControlledPermanentCost; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.combat.CantBeBlockedTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.ShroudAbility; @@ -10,42 +9,37 @@ import mage.abilities.keyword.SpliceAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Duration; import mage.constants.SubType; import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.ColorPredicate; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; /** - * * @author LevelX2 */ public final class VeilOfSecrecy extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("a blue creature"); + private static final FilterControlledPermanent filter = new FilterControlledCreaturePermanent("a blue creature"); static { filter.add(new ColorPredicate(ObjectColor.BLUE)); } public VeilOfSecrecy(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); this.subtype.add(SubType.ARCANE); // Target creature gains shroud until end of turn and can't be blocked this turn. - Effect effect = new GainAbilityTargetEffect(ShroudAbility.getInstance(), Duration.EndOfTurn); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect(ShroudAbility.getInstance()).setText("target creature gains shroud until end of turn")); + this.getSpellAbility().addEffect(new CantBeBlockedTargetEffect().setText("and can't be blocked this turn")); this.getSpellAbility().addTarget(new TargetCreaturePermanent().withChooseHint("gains shroud and can't be blocked")); - effect.setText("Target creature gains shroud until end of turn"); - this.getSpellAbility().addEffect(effect); - effect = new CantBeBlockedTargetEffect(); - effect.setText("and can't be blocked this turn"); - this.getSpellAbility().addEffect(effect); - + // Splice onto Arcane-Return a blue creature you control to its owner's hand. - this.addAbility(new SpliceAbility(SpliceAbility.ARCANE, new ReturnToHandChosenControlledPermanentCost(new TargetControlledCreaturePermanent(filter)))); + this.addAbility(new SpliceAbility(SpliceAbility.ARCANE, new ReturnToHandChosenControlledPermanentCost(new TargetControlledPermanent(filter)))); } private VeilOfSecrecy(final VeilOfSecrecy card) { diff --git a/Mage.Sets/src/mage/cards/v/VeiledApparition.java b/Mage.Sets/src/mage/cards/v/VeiledApparition.java index ddb202c6119..0e00a764e22 100644 --- a/Mage.Sets/src/mage/cards/v/VeiledApparition.java +++ b/Mage.Sets/src/mage/cards/v/VeiledApparition.java @@ -1,11 +1,8 @@ package mage.cards.v; -import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; -import mage.abilities.condition.common.SourceMatchesFilterCondition; +import mage.abilities.condition.common.SourceIsEnchantmentCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.SacrificeSourceUnlessPaysEffect; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.keyword.FlyingAbility; @@ -15,29 +12,31 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.filter.FilterSpell; import mage.filter.StaticFilters; -import mage.game.permanent.token.TokenImpl; +import mage.game.permanent.token.custom.CreatureToken; import java.util.UUID; /** - * * @author jeffwadsworth */ public final class VeiledApparition extends CardImpl { - - private static final FilterSpell filter = new FilterSpell(); public VeiledApparition(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); // When an opponent casts a spell, if Veiled Apparition is an enchantment, Veiled Apparition becomes a 3/3 Illusion creature with flying and "At the beginning of your upkeep, sacrifice Veiled Apparition unless you pay {1}{U}." - TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new VeiledApparitionToken(), null, Duration.WhileOnBattlefield), - filter, false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_PERMANENT_ENCHANTMENT), - "When an opponent casts a spell, if {this} is an enchantment, {this} becomes a 3/3 Illusion creature with flying and \"At the beginning of your upkeep, sacrifice Veiled Apparition unless you pay {1}{U}.\"")); - + this.addAbility(new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect( + new CreatureToken( + 3, 3, "3/3 Illusion creature with flying and \"At the beginning " + + "of your upkeep, sacrifice this creature unless you pay {1}{U}.\"", SubType.ILLUSION + ).withAbility(FlyingAbility.getInstance()).withAbility(new BeginningOfUpkeepTriggeredAbility( + new SacrificeSourceUnlessPaysEffect(new ManaCostsImpl<>("{1}{U}")) + )), null, Duration.WhileOnBattlefield + ), StaticFilters.FILTER_SPELL_A, false) + .withInterveningIf(SourceIsEnchantmentCondition.instance) + .withRuleTextReplacement(true) + .setTriggerPhrase("When an opponent casts a spell, ")); } private VeiledApparition(final VeiledApparition card) { @@ -49,26 +48,3 @@ public final class VeiledApparition extends CardImpl { return new VeiledApparition(this); } } - -class VeiledApparitionToken extends TokenImpl { - - VeiledApparitionToken() { - super("Illusion", "3/3 Illusion creature with flying and \"At the beginning of your upkeep, sacrifice Veiled Apparition unless you pay {1}{U}."); - cardType.add(CardType.CREATURE); - subtype.add(SubType.ILLUSION); - power = new MageInt(3); - toughness = new MageInt(3); - this.addAbility(FlyingAbility.getInstance()); - this.addAbility(new BeginningOfUpkeepTriggeredAbility( - new SacrificeSourceUnlessPaysEffect(new ManaCostsImpl<>("{1}{U}")) - )); - } - - private VeiledApparitionToken(final VeiledApparitionToken token) { - super(token); - } - - public VeiledApparitionToken copy() { - return new VeiledApparitionToken(this); - } -} diff --git a/Mage.Sets/src/mage/cards/v/VeiledCrocodile.java b/Mage.Sets/src/mage/cards/v/VeiledCrocodile.java index 66092e37d46..b18d6fc37bc 100644 --- a/Mage.Sets/src/mage/cards/v/VeiledCrocodile.java +++ b/Mage.Sets/src/mage/cards/v/VeiledCrocodile.java @@ -1,7 +1,7 @@ package mage.cards.v; -import mage.MageInt; import mage.abilities.StateTriggeredAbility; +import mage.abilities.condition.common.SourceIsEnchantmentCondition; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -11,9 +11,11 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.permanent.token.TokenImpl; +import mage.game.permanent.token.custom.CreatureToken; import mage.players.Player; +import java.util.Objects; +import java.util.Set; import java.util.UUID; /** @@ -41,9 +43,14 @@ public final class VeiledCrocodile extends CardImpl { class VeiledCrocodileStateTriggeredAbility extends StateTriggeredAbility { public VeiledCrocodileStateTriggeredAbility() { - super(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new VeilCrocodileToken(), null, Duration.Custom)); - this.withRuleTextReplacement(false); - setTriggerPhrase("When a player has no cards in hand, if {this} is an enchantment, "); + super(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect( + new CreatureToken( + 4, 4, "4/4 Crocodile creature", SubType.CROCODILE + ), null, Duration.Custom + )); + this.withInterveningIf(SourceIsEnchantmentCondition.instance); + this.withRuleTextReplacement(true); + this.setTriggerPhrase("When a player has no cards in hand, "); } private VeiledCrocodileStateTriggeredAbility(final VeiledCrocodileStateTriggeredAbility ability) { @@ -57,41 +64,13 @@ class VeiledCrocodileStateTriggeredAbility extends StateTriggeredAbility { @Override public boolean checkTrigger(GameEvent event, Game game) { - for (UUID playerId : game.getState().getPlayersInRange(controllerId, game)) { - Player player = game.getPlayer(playerId); - if (player != null - && player.getHand().isEmpty()) { - return true; - } - } - return false; - } - - @Override - public boolean checkInterveningIfClause(Game game) { - if (getSourcePermanentIfItStillExists(game) != null) { - return getSourcePermanentIfItStillExists(game).isEnchantment(game); - } - return false; - } - -} - -class VeilCrocodileToken extends TokenImpl { - - public VeilCrocodileToken() { - super("Crocodile", "4/4 Crocodile creature"); - cardType.add(CardType.CREATURE); - subtype.add(SubType.CROCODILE); - power = new MageInt(4); - toughness = new MageInt(4); - } - - private VeilCrocodileToken(final VeilCrocodileToken token) { - super(token); - } - - public VeilCrocodileToken copy() { - return new VeilCrocodileToken(this); + return game + .getState() + .getPlayersInRange(getControllerId(), game) + .stream() + .map(game::getPlayer) + .filter(Objects::nonNull) + .map(Player::getHand) + .anyMatch(Set::isEmpty); } } diff --git a/Mage.Sets/src/mage/cards/v/VeiledSentry.java b/Mage.Sets/src/mage/cards/v/VeiledSentry.java index 47e1dafc782..8c6238d454a 100644 --- a/Mage.Sets/src/mage/cards/v/VeiledSentry.java +++ b/Mage.Sets/src/mage/cards/v/VeiledSentry.java @@ -2,14 +2,11 @@ package mage.cards.v; import mage.abilities.Ability; import mage.abilities.common.SpellCastOpponentTriggeredAbility; -import mage.abilities.condition.Condition; -import mage.abilities.condition.common.SourceMatchesFilterCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.common.SourceIsEnchantmentCondition; import mage.abilities.effects.ContinuousEffectImpl; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.stack.Spell; @@ -21,17 +18,14 @@ import java.util.UUID; */ public final class VeiledSentry extends CardImpl { - private static final Condition condition = new SourceMatchesFilterCondition(StaticFilters.FILTER_PERMANENT_ENCHANTMENT); - public VeiledSentry(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}"); // When an opponent casts a spell, if Veiled Sentry is an enchantment, Veiled Sentry becomes an Illusion creature with power and toughness each equal to that spell's converted mana cost. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new SpellCastOpponentTriggeredAbility(new VeiledSentryEffect(), false), - condition, "When an opponent casts a spell, if {this} is an enchantment, " + - "{this} becomes an Illusion creature with power and toughness each equal to that spell's mana value." - )); + this.addAbility(new SpellCastOpponentTriggeredAbility(new VeiledSentryEffect(), false) + .withInterveningIf(SourceIsEnchantmentCondition.instance) + .withRuleTextReplacement(true) + .setTriggerPhrase("When an opponent casts a spell, ")); } private VeiledSentry(final VeiledSentry card) { @@ -50,7 +44,7 @@ class VeiledSentryEffect extends ContinuousEffectImpl { public VeiledSentryEffect() { super(Duration.Custom, Outcome.BecomeCreature); - staticText = "{this} becomes an Illusion creature with power and toughness equal to that spell's mana value"; + staticText = "{this} becomes an Illusion creature with power and toughness each equal to that spell's mana value"; this.dependencyTypes.add(DependencyType.BecomeCreature); } diff --git a/Mage.Sets/src/mage/cards/v/VeiledSerpent.java b/Mage.Sets/src/mage/cards/v/VeiledSerpent.java index 42bf1e8af41..4fbe5a44683 100644 --- a/Mage.Sets/src/mage/cards/v/VeiledSerpent.java +++ b/Mage.Sets/src/mage/cards/v/VeiledSerpent.java @@ -1,13 +1,9 @@ package mage.cards.v; -import java.util.UUID; -import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility; -import mage.abilities.condition.common.SourceMatchesFilterCondition; +import mage.abilities.condition.common.SourceIsEnchantmentCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.combat.CantAttackUnlessDefenderControllsPermanent; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.keyword.CyclingAbility; @@ -16,30 +12,36 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; -import mage.filter.FilterSpell; +import mage.filter.FilterPermanent; import mage.filter.StaticFilters; -import mage.filter.common.FilterLandPermanent; -import mage.game.permanent.token.TokenImpl; +import mage.game.permanent.token.custom.CreatureToken; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class VeiledSerpent extends CardImpl { + private static final FilterPermanent filter = new FilterPermanent(SubType.ISLAND, "an Island"); + public VeiledSerpent(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); // When an opponent casts a spell, if Veiled Serpent is an enchantment, Veiled Serpent becomes a 4/4 Serpent creature that can't attack unless defending player controls an Island. - TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new VeiledSerpentToken(), null, Duration.WhileOnBattlefield), - new FilterSpell(), false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_PERMANENT_ENCHANTMENT), - "When an opponent casts a spell, if {this} is an enchantment, {this} becomes a 4/4 Serpent creature that can't attack unless defending player controls an Island.")); + this.addAbility(new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect( + new CreatureToken( + 4, 4, "4/4 Serpent creature with " + + "\"This creature can't attack unless defending player controls an Island.\"", + SubType.SERPENT + ).withAbility(new SimpleStaticAbility(new CantAttackUnlessDefenderControllsPermanent(filter))), null, Duration.WhileOnBattlefield + ), StaticFilters.FILTER_SPELL_A, false) + .withInterveningIf(SourceIsEnchantmentCondition.instance) + .withRuleTextReplacement(true) + .setTriggerPhrase("When an opponent casts a spell, ")); // Cycling {2} this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{2}"))); - } private VeiledSerpent(final VeiledSerpent card) { @@ -51,25 +53,3 @@ public final class VeiledSerpent extends CardImpl { return new VeiledSerpent(this); } } - -class VeiledSerpentToken extends TokenImpl { - - public VeiledSerpentToken() { - super("Serpent", "4/4 Serpent creature"); - cardType.add(CardType.CREATURE); - subtype.add(SubType.SERPENT); - power = new MageInt(4); - toughness = new MageInt(4); - this.addAbility(new SimpleStaticAbility( - new CantAttackUnlessDefenderControllsPermanent( - new FilterLandPermanent(SubType.ISLAND, "an Island")))); - } - - private VeiledSerpentToken(final VeiledSerpentToken token) { - super(token); - } - - public VeiledSerpentToken copy() { - return new VeiledSerpentToken(this); - } -} diff --git a/Mage.Sets/src/mage/cards/v/Vendetta.java b/Mage.Sets/src/mage/cards/v/Vendetta.java index e643f7395f5..94280219839 100644 --- a/Mage.Sets/src/mage/cards/v/Vendetta.java +++ b/Mage.Sets/src/mage/cards/v/Vendetta.java @@ -12,8 +12,11 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author North, Loki @@ -24,7 +27,7 @@ public final class Vendetta extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{B}"); // Destroy target nonblack creature. It can't be regenerated. You lose life equal to that creature's toughness. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); this.getSpellAbility().addEffect(new VendettaEffect()); } diff --git a/Mage.Sets/src/mage/cards/v/VenerableWarsinger.java b/Mage.Sets/src/mage/cards/v/VenerableWarsinger.java index 269eb2ba72a..45782471e5b 100644 --- a/Mage.Sets/src/mage/cards/v/VenerableWarsinger.java +++ b/Mage.Sets/src/mage/cards/v/VenerableWarsinger.java @@ -1,7 +1,10 @@ package mage.cards.v; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.dynamicvalue.common.EffectKeyValue; +import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.keyword.TrampleAbility; import mage.abilities.keyword.VigilanceAbility; @@ -10,15 +13,10 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.common.FilterCreatureCard; -import mage.filter.predicate.mageobject.ManaValuePredicate; -import mage.game.Game; -import mage.game.events.DamagedEvent; -import mage.game.events.GameEvent; -import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; +import mage.target.targetadjustment.ManaValueTargetAdjuster; import java.util.UUID; @@ -27,6 +25,8 @@ import java.util.UUID; */ public final class VenerableWarsinger extends CardImpl { + private static final FilterCard filter = new FilterCreatureCard("creature card with mana value X or less from your graveyard"); + public VenerableWarsinger(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{W}"); @@ -42,7 +42,11 @@ public final class VenerableWarsinger extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // Whenever Venerable Warsinger deals combat damage to a player, you may return target creature card with mana value X or less from your graveyard to the battlefield, where X is the amount of damage that Venerable Warsinger dealt to that player. - this.addAbility(new VenerableWarsingerTriggeredAbility()); + Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect(), true); + ability.addTarget(new TargetCardInYourGraveyard(filter)); + ability.setTargetAdjuster(new ManaValueTargetAdjuster(new EffectKeyValue("damage"), ComparisonType.OR_LESS)); + ability.addEffect(new InfoEffect("where X is the amount of damage {this} dealt to that player").concatBy(",")); + this.addAbility(ability); } private VenerableWarsinger(final VenerableWarsinger card) { @@ -54,48 +58,3 @@ public final class VenerableWarsinger extends CardImpl { return new VenerableWarsinger(this); } } - -class VenerableWarsingerTriggeredAbility extends TriggeredAbilityImpl { - - VenerableWarsingerTriggeredAbility() { - super(Zone.BATTLEFIELD, new ReturnFromGraveyardToBattlefieldTargetEffect(), true); - } - - private VenerableWarsingerTriggeredAbility(final VenerableWarsingerTriggeredAbility ability) { - super(ability); - } - - @Override - public VenerableWarsingerTriggeredAbility copy() { - return new VenerableWarsingerTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - Player player = game.getPlayer(event.getPlayerId()); - if (player == null - || !event.getSourceId().equals(getSourceId()) - || !((DamagedEvent) event).isCombatDamage()) { - return false; - } - FilterCard filter = new FilterCreatureCard( - "creature card with mana value " + event.getAmount() + " less from your graveyard" - ); - filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, event.getAmount() + 1)); - this.getTargets().clear(); - this.addTarget(new TargetCardInYourGraveyard(filter)); - return true; - } - - @Override - public String getRule() { - return "Whenever {this} deals combat damage to a player, you may return target creature card " + - "with mana value X or less from your graveyard to the battlefield, " + - "where X is the amount of damage {this} dealt to that player."; - } -} diff --git a/Mage.Sets/src/mage/cards/v/Vengeance.java b/Mage.Sets/src/mage/cards/v/Vengeance.java index b2c7b6185c2..bd1c4ca4530 100644 --- a/Mage.Sets/src/mage/cards/v/Vengeance.java +++ b/Mage.Sets/src/mage/cards/v/Vengeance.java @@ -8,6 +8,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -26,7 +27,7 @@ public final class Vengeance extends CardImpl { // Destroy target tapped creature. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); } diff --git a/Mage.Sets/src/mage/cards/v/VengeantVampire.java b/Mage.Sets/src/mage/cards/v/VengeantVampire.java index 528316fc75c..91d783f056c 100644 --- a/Mage.Sets/src/mage/cards/v/VengeantVampire.java +++ b/Mage.Sets/src/mage/cards/v/VengeantVampire.java @@ -11,10 +11,13 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * @author JayDi85 */ @@ -32,7 +35,7 @@ public final class VengeantVampire extends CardImpl { // When Vengeant Vampire dies, destroy target creature an opponent controls and you gain 4 life. Ability ability = new DiesSourceTriggeredAbility(new DestroyTargetEffect()); ability.addEffect(new GainLifeEffect(4).concatBy("and")); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/v/VengefulDevil.java b/Mage.Sets/src/mage/cards/v/VengefulDevil.java index 5502c231501..69eacef6830 100644 --- a/Mage.Sets/src/mage/cards/v/VengefulDevil.java +++ b/Mage.Sets/src/mage/cards/v/VengefulDevil.java @@ -13,7 +13,6 @@ import mage.cards.CardSetInfo; import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.target.common.TargetAnyTarget; import java.util.UUID; @@ -35,12 +34,10 @@ public final class VengefulDevil extends CardImpl { // Morbid — {T}: Vengeful Devil deals 1 damage to any target. Activate this ability only if a creature died this turn. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new DamageTargetEffect(1), - new TapSourceCost(), MorbidCondition.instance + new DamageTargetEffect(1), new TapSourceCost(), MorbidCondition.instance ); ability.addTarget(new TargetAnyTarget()); - ability.setAbilityWord(AbilityWord.MORBID); - this.addAbility(ability.addHint(MorbidHint.instance)); + this.addAbility(ability.setAbilityWord(AbilityWord.MORBID).addHint(MorbidHint.instance)); } private VengefulDevil(final VengefulDevil card) { diff --git a/Mage.Sets/src/mage/cards/v/VengefulPharaoh.java b/Mage.Sets/src/mage/cards/v/VengefulPharaoh.java index d241d75645a..c16b58cfe3f 100644 --- a/Mage.Sets/src/mage/cards/v/VengefulPharaoh.java +++ b/Mage.Sets/src/mage/cards/v/VengefulPharaoh.java @@ -56,7 +56,7 @@ class VengefulPharaohTriggeredAbility extends TriggeredAbilityImpl implements Ba VengefulPharaohTriggeredAbility() { super(Zone.GRAVEYARD, new DestroyTargetEffect(), false); this.addTarget(new TargetAttackingCreature()); - this.addEffect(new PutOnLibrarySourceEffect(true).setText(", then put {this} on top of your library")); + this.addEffect(new PutOnLibrarySourceEffect(true).setText(", then put this card on top of your library")); this.withInterveningIf(SourceInGraveyardCondition.instance); setTriggerPhrase("Whenever combat damage is dealt to you or a planeswalker you control, "); } @@ -95,5 +95,4 @@ class VengefulPharaohTriggeredAbility extends TriggeredAbilityImpl implements Ba } return false; } - } diff --git a/Mage.Sets/src/mage/cards/v/VenomousBreath.java b/Mage.Sets/src/mage/cards/v/VenomousBreath.java index 6da5caa866d..49a7c85d0a9 100644 --- a/Mage.Sets/src/mage/cards/v/VenomousBreath.java +++ b/Mage.Sets/src/mage/cards/v/VenomousBreath.java @@ -101,7 +101,7 @@ class VenomousBreathEffect extends OneShotEffect { List toDestroy = new ArrayList<>(); for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source, game)) { if (!creature.getId().equals(targetCreature.getSourceId())) { - if (watcher.creatureHasBlockedAttacker(new MageObjectReference(creature, game), targetCreature, game) || watcher.creatureHasBlockedAttacker(targetCreature, new MageObjectReference(creature, game), game)) { + if (watcher.creatureHasBlockedAttacker(new MageObjectReference(creature, game), targetCreature) || watcher.creatureHasBlockedAttacker(targetCreature, new MageObjectReference(creature, game))) { toDestroy.add(creature); } } diff --git a/Mage.Sets/src/mage/cards/v/VenomspoutBrackus.java b/Mage.Sets/src/mage/cards/v/VenomspoutBrackus.java index 8c42d93e58b..36775b55f29 100644 --- a/Mage.Sets/src/mage/cards/v/VenomspoutBrackus.java +++ b/Mage.Sets/src/mage/cards/v/VenomspoutBrackus.java @@ -17,6 +17,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterAttackingOrBlockingCreature; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -42,7 +43,7 @@ public final class VenomspoutBrackus extends CardImpl { // {1}{G}, {tap}: Venomspout Brackus deals 5 damage to target attacking or blocking creature with flying. Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(5), new ManaCostsImpl<>("{1}{G}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // Morph {3}{G}{G} this.addAbility(new MorphAbility(this, new ManaCostsImpl<>("{3}{G}{G}"))); diff --git a/Mage.Sets/src/mage/cards/v/VerdelothTheAncient.java b/Mage.Sets/src/mage/cards/v/VerdelothTheAncient.java index 56fd68be9fb..f3fc8285a67 100644 --- a/Mage.Sets/src/mage/cards/v/VerdelothTheAncient.java +++ b/Mage.Sets/src/mage/cards/v/VerdelothTheAncient.java @@ -5,7 +5,6 @@ import mage.MageObject; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.GetXValue; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.continuous.BoostAllEffect; @@ -54,10 +53,9 @@ public final class VerdelothTheAncient extends CardImpl { ))); // When Verdeloth the Ancient enters the battlefield, if it was kicked, create X 1/1 green Saproling creature tokens. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility( - new CreateTokenEffect(new SaprolingToken(), GetXValue.instance), false - ), KickedCondition.ONCE, "When {this} enters, " + - "if it was kicked, create X 1/1 green Saproling creature tokens.")); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new CreateTokenEffect(new SaprolingToken(), GetXValue.instance) + ).withInterveningIf(KickedCondition.ONCE)); } private VerdelothTheAncient(final VerdelothTheAncient card) { diff --git a/Mage.Sets/src/mage/cards/v/VerduranEmissary.java b/Mage.Sets/src/mage/cards/v/VerduranEmissary.java index b4cf54eef45..79c6e24a4e7 100644 --- a/Mage.Sets/src/mage/cards/v/VerduranEmissary.java +++ b/Mage.Sets/src/mage/cards/v/VerduranEmissary.java @@ -1,12 +1,9 @@ - package mage.cards.v; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -15,14 +12,15 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.target.common.TargetArtifactPermanent; +import java.util.UUID; + /** - * * @author FenrisulfrX */ public final class VerduranEmissary extends CardImpl { public VerduranEmissary(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WIZARD); this.power = new MageInt(2); @@ -32,10 +30,9 @@ public final class VerduranEmissary extends CardImpl { this.addAbility(new KickerAbility("{1}{R}")); // When {this} enters, if it was kicked, destroy target artifact. It can't be regenerated. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(true)); + Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(true)).withInterveningIf(KickedCondition.ONCE); ability.addTarget(new TargetArtifactPermanent()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.ONCE, - "When {this} enters, if it was kicked, destroy target artifact. It can't be regenerated.")); + this.addAbility(ability); } private VerduranEmissary(final VerduranEmissary card) { diff --git a/Mage.Sets/src/mage/cards/v/VerityCircle.java b/Mage.Sets/src/mage/cards/v/VerityCircle.java index f34265717bc..9cebaf64cc7 100644 --- a/Mage.Sets/src/mage/cards/v/VerityCircle.java +++ b/Mage.Sets/src/mage/cards/v/VerityCircle.java @@ -13,6 +13,7 @@ import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -36,7 +37,7 @@ public final class VerityCircle extends CardImpl { // {4}{U}: Tap target creature without flying. Ability ability = new SimpleActivatedAbility(new TapTargetEffect(), new ManaCostsImpl<>("{4}{U}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/v/VerixBladewing.java b/Mage.Sets/src/mage/cards/v/VerixBladewing.java index 94bb69ff6c8..1fe5e6a02c2 100644 --- a/Mage.Sets/src/mage/cards/v/VerixBladewing.java +++ b/Mage.Sets/src/mage/cards/v/VerixBladewing.java @@ -1,11 +1,8 @@ package mage.cards.v; -import java.util.UUID; - import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.KickerAbility; @@ -16,9 +13,11 @@ import mage.constants.SubType; import mage.constants.SuperType; import mage.game.permanent.token.KaroxBladewingDragonToken; +import java.util.UUID; + /** * @author JRHerlehy - * Created on 4/5/18. + * Created on 4/5/18. */ public final class VerixBladewing extends CardImpl { @@ -38,12 +37,7 @@ public final class VerixBladewing extends CardImpl { // When Verix Bladewing enters the battlefield, if it was kicked, create Karox Bladewing, // a legendary 4/4 red Dragon creature token with flying. - EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility( - new CreateTokenEffect(new KaroxBladewingDragonToken())); - - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.ONCE, - "When {this} enters, if it was kicked, create Karox Bladewing, " + - "a legendary 4/4 red Dragon creature token with flying.")); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new KaroxBladewingDragonToken())).withInterveningIf(KickedCondition.ONCE)); } private VerixBladewing(final VerixBladewing card) { diff --git a/Mage.Sets/src/mage/cards/v/Vertigo.java b/Mage.Sets/src/mage/cards/v/Vertigo.java index 37d06241451..4e51ad30f95 100644 --- a/Mage.Sets/src/mage/cards/v/Vertigo.java +++ b/Mage.Sets/src/mage/cards/v/Vertigo.java @@ -11,6 +11,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -33,7 +34,7 @@ public final class Vertigo extends CardImpl { this.getSpellAbility().addEffect(new DamageTargetEffect(2)); this.getSpellAbility().addEffect(new LoseAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn) .setText("That creature loses flying until end of turn")); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private Vertigo(final Vertigo card) { diff --git a/Mage.Sets/src/mage/cards/v/VeryCrypticCommandD.java b/Mage.Sets/src/mage/cards/v/VeryCrypticCommandD.java index 7286e6f419a..5e213c26ee9 100644 --- a/Mage.Sets/src/mage/cards/v/VeryCrypticCommandD.java +++ b/Mage.Sets/src/mage/cards/v/VeryCrypticCommandD.java @@ -69,7 +69,7 @@ public final class VeryCrypticCommandD extends CardImpl { // Turn over target nontoken creature. mode = new Mode(new TurnOverEffect()); - mode.addTarget(new TargetCreaturePermanent(filter2)); + mode.addTarget(new TargetPermanent(filter2)); this.getSpellAbility().getModes().addMode(mode); } diff --git a/Mage.Sets/src/mage/cards/v/VesselOfTheAllConsuming.java b/Mage.Sets/src/mage/cards/v/VesselOfTheAllConsuming.java index d0162684638..a4ac3365a20 100644 --- a/Mage.Sets/src/mage/cards/v/VesselOfTheAllConsuming.java +++ b/Mage.Sets/src/mage/cards/v/VesselOfTheAllConsuming.java @@ -5,7 +5,7 @@ import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.DealsDamageSourceTriggeredAbility; import mage.abilities.common.DealsDamageToAPlayerTriggeredAbility; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.effects.common.LoseGameTargetPlayerEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.TrampleAbility; @@ -49,12 +49,9 @@ public final class VesselOfTheAllConsuming extends CardImpl { this.addAbility(new DealsDamageSourceTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()))); // Whenever Vessel of the All-Consuming deals damage to a player, if it has dealt 10 or more damage to that player this turn, they lose the game. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new DealsDamageToAPlayerTriggeredAbility( - new LoseGameTargetPlayerEffect(), false, true - ), VesselOfTheAllConsumingWatcher::checkPermanent, "Whenever {this} deals damage to a player, " + - "if it has dealt 10 or more damage to that player this turn, they lose the game." - )); + this.addAbility(new DealsDamageToAPlayerTriggeredAbility( + new LoseGameTargetPlayerEffect().setText("they lose the game"), false, true + ).withInterveningIf(VesselOfTheAllConsumingCondition.instance)); } private VesselOfTheAllConsuming(final VesselOfTheAllConsuming card) { @@ -71,6 +68,20 @@ public final class VesselOfTheAllConsuming extends CardImpl { } } +enum VesselOfTheAllConsumingCondition implements Condition { + instance; + + @Override + public boolean apply(Game game, Ability source) { + return VesselOfTheAllConsumingWatcher.checkPermanent(game, source); + } + + @Override + public String toString() { + return "it has dealt 10 or more damage to that player this turn"; + } +} + class VesselOfTheAllConsumingWatcher extends Watcher { private final Map, Integer> morMap = new HashMap<>(); diff --git a/Mage.Sets/src/mage/cards/v/VesuvanShapeshifter.java b/Mage.Sets/src/mage/cards/v/VesuvanShapeshifter.java index 40f766221b7..bcab5c07bda 100644 --- a/Mage.Sets/src/mage/cards/v/VesuvanShapeshifter.java +++ b/Mage.Sets/src/mage/cards/v/VesuvanShapeshifter.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.AsEntersBattlefieldAbility; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.AsTurnedFaceUpEffect; @@ -13,16 +12,18 @@ import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CopyEffect; import mage.abilities.effects.common.CopyPermanentEffect; import mage.abilities.keyword.MorphAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.StaticFilters; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.mageobject.AnotherPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import mage.util.functions.CopyApplier; import java.util.UUID; @@ -104,11 +105,7 @@ class VesuvanShapeshifterEffect extends OneShotEffect { Permanent copyToCreature = game.getPermanent(source.getSourceId()); if (copyToCreature != null) { - FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature"); - filter.add(AnotherPredicate.instance); - - TargetCreaturePermanent target = new TargetCreaturePermanent(0, 1, filter, true); - + TargetPermanent target = new TargetPermanent(0, 1, StaticFilters.FILTER_ANOTHER_CREATURE, true); if (controller != null && controller.chooseTarget(Outcome.BecomeCreature, target, source, game) && !target.getTargets().isEmpty()) { Permanent copyFromCreature = game.getPermanentOrLKIBattlefield(target.getFirstTarget()); if (copyFromCreature != null) { diff --git a/Mage.Sets/src/mage/cards/v/VeteranCathar.java b/Mage.Sets/src/mage/cards/v/VeteranCathar.java index 916d21e0def..d25272fd073 100644 --- a/Mage.Sets/src/mage/cards/v/VeteranCathar.java +++ b/Mage.Sets/src/mage/cards/v/VeteranCathar.java @@ -15,8 +15,11 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.constants.SubType.HUMAN; + /** * * @author LevelX2 @@ -32,7 +35,7 @@ public final class VeteranCathar extends CardImpl { // {3}{W}: Target Human gains double strike until end of turn. Ability ability = new SimpleActivatedAbility(new GainAbilityTargetEffect(DoubleStrikeAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl<>("{3}{W}")); - ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent(SubType.HUMAN, "Human"))); + ability.addTarget(new TargetPermanent(new FilterCreaturePermanent(HUMAN, "Human"))); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/v/VeteransVoice.java b/Mage.Sets/src/mage/cards/v/VeteransVoice.java index fc36117feea..32160ab522a 100644 --- a/Mage.Sets/src/mage/cards/v/VeteransVoice.java +++ b/Mage.Sets/src/mage/cards/v/VeteransVoice.java @@ -10,7 +10,10 @@ import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.keyword.EnchantAbility; 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.predicate.Predicates; @@ -49,7 +52,6 @@ public final class VeteransVoice extends CardImpl { // Tap enchanted creature: Target creature other than the creature tapped this way gets +2/+1 until end of turn. Activate this ability only if enchanted creature is untapped. this.addAbility(new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new BoostTargetEffect(2, 1, Duration.EndOfTurn) .setText("target creature other than the creature tapped this way gets +2/+1 until end of turn"), new TapAttachedCost(), condition diff --git a/Mage.Sets/src/mage/cards/v/ViconiaDrowApostate.java b/Mage.Sets/src/mage/cards/v/ViconiaDrowApostate.java index 4af8640dfef..0bf96e52df6 100644 --- a/Mage.Sets/src/mage/cards/v/ViconiaDrowApostate.java +++ b/Mage.Sets/src/mage/cards/v/ViconiaDrowApostate.java @@ -1,18 +1,20 @@ package mage.cards.v; import mage.MageInt; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.ChooseABackgroundAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInControllerGraveyardCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; import mage.abilities.effects.common.ReturnFromGraveyardAtRandomEffect; import mage.abilities.hint.Hint; import mage.abilities.hint.ValueHint; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.Zone; import mage.filter.StaticFilters; import java.util.UUID; @@ -23,7 +25,7 @@ import java.util.UUID; public final class ViconiaDrowApostate extends CardImpl { private static final Condition condition - = new CardsInControllerGraveyardCondition(4, StaticFilters.FILTER_CARD_CREATURE); + = new CardsInControllerGraveyardCondition(4, StaticFilters.FILTER_CARD_CREATURES); private static final Hint hint = new ValueHint( "Creature cards in your graveyard", new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_CREATURE) @@ -39,12 +41,9 @@ public final class ViconiaDrowApostate extends CardImpl { this.toughness = new MageInt(3); // At the beginning of your upkeep, if there are four or more creature cards in your graveyard, return a creature card at random from your graveyard to your hand. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility( - new ReturnFromGraveyardAtRandomEffect(StaticFilters.FILTER_CARD_CREATURE, Zone.HAND), false - ), condition, "At the beginning of your upkeep, if there are four or more creature cards " + - "in your graveyard, return a creature card at random from your graveyard to your hand." - ).addHint(hint)); + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new ReturnFromGraveyardAtRandomEffect(StaticFilters.FILTER_CARD_CREATURE, Zone.HAND) + ).withInterveningIf(condition).addHint(hint)); // Choose a Background this.addAbility(ChooseABackgroundAbility.getInstance()); diff --git a/Mage.Sets/src/mage/cards/v/VictimOfNight.java b/Mage.Sets/src/mage/cards/v/VictimOfNight.java index bf58f605bfa..c127f2d6d90 100644 --- a/Mage.Sets/src/mage/cards/v/VictimOfNight.java +++ b/Mage.Sets/src/mage/cards/v/VictimOfNight.java @@ -9,6 +9,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -30,7 +31,7 @@ public final class VictimOfNight extends CardImpl { // Destroy target non-Vampire, non-Werewolf, non-Zombie creature. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new DestroyTargetEffect()); } diff --git a/Mage.Sets/src/mage/cards/v/VigeanGraftmage.java b/Mage.Sets/src/mage/cards/v/VigeanGraftmage.java index eeb6f55a359..5001b126f5a 100644 --- a/Mage.Sets/src/mage/cards/v/VigeanGraftmage.java +++ b/Mage.Sets/src/mage/cards/v/VigeanGraftmage.java @@ -14,8 +14,11 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_CREATURE_P1P1; + /** * * @author JotaPeRL @@ -35,7 +38,7 @@ public final class VigeanGraftmage extends CardImpl { // {1}{U}: Untap target creature with a +1/+1 counter on it. Ability ability = new SimpleActivatedAbility(new UntapTargetEffect(), new ManaCostsImpl<>("{1}{U}")); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_P1P1)); + ability.addTarget(new TargetPermanent(FILTER_CREATURE_P1P1)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/v/VineshaperProdigy.java b/Mage.Sets/src/mage/cards/v/VineshaperProdigy.java index fcefd11822c..d7964f27e9b 100644 --- a/Mage.Sets/src/mage/cards/v/VineshaperProdigy.java +++ b/Mage.Sets/src/mage/cards/v/VineshaperProdigy.java @@ -3,7 +3,6 @@ package mage.cards.v; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; @@ -30,14 +29,9 @@ public final class VineshaperProdigy extends CardImpl { this.addAbility(new KickerAbility("{1}{U}")); // When Vineshaper Prodigy enters the battlefield, if it was kicked, look at the top three cards of your library. Put one of them into your hand and the rest on the bottom of your library in any order. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility( - new LookLibraryAndPickControllerEffect( - 3, 1, PutCards.HAND, PutCards.BOTTOM_ANY - )), KickedCondition.ONCE, "When {this} enters, " + - "if it was kicked, look at the top three cards of your library. " + - "Put one of them into your hand and the rest on the bottom of your library in any order." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new LookLibraryAndPickControllerEffect( + 3, 1, PutCards.HAND, PutCards.BOTTOM_ANY + )).withInterveningIf(KickedCondition.ONCE)); } private VineshaperProdigy(final VineshaperProdigy card) { diff --git a/Mage.Sets/src/mage/cards/v/VioletPall.java b/Mage.Sets/src/mage/cards/v/VioletPall.java index 66184057da8..d7ba6b14b41 100644 --- a/Mage.Sets/src/mage/cards/v/VioletPall.java +++ b/Mage.Sets/src/mage/cards/v/VioletPall.java @@ -9,8 +9,11 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; import mage.game.permanent.token.FaerieRogueToken; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author Loki @@ -22,7 +25,7 @@ public final class VioletPall extends CardImpl { this.subtype.add(SubType.FAERIE); this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK)); this.getSpellAbility().addEffect(new CreateTokenEffect(new FaerieRogueToken(), 1)); } diff --git a/Mage.Sets/src/mage/cards/v/ViridianScout.java b/Mage.Sets/src/mage/cards/v/ViridianScout.java index e42e1048ae3..3cbf66865ef 100644 --- a/Mage.Sets/src/mage/cards/v/ViridianScout.java +++ b/Mage.Sets/src/mage/cards/v/ViridianScout.java @@ -16,6 +16,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class ViridianScout extends CardImpl { // {2}{G}, Sacrifice Viridian Scout: Viridian Scout deals 2 damage to target creature with flying. Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(2, "it"), new ManaCostsImpl<>("{2}{G}")); ability.addCost(new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/v/VirtueOfCourage.java b/Mage.Sets/src/mage/cards/v/VirtueOfCourage.java index 8abfd96bd49..716290617bb 100644 --- a/Mage.Sets/src/mage/cards/v/VirtueOfCourage.java +++ b/Mage.Sets/src/mage/cards/v/VirtueOfCourage.java @@ -1,16 +1,14 @@ package mage.cards.v; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SourceDealsNoncombatDamageToOpponentTriggeredAbility; +import mage.abilities.dynamicvalue.common.SavedDamageValue; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.ExileTopXMayPlayUntilEffect; import mage.cards.AdventureCard; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.DamagedPlayerEvent; -import mage.game.events.GameEvent; +import mage.constants.SetTargetPointer; import mage.target.common.TargetAnyTarget; import java.util.UUID; @@ -24,7 +22,10 @@ public final class VirtueOfCourage extends AdventureCard { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, new CardType[]{CardType.INSTANT}, "{3}{R}{R}", "Embereth Blaze", "{1}{R}"); // Whenever a source you control deals noncombat damage to an opponent, you may exile that many cards from the top of your library. You may play those cards this turn. - this.addAbility(new VirtueOfCourageTriggeredAbility()); + this.addAbility(new SourceDealsNoncombatDamageToOpponentTriggeredAbility( + new ExileTopXMayPlayUntilEffect(SavedDamageValue.MANY, false, Duration.EndOfTurn) + .setText("you may exile that many cards from the top of your library. You may play those cards this turn.") + , true, SetTargetPointer.NONE)); // Embereth Blaze // Embereth Blaze deals 2 damage to any target. @@ -43,44 +44,3 @@ public final class VirtueOfCourage extends AdventureCard { return new VirtueOfCourage(this); } } - -class VirtueOfCourageTriggeredAbility extends TriggeredAbilityImpl { - - VirtueOfCourageTriggeredAbility() { - super(Zone.BATTLEFIELD, null, true); - } - - private VirtueOfCourageTriggeredAbility(final VirtueOfCourageTriggeredAbility 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(getControllerId()).contains(event.getTargetId()) - || !game.getControllerId(event.getSourceId()).equals(getControllerId())) { - return false; - } - this.getEffects().clear(); - this.addEffect(new ExileTopXMayPlayUntilEffect(event.getAmount(), Duration.EndOfTurn)); - return true; - } - - @Override - public VirtueOfCourageTriggeredAbility copy() { - return new VirtueOfCourageTriggeredAbility(this); - } - - @Override - public String getRule() { - return "whenever a source you control deals noncombat damage to an opponent, " - + "you may exile that many cards from the top of your library. " - + "You may play those cards this turn."; - } -} diff --git a/Mage.Sets/src/mage/cards/v/VisceridDrone.java b/Mage.Sets/src/mage/cards/v/VisceridDrone.java index ea684250281..c3f01ae7ef8 100644 --- a/Mage.Sets/src/mage/cards/v/VisceridDrone.java +++ b/Mage.Sets/src/mage/cards/v/VisceridDrone.java @@ -18,6 +18,7 @@ import mage.filter.StaticFilters; import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; @@ -54,7 +55,7 @@ public final class VisceridDrone extends CardImpl { new SacrificeTargetCost(filter2), "Sacrifice a creature and a Swamp" )); - ability.addTarget(new TargetCreaturePermanent(filter1)); + ability.addTarget(new TargetPermanent(filter1)); this.addAbility(ability); // {tap}, Sacrifice a creature and a snow Swamp: Destroy target creature. It can't be regenerated. diff --git a/Mage.Sets/src/mage/cards/v/VisionOfTheUnspeakable.java b/Mage.Sets/src/mage/cards/v/VisionOfTheUnspeakable.java index a93dc245b06..99a77ff529a 100644 --- a/Mage.Sets/src/mage/cards/v/VisionOfTheUnspeakable.java +++ b/Mage.Sets/src/mage/cards/v/VisionOfTheUnspeakable.java @@ -36,8 +36,8 @@ public final class VisionOfTheUnspeakable extends CardImpl { // Vision of the Unspeakable gets +1/+1 for each card in your hand. this.addAbility(new SimpleStaticAbility(new BoostSourceEffect( - CardsInControllerHandCount.ANY, - CardsInControllerHandCount.ANY, + CardsInControllerHandCount.ANY_SINGULAR, + CardsInControllerHandCount.ANY_SINGULAR, Duration.WhileOnBattlefield ))); } diff --git a/Mage.Sets/src/mage/cards/v/VitalSplicer.java b/Mage.Sets/src/mage/cards/v/VitalSplicer.java index 4b180c3a4e1..e0c186fd8b5 100644 --- a/Mage.Sets/src/mage/cards/v/VitalSplicer.java +++ b/Mage.Sets/src/mage/cards/v/VitalSplicer.java @@ -15,6 +15,7 @@ import mage.constants.TargetController; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.game.permanent.token.PhyrexianGolemToken; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -46,7 +47,7 @@ public final class VitalSplicer extends CardImpl { // {1}: Regenerate target Golem you control. Ability ability = new SimpleActivatedAbility(new RegenerateTargetEffect(), new ManaCostsImpl<>("{1}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/v/VituGhaziInspector.java b/Mage.Sets/src/mage/cards/v/VituGhaziInspector.java index c0aeffc1fc0..72e65d3c3aa 100644 --- a/Mage.Sets/src/mage/cards/v/VituGhaziInspector.java +++ b/Mage.Sets/src/mage/cards/v/VituGhaziInspector.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CollectedEvidenceCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.keyword.CollectEvidenceAbility; @@ -38,12 +37,10 @@ public final class VituGhaziInspector extends CardImpl { this.addAbility(ReachAbility.getInstance()); // When Vitu-Ghazi Inspector enters the battlefield, if evidence was collected, put a +1/+1 counter on target creature and you gain 2 life. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance())), - CollectedEvidenceCondition.instance, "When {this} enters, if evidence was " + - "collected, put a +1/+1 counter on target creature and you gain 2 life." - ); - ability.addEffect(new GainLifeEffect(2)); + Ability ability = new EntersBattlefieldTriggeredAbility( + new AddCountersTargetEffect(CounterType.P1P1.createInstance()) + ).withInterveningIf(CollectedEvidenceCondition.instance); + ability.addEffect(new GainLifeEffect(2).concatBy("and")); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/v/VivienOfTheArkbow.java b/Mage.Sets/src/mage/cards/v/VivienOfTheArkbow.java index f53d67f5017..5ca61378564 100644 --- a/Mage.Sets/src/mage/cards/v/VivienOfTheArkbow.java +++ b/Mage.Sets/src/mage/cards/v/VivienOfTheArkbow.java @@ -15,11 +15,14 @@ import mage.constants.SubType; import mage.constants.SuperType; import mage.counters.CounterType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * @author TheElk801 */ @@ -40,7 +43,7 @@ public final class VivienOfTheArkbow extends CardImpl { // −3: Target creature you control deals damage equal to its power to target creature you don't control. ability = new LoyaltyAbility(new DamageWithPowerFromOneToAnotherTargetEffect(), -3); ability.addTarget(new TargetControlledCreaturePermanent()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + ability.addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.addAbility(ability); // −9: Creatures you control get +4/+4 and gain trample until end of turn. diff --git a/Mage.Sets/src/mage/cards/v/ViviensJaguar.java b/Mage.Sets/src/mage/cards/v/ViviensJaguar.java index 8bd8ae4f22f..737c29c7b3b 100644 --- a/Mage.Sets/src/mage/cards/v/ViviensJaguar.java +++ b/Mage.Sets/src/mage/cards/v/ViviensJaguar.java @@ -1,30 +1,29 @@ package mage.cards.v; -import java.util.UUID; import mage.MageInt; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect; -import mage.constants.SubType; 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.common.FilterControlledPlaneswalkerPermanent; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class ViviensJaguar extends CardImpl { - private static final FilterControlledPlaneswalkerPermanent filter - = new FilterControlledPlaneswalkerPermanent( - SubType.VIVIEN, - "a Vivien planeswalker" - ); + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPlaneswalkerPermanent(SubType.VIVIEN, "you control a Vivien planeswalker") + ); public ViviensJaguar(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); @@ -38,13 +37,9 @@ public final class ViviensJaguar extends CardImpl { this.addAbility(ReachAbility.getInstance()); // {2}{G}: Return Vivien's Jaguar from your graveyard to your hand. Activate this ability only if you control a Vivien planeswalker. - this.addAbility(new ConditionalActivatedAbility( - Zone.GRAVEYARD, - new ReturnSourceFromGraveyardToHandEffect(), - new ManaCostsImpl<>("{2}{G}"), - new PermanentsOnTheBattlefieldCondition(filter), - "{2}{G}: Return {this} from your graveyard to your hand. " - + "Activate only if you control a Vivien planeswalker." + this.addAbility(new ActivateIfConditionActivatedAbility( + Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(), + new ManaCostsImpl<>("{2}{G}"), condition )); } diff --git a/Mage.Sets/src/mage/cards/v/VivisectionEvangelist.java b/Mage.Sets/src/mage/cards/v/VivisectionEvangelist.java index 205be888562..e40b39f78d3 100644 --- a/Mage.Sets/src/mage/cards/v/VivisectionEvangelist.java +++ b/Mage.Sets/src/mage/cards/v/VivisectionEvangelist.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CorruptedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.VigilanceAbility; import mage.cards.CardImpl; @@ -43,12 +42,8 @@ public final class VivisectionEvangelist extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // Corrupted -- When Vivisection Evangelist enters the battlefield, if an opponent has three or more poison counters, destroy target creature or planeswalker an opponent controls. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect(), false), - CorruptedCondition.instance, "When {this} enters, " + - "if an opponent has three or more poison counters, " + - "destroy target creature or planeswalker an opponent controls." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()) + .withInterveningIf(CorruptedCondition.instance); ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability.setAbilityWord(AbilityWord.CORRUPTED).addHint(CorruptedCondition.getHint())); } diff --git a/Mage.Sets/src/mage/cards/v/VoidGrafter.java b/Mage.Sets/src/mage/cards/v/VoidGrafter.java index c1113515201..0c06de0094a 100644 --- a/Mage.Sets/src/mage/cards/v/VoidGrafter.java +++ b/Mage.Sets/src/mage/cards/v/VoidGrafter.java @@ -1,6 +1,5 @@ package mage.cards.v; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; @@ -11,19 +10,20 @@ import mage.abilities.keyword.HexproofAbility; 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.filter.StaticFilters; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author fireshoes */ public final class VoidGrafter extends CardImpl { public VoidGrafter(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}{U}"); this.subtype.add(SubType.ELDRAZI); this.subtype.add(SubType.DRONE); this.power = new MageInt(2); @@ -36,8 +36,10 @@ public final class VoidGrafter extends CardImpl { this.addAbility(FlashAbility.getInstance()); // When Void Grafter enters the battlefield, another target creature you control gain hexproof until end of turn. - Ability ability = new EntersBattlefieldTriggeredAbility(new GainAbilityTargetEffect(HexproofAbility.getInstance(), Duration.EndOfTurn), false); - ability.addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); + Ability ability = new EntersBattlefieldTriggeredAbility(new GainAbilityTargetEffect( + HexproofAbility.getInstance(), Duration.EndOfTurn + ), false); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/v/VoldarenAmbusher.java b/Mage.Sets/src/mage/cards/v/VoldarenAmbusher.java index 6a19c5a54ca..c0bdb0337d8 100644 --- a/Mage.Sets/src/mage/cards/v/VoldarenAmbusher.java +++ b/Mage.Sets/src/mage/cards/v/VoldarenAmbusher.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.OpponentsLostLifeCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.common.DamageTargetEffect; @@ -25,8 +24,9 @@ import java.util.UUID; */ public final class VoldarenAmbusher extends CardImpl { - private static final DynamicValue xValue - = new PermanentsOnBattlefieldCount(new FilterControlledPermanent(SubType.VAMPIRE)); + private static final DynamicValue xValue = new PermanentsOnBattlefieldCount( + new FilterControlledPermanent(SubType.VAMPIRE, "Vampires you control"), null + ); private static final Hint hint = new ValueHint("Vampires you control", xValue); public VoldarenAmbusher(UUID ownerId, CardSetInfo setInfo) { @@ -38,12 +38,8 @@ public final class VoldarenAmbusher extends CardImpl { this.toughness = new MageInt(2); // When Voldaren Ambusher enters the battlefield, if an opponent lost life this turn, it deals X damage to up to one target creature or planeswalker, where X is the number of Vampires you control. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(xValue)), - OpponentsLostLifeCondition.instance, "When {this} enters, " + - "if an opponent lost life this turn, it deals X damage to up to one target " + - "creature or planeswalker, where X is the number of Vampires you control." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(xValue, "it")) + .withInterveningIf(OpponentsLostLifeCondition.instance); ability.addTarget(new TargetCreatureOrPlaneswalker(0, 1)); this.addAbility(ability.addHint(OpponentsLostLifeHint.instance).addHint(hint)); } diff --git a/Mage.Sets/src/mage/cards/v/VoltaicConstruct.java b/Mage.Sets/src/mage/cards/v/VoltaicConstruct.java index 7d08ba87a9c..6d00a6e0d0c 100644 --- a/Mage.Sets/src/mage/cards/v/VoltaicConstruct.java +++ b/Mage.Sets/src/mage/cards/v/VoltaicConstruct.java @@ -14,6 +14,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -34,7 +35,7 @@ public final class VoltaicConstruct extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); Ability ability = new SimpleActivatedAbility(new UntapTargetEffect(), new GenericManaCost(2)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/v/VonaButcherOfMagan.java b/Mage.Sets/src/mage/cards/v/VonaButcherOfMagan.java index d4ceca02044..024c9a31cf2 100644 --- a/Mage.Sets/src/mage/cards/v/VonaButcherOfMagan.java +++ b/Mage.Sets/src/mage/cards/v/VonaButcherOfMagan.java @@ -7,7 +7,6 @@ import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.costs.common.PayLifeCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.common.DestroyTargetEffect; -import mage.abilities.hint.common.MyTurnHint; import mage.abilities.keyword.LifelinkAbility; import mage.abilities.keyword.VigilanceAbility; import mage.cards.CardImpl; @@ -15,7 +14,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; -import mage.constants.Zone; import mage.target.common.TargetNonlandPermanent; import java.util.UUID; @@ -41,10 +39,11 @@ public final class VonaButcherOfMagan extends CardImpl { this.addAbility(LifelinkAbility.getInstance()); // {T}, Pay 7 life: Destroy target nonland permanent. Activate this ability only during your turn. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new TapSourceCost(), MyTurnCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new DestroyTargetEffect(), new TapSourceCost(), MyTurnCondition.instance + ); ability.addCost(new PayLifeCost(7)); ability.addTarget(new TargetNonlandPermanent()); - ability.addHint(MyTurnHint.instance); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/v/VoodooDoll.java b/Mage.Sets/src/mage/cards/v/VoodooDoll.java index 1117c54da00..0698119433b 100644 --- a/Mage.Sets/src/mage/cards/v/VoodooDoll.java +++ b/Mage.Sets/src/mage/cards/v/VoodooDoll.java @@ -1,20 +1,20 @@ package mage.cards.v; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.SourceTappedCondition; import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.CountersSourceCount; import mage.abilities.effects.common.DamageControllerEffect; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.DestroySourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -30,6 +30,8 @@ import java.util.UUID; */ public final class VoodooDoll extends CardImpl { + private static final DynamicValue xValue = new CountersSourceCount(CounterType.PIN); + public VoodooDoll(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}"); @@ -39,18 +41,18 @@ public final class VoodooDoll extends CardImpl { )); // At the beginning of your end step, if Voodoo Doll is untapped, destroy Voodoo Doll and it deals damage to you equal to the number of pin counters on it. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - new DestroySourceEffect() - ), SourceTappedCondition.UNTAPPED, "At the beginning of your end step, " + - "if {this} is untapped, destroy {this} and it deals damage to you equal to the number of pin counters on it." - ); - ability.addEffect(new DamageControllerEffect(new CountersSourceCount(CounterType.PIN))); + Ability ability = new BeginningOfEndStepTriggeredAbility(new DestroySourceEffect()) + .withInterveningIf(SourceTappedCondition.UNTAPPED); + ability.addEffect(new DamageControllerEffect(xValue) + .setText("and it deals damage to you equal to the number of pin counters on it")); this.addAbility(ability); // {X}{X}, {T}: Voodoo Doll deals damage equal to the number of pin counters on it to any target. X is the number of pin counters on Voodoo Doll. ability = new SimpleActivatedAbility( - new DamageTargetEffect(new CountersSourceCount(CounterType.PIN)), new ManaCostsImpl<>("{X}{X}") + new DamageTargetEffect(new CountersSourceCount(CounterType.PIN)) + .setText("{this} deals damage equal to the number of pin counters on it " + + "to any target. X is the number of pin counters on {this}"), + new ManaCostsImpl<>("{X}{X}") ); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetAnyTarget()); diff --git a/Mage.Sets/src/mage/cards/v/VraskasConquistador.java b/Mage.Sets/src/mage/cards/v/VraskasConquistador.java index 14e811ae99d..6aad67376dc 100644 --- a/Mage.Sets/src/mage/cards/v/VraskasConquistador.java +++ b/Mage.Sets/src/mage/cards/v/VraskasConquistador.java @@ -1,19 +1,19 @@ package mage.cards.v; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.AttacksOrBlocksTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.LoseLifeTargetEffect; 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.SubType; -import mage.filter.common.FilterControlledPermanent; +import mage.filter.common.FilterControlledPlaneswalkerPermanent; import mage.target.common.TargetOpponent; import java.util.UUID; @@ -23,12 +23,10 @@ import java.util.UUID; */ public final class VraskasConquistador extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent(); - - static { - filter.add(CardType.PLANESWALKER.getPredicate()); - filter.add(SubType.VRASKA.getPredicate()); - } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledPlaneswalkerPermanent(SubType.VRASKA, "you control a Vraska planeswalker") + ); + private static final Hint hint = new ConditionHint(condition); public VraskasConquistador(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); @@ -39,14 +37,12 @@ public final class VraskasConquistador extends CardImpl { this.toughness = new MageInt(1); // Whenever Vraska's Conquistador attacks or blocks, if you control a Vraska planeswalker, target opponent loses 2 life and you gain 2 life. - Condition condition = new PermanentsOnTheBattlefieldCondition(filter); - TriggeredAbility ability = new AttacksOrBlocksTriggeredAbility(new LoseLifeTargetEffect(2), false); + Ability ability = new AttacksOrBlocksTriggeredAbility( + new LoseLifeTargetEffect(2), false + ).withInterveningIf(condition); ability.addEffect(new GainLifeEffect(2).concatBy("and")); ability.addTarget(new TargetOpponent()); - ability.addHint(new ConditionHint(condition, "You control a Vraska planeswalker")); - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - ability, condition, - "Whenever {this} attacks or blocks, if you control a Vraska planeswalker, target opponent loses 2 life and you gain 2 life.")); + this.addAbility(ability.addHint(hint)); } private VraskasConquistador(final VraskasConquistador card) { diff --git a/Mage.Sets/src/mage/cards/w/Wakedancer.java b/Mage.Sets/src/mage/cards/w/Wakedancer.java index bb48fa7c66e..ae1bdd2a4d3 100644 --- a/Mage.Sets/src/mage/cards/w/Wakedancer.java +++ b/Mage.Sets/src/mage/cards/w/Wakedancer.java @@ -1,30 +1,26 @@ - package mage.cards.w; -import java.util.UUID; import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.MorbidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.hint.common.MorbidHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; import mage.game.permanent.token.ZombieToken; +import java.util.UUID; + /** - * * @author Loki */ public final class Wakedancer extends CardImpl { - private static final String staticText = "Morbid — When {this} enters, if a creature died this turn, create a 2/2 black Zombie creature token."; - public Wakedancer(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.HUMAN); this.subtype.add(SubType.SHAMAN); @@ -33,8 +29,8 @@ public final class Wakedancer extends CardImpl { this.toughness = new MageInt(2); // Morbid — When Wakedancer enters the battlefield, if a creature died this turn, create a 2/2 black Zombie creature token. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ZombieToken())); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, MorbidCondition.instance, staticText).addHint(MorbidHint.instance)); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ZombieToken())) + .withInterveningIf(MorbidCondition.instance).setAbilityWord(AbilityWord.MORBID).addHint(MorbidHint.instance)); } private Wakedancer(final Wakedancer card) { diff --git a/Mage.Sets/src/mage/cards/w/WakeningSunsAvatar.java b/Mage.Sets/src/mage/cards/w/WakeningSunsAvatar.java index 8df0e3b6166..4cd44f0e1a4 100644 --- a/Mage.Sets/src/mage/cards/w/WakeningSunsAvatar.java +++ b/Mage.Sets/src/mage/cards/w/WakeningSunsAvatar.java @@ -1,11 +1,8 @@ - package mage.cards.w; -import java.util.UUID; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromHandSourcePermanentCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DestroyAllEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -15,8 +12,9 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.watchers.common.CastFromHandWatcher; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class WakeningSunsAvatar extends CardImpl { @@ -36,11 +34,8 @@ public final class WakeningSunsAvatar extends CardImpl { this.toughness = new MageInt(7); // When Wakening Sun's Avatar enters the battlefield, if you cast it from you hand, destroy all non-Dinosaur creatures. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new DestroyAllEffect(filter), false), - CastFromHandSourcePermanentCondition.instance, - "When {this} enters, if you cast it from your hand, destroy all non-Dinosaur creatures."), - new CastFromHandWatcher()); + this.addAbility(new EntersBattlefieldTriggeredAbility(new DestroyAllEffect(filter)) + .withInterveningIf(CastFromHandSourcePermanentCondition.instance), new CastFromHandWatcher()); } private WakeningSunsAvatar(final WakeningSunsAvatar card) { diff --git a/Mage.Sets/src/mage/cards/w/WalkThePlank.java b/Mage.Sets/src/mage/cards/w/WalkThePlank.java index b719d45c10b..6e5a0183e8b 100644 --- a/Mage.Sets/src/mage/cards/w/WalkThePlank.java +++ b/Mage.Sets/src/mage/cards/w/WalkThePlank.java @@ -9,6 +9,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -29,7 +30,7 @@ public final class WalkThePlank extends CardImpl { // Destroy target non-Merfolk creature. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private WalkThePlank(final WalkThePlank card) { diff --git a/Mage.Sets/src/mage/cards/w/WalkerOfSecretWays.java b/Mage.Sets/src/mage/cards/w/WalkerOfSecretWays.java index 64e85962af2..91108e59548 100644 --- a/Mage.Sets/src/mage/cards/w/WalkerOfSecretWays.java +++ b/Mage.Sets/src/mage/cards/w/WalkerOfSecretWays.java @@ -6,20 +6,16 @@ import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.LookAtTargetPlayerHandEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect; -import mage.abilities.hint.common.MyTurnHint; import mage.abilities.keyword.NinjutsuAbility; 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.FilterControlledPermanent; -import mage.game.Game; -import mage.players.Player; -import mage.target.common.TargetControlledPermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -28,7 +24,7 @@ import java.util.UUID; */ public final class WalkerOfSecretWays extends CardImpl { - private static final FilterControlledPermanent filterCreature = new FilterControlledPermanent(SubType.NINJA, "Ninja you control"); + private static final FilterPermanent filterCreature = new FilterControlledPermanent(SubType.NINJA, "Ninja you control"); public WalkerOfSecretWays(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); @@ -42,15 +38,16 @@ public final class WalkerOfSecretWays extends CardImpl { this.addAbility(new NinjutsuAbility("{1}{U}")); // Whenever Walker of Secret Ways deals combat damage to a player, look at that player's hand. - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new WalkerOfSecretWaysEffect(), false, true)); + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility( + new LookAtTargetPlayerHandEffect(), false, true + )); // {1}{U}: Return target Ninja you control to its owner's hand. Activate this ability only during your turn. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandTargetEffect(), new ManaCostsImpl<>("{1}{U}"), MyTurnCondition.instance); - ability.addTarget(new TargetControlledPermanent(filterCreature)); - ability.addHint(MyTurnHint.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new ReturnToHandTargetEffect(), new ManaCostsImpl<>("{1}{U}"), MyTurnCondition.instance + ); + ability.addTarget(new TargetPermanent(filterCreature)); this.addAbility(ability); - - } private WalkerOfSecretWays(final WalkerOfSecretWays card) { @@ -62,30 +59,3 @@ public final class WalkerOfSecretWays extends CardImpl { return new WalkerOfSecretWays(this); } } - -class WalkerOfSecretWaysEffect extends OneShotEffect { - WalkerOfSecretWaysEffect() { - super(Outcome.Detriment); - staticText = "look at that player's hand"; - } - - private WalkerOfSecretWaysEffect(final WalkerOfSecretWaysEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); - if (player != null && controller != null) { - controller.lookAtCards("Walker of Secret Ways", player.getHand(), game); - } - return true; - } - - @Override - public WalkerOfSecretWaysEffect copy() { - return new WalkerOfSecretWaysEffect(this); - } - -} diff --git a/Mage.Sets/src/mage/cards/w/WallOfForgottenPharaohs.java b/Mage.Sets/src/mage/cards/w/WallOfForgottenPharaohs.java index 08b743db0d8..5d71e6859be 100644 --- a/Mage.Sets/src/mage/cards/w/WallOfForgottenPharaohs.java +++ b/Mage.Sets/src/mage/cards/w/WallOfForgottenPharaohs.java @@ -11,7 +11,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.target.common.TargetPlayerOrPlaneswalker; import java.util.UUID; @@ -33,8 +32,7 @@ public final class WallOfForgottenPharaohs extends CardImpl { // {T}: Wall of Forgotten Pharaohs deals 1 damage to target player. Activate this ability only if you control a Desert or there is a Desert card in your graveyard. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new DamageTargetEffect(1), - new TapSourceCost(), DesertControlledOrGraveyardCondition.instance + new DamageTargetEffect(1), new TapSourceCost(), DesertControlledOrGraveyardCondition.instance ); ability.addTarget(new TargetPlayerOrPlaneswalker()); this.addAbility(ability.addHint(DesertControlledOrGraveyardCondition.getHint())); diff --git a/Mage.Sets/src/mage/cards/w/WallOfResistance.java b/Mage.Sets/src/mage/cards/w/WallOfResistance.java index 80d0a58cc10..0e06738f15d 100644 --- a/Mage.Sets/src/mage/cards/w/WallOfResistance.java +++ b/Mage.Sets/src/mage/cards/w/WallOfResistance.java @@ -2,12 +2,11 @@ package mage.cards.w; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.DefenderAbility; import mage.abilities.keyword.FlyingAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -38,13 +37,10 @@ public final class WallOfResistance extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // At the beginning of each end step, if Wall of Resistance was dealt damage this turn, put a +0/+1 counter on it. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - TargetController.ANY, new AddCountersSourceEffect(CounterType.P0P1.createInstance()), - false - ), WallOfResistanceCondition.instance, "At the beginning of each end step, " + - "if {this} was dealt damage this turn, put a +0/+1 counter on it." - )); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.ANY, new AddCountersSourceEffect(CounterType.P0P1.createInstance()), + false, WallOfResistanceCondition.instance + ).withRuleTextReplacement(true)); } private WallOfResistance(final WallOfResistance card) { @@ -65,4 +61,9 @@ enum WallOfResistanceCondition implements Condition { Permanent permanent = source.getSourcePermanentOrLKI(game); return permanent != null && !permanent.getDealtDamageByThisTurn().isEmpty(); } + + @Override + public String toString() { + return "{this} was dealt damage this turn"; + } } diff --git a/Mage.Sets/src/mage/cards/w/WallOfVipers.java b/Mage.Sets/src/mage/cards/w/WallOfVipers.java index 014401a77af..6df17ae8c11 100644 --- a/Mage.Sets/src/mage/cards/w/WallOfVipers.java +++ b/Mage.Sets/src/mage/cards/w/WallOfVipers.java @@ -20,6 +20,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.combat.CombatGroup; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -41,7 +42,7 @@ public final class WallOfVipers extends CardImpl { // {3}: Destroy Wall of Vipers and target creature it's blocking. Any player may activate this ability. SimpleActivatedAbility ability = new SimpleActivatedAbility(new DestroySourceEffect(), new ManaCostsImpl<>("{3}")); ability.addEffect(new DestroyTargetEffect(" and target creature it's blocking")); - ability.addTarget(new TargetCreaturePermanent(new WallOfVipersFilter())); + ability.addTarget(new TargetPermanent(new WallOfVipersFilter())); ability.setMayActivate(TargetController.ANY); ability.addEffect(new InfoEffect("Any player may activate this ability")); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/w/Wallop.java b/Mage.Sets/src/mage/cards/w/Wallop.java index 065a1add221..84b1732ae45 100644 --- a/Mage.Sets/src/mage/cards/w/Wallop.java +++ b/Mage.Sets/src/mage/cards/w/Wallop.java @@ -12,6 +12,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -33,7 +34,7 @@ public final class Wallop extends CardImpl { // Destroy target blue or black creature with flying. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private Wallop(final Wallop card) { diff --git a/Mage.Sets/src/mage/cards/w/WandOfIth.java b/Mage.Sets/src/mage/cards/w/WandOfIth.java index bba33d38036..f35e89212d5 100644 --- a/Mage.Sets/src/mage/cards/w/WandOfIth.java +++ b/Mage.Sets/src/mage/cards/w/WandOfIth.java @@ -7,11 +7,9 @@ import mage.abilities.costs.common.PayLifeCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.OneShotEffect; -import mage.abilities.hint.common.MyTurnHint; import mage.cards.*; 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; @@ -28,10 +26,11 @@ public final class WandOfIth extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); // {3}, {T}: Target player reveals a card at random from their hand. If it's a land card, that player discards it unless they pay 1 life. If it isn't a land card, the player discards it unless they pay life equal to its converted mana cost. Activate this ability only during your turn. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new WandOfIthEffect(), new GenericManaCost(3), MyTurnCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new WandOfIthEffect(), new GenericManaCost(3), MyTurnCondition.instance + ); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetPlayer()); - ability.addHint(MyTurnHint.instance); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/w/WanderingArchaic.java b/Mage.Sets/src/mage/cards/w/WanderingArchaic.java index e31b06ad2f8..2640d7e4012 100644 --- a/Mage.Sets/src/mage/cards/w/WanderingArchaic.java +++ b/Mage.Sets/src/mage/cards/w/WanderingArchaic.java @@ -4,6 +4,7 @@ import mage.abilities.Ability; import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.costs.Cost; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.GainLifeAllEffect; import mage.cards.*; import mage.constants.*; import mage.filter.FilterCard; @@ -49,6 +50,7 @@ public final class WanderingArchaic extends ModalDoubleFacedCard { // Sorcery // Each player looks at the top five cards of their library, reveals a land card and/or an instant or sorcery card from among them, then puts the cards they revealed this way into their hand and the rest on the bottom of their library in a random order. Each player gains 3 life. this.getRightHalfCard().getSpellAbility().addEffect(new ExploreTheVastlandsEffect()); + this.getRightHalfCard().getSpellAbility().addEffect(new GainLifeAllEffect(3)); } private WanderingArchaic(final WanderingArchaic card) { @@ -105,7 +107,7 @@ class ExploreTheVastlandsEffect extends OneShotEffect { staticText = "each player looks at the top five cards of their library " + "and may reveal a land card and/or an instant or sorcery card from among them. " + "Each player puts the cards they revealed this way into their hand and the rest " + - "on the bottom of their library in a random order. Each player gains 3 life"; + "on the bottom of their library in a random order."; } private ExploreTheVastlandsEffect(final ExploreTheVastlandsEffect effect) { @@ -133,12 +135,6 @@ class ExploreTheVastlandsEffect extends OneShotEffect { player.moveCards(toHand, Zone.HAND, source, game); player.putCardsOnBottomOfLibrary(cards, game, source, false); } - for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { - Player player = game.getPlayer(playerId); - if (player != null) { - player.gainLife(3, game, source); - } - } return true; } } diff --git a/Mage.Sets/src/mage/cards/w/WanderingChampion.java b/Mage.Sets/src/mage/cards/w/WanderingChampion.java index 907f3801848..6022841ed54 100644 --- a/Mage.Sets/src/mage/cards/w/WanderingChampion.java +++ b/Mage.Sets/src/mage/cards/w/WanderingChampion.java @@ -2,17 +2,17 @@ package mage.cards.w; import mage.MageInt; import mage.ObjectColor; -import mage.abilities.TriggeredAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.common.DiscardCardCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; 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.FilterPermanent; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; @@ -24,12 +24,17 @@ import java.util.UUID; */ public final class WanderingChampion extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent("green permanent"); + private static final FilterPermanent filter = new FilterControlledPermanent("you control a blue or red permanent"); static { - filter.add(Predicates.or(new ColorPredicate(ObjectColor.BLUE), new ColorPredicate(ObjectColor.RED))); + filter.add(Predicates.or( + new ColorPredicate(ObjectColor.BLUE), + new ColorPredicate(ObjectColor.RED) + )); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); + public WanderingChampion(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); this.subtype.add(SubType.HUMAN); @@ -38,10 +43,9 @@ public final class WanderingChampion extends CardImpl { this.toughness = new MageInt(1); // Whenever Wandering Champion deals combat damage to a player, if you control a blue or red permanent, you may discard a card. If you do, draw a card. - TriggeredAbility ability = new DealsCombatDamageToAPlayerTriggeredAbility(new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new DiscardCardCost()), false); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new PermanentsOnTheBattlefieldCondition(filter), - "Whenever {this} deals combat damage to a player, if you control a blue or red permanent, you may discard a card. If you do, draw a card.")); - + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility( + new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new DiscardCardCost()) + ).withInterveningIf(condition)); } private WanderingChampion(final WanderingChampion card) { diff --git a/Mage.Sets/src/mage/cards/w/WanderingMage.java b/Mage.Sets/src/mage/cards/w/WanderingMage.java index af772345bdd..662a8afe48d 100644 --- a/Mage.Sets/src/mage/cards/w/WanderingMage.java +++ b/Mage.Sets/src/mage/cards/w/WanderingMage.java @@ -16,6 +16,7 @@ import mage.constants.SubType; import mage.counters.CounterType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetPlayerOrPlaneswalker; @@ -53,7 +54,7 @@ public final class WanderingMage extends CardImpl { // {U}: Prevent the next 1 damage that would be dealt to target Cleric or Wizard creature this turn. ability = new SimpleActivatedAbility( new PreventDamageToTargetEffect(Duration.EndOfTurn, 1), new ManaCostsImpl<>("{U}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); // {B}, Put a -1/-1 counter on a creature you control: Prevent the next 2 damage that would be dealt to target player this turn. diff --git a/Mage.Sets/src/mage/cards/w/WanderingTroubadour.java b/Mage.Sets/src/mage/cards/w/WanderingTroubadour.java index 528a864a7d8..39410e4e51a 100644 --- a/Mage.Sets/src/mage/cards/w/WanderingTroubadour.java +++ b/Mage.Sets/src/mage/cards/w/WanderingTroubadour.java @@ -1,20 +1,19 @@ package mage.cards.w; -import java.util.UUID; import mage.MageInt; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.common.LandfallCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect; import mage.abilities.hint.common.CurrentDungeonHint; -import mage.constants.SubType; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SubType; import mage.watchers.common.LandfallWatcher; +import java.util.UUID; + /** - * * @author weirddan455 */ public final class WanderingTroubadour extends CardImpl { @@ -28,11 +27,8 @@ public final class WanderingTroubadour extends CardImpl { this.toughness = new MageInt(2); // At the beginning of your end step, if you had a land enter the battlefield under your control this turn, venture into the dungeon. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility(new VentureIntoTheDungeonEffect()), - LandfallCondition.instance, - "At the beginning of your end step, if you had a land enter the battlefield under your control this turn, venture into the dungeon." - ).addHint(CurrentDungeonHint.instance), new LandfallWatcher()); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new VentureIntoTheDungeonEffect()) + .withInterveningIf(LandfallCondition.instance).addHint(CurrentDungeonHint.instance), new LandfallWatcher()); } private WanderingTroubadour(final WanderingTroubadour card) { diff --git a/Mage.Sets/src/mage/cards/w/WarTorchGoblin.java b/Mage.Sets/src/mage/cards/w/WarTorchGoblin.java index f2563f0242d..bf2af820e32 100644 --- a/Mage.Sets/src/mage/cards/w/WarTorchGoblin.java +++ b/Mage.Sets/src/mage/cards/w/WarTorchGoblin.java @@ -15,6 +15,7 @@ import mage.constants.SubType; import mage.constants.ColoredManaSymbol; import mage.constants.Zone; import mage.filter.common.FilterBlockingCreature; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -34,7 +35,7 @@ public final class WarTorchGoblin extends CardImpl { // {R}, Sacrifice War-Torch Goblin: War-Torch Goblin deals 2 damage to target blocking creature. Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(2, "it"), new ColoredManaCost(ColoredManaSymbol.R)); ability.addCost(new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(new FilterBlockingCreature())); + ability.addTarget(new TargetPermanent(new FilterBlockingCreature())); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/w/WarchanterSkald.java b/Mage.Sets/src/mage/cards/w/WarchanterSkald.java index 9ab4d48ddd6..7308b19695c 100644 --- a/Mage.Sets/src/mage/cards/w/WarchanterSkald.java +++ b/Mage.Sets/src/mage/cards/w/WarchanterSkald.java @@ -1,20 +1,18 @@ package mage.cards.w; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.BecomesTappedSourceTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.condition.OrCondition; +import mage.abilities.condition.common.EnchantedSourceCondition; +import mage.abilities.condition.common.EquippedSourceCondition; 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.Game; -import mage.game.permanent.Permanent; import mage.game.permanent.token.DwarfBerserkerToken; -import java.util.Objects; import java.util.UUID; /** @@ -22,6 +20,12 @@ import java.util.UUID; */ public final class WarchanterSkald extends CardImpl { + private static final Condition condition = new OrCondition( + "it's enchanted or equipped", + new EnchantedSourceCondition(), + EquippedSourceCondition.instance + ); + public WarchanterSkald(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); @@ -31,11 +35,7 @@ public final class WarchanterSkald extends CardImpl { this.toughness = new MageInt(3); // Whenever Warchanter Skald becomes tapped, if it's enchanted or equipped, create a 2/1 red Dwarf Berserker creature token. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BecomesTappedSourceTriggeredAbility(new CreateTokenEffect(new DwarfBerserkerToken())), - WarchanterSkaldCondition.instance, "Whenever {this} becomes tapped, " + - "if it's enchanted or equipped, create a 2/1 red Dwarf Berserker creature token." - )); + this.addAbility(new BecomesTappedSourceTriggeredAbility(new CreateTokenEffect(new DwarfBerserkerToken())).withInterveningIf(condition)); } private WarchanterSkald(final WarchanterSkald card) { @@ -47,18 +47,3 @@ public final class WarchanterSkald extends CardImpl { return new WarchanterSkald(this); } } - -enum WarchanterSkaldCondition implements Condition { - instance; - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = source.getSourcePermanentOrLKI(game); - return permanent != null && permanent - .getAttachments() - .stream() - .map(game::getPermanent) - .filter(Objects::nonNull) - .anyMatch(p -> p.hasSubtype(SubType.AURA, game) || p.hasSubtype(SubType.EQUIPMENT, game)); - } -} diff --git a/Mage.Sets/src/mage/cards/w/WarkiteMarauder.java b/Mage.Sets/src/mage/cards/w/WarkiteMarauder.java index 6ce6825f1dd..de5f5ca75f6 100644 --- a/Mage.Sets/src/mage/cards/w/WarkiteMarauder.java +++ b/Mage.Sets/src/mage/cards/w/WarkiteMarauder.java @@ -16,6 +16,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.DefendingPlayerControlsSourceAttackingPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -45,7 +46,7 @@ public final class WarkiteMarauder extends CardImpl { .setText("target creature defending player controls loses all abilities"), false); ability.addEffect(new SetBasePowerToughnessTargetEffect(0, 1, Duration.EndOfTurn) .setText("and has base power and toughness 0/1 until end of turn")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/w/WarpingWail.java b/Mage.Sets/src/mage/cards/w/WarpingWail.java index 88f62df69ea..32d44adf4fe 100644 --- a/Mage.Sets/src/mage/cards/w/WarpingWail.java +++ b/Mage.Sets/src/mage/cards/w/WarpingWail.java @@ -16,6 +16,7 @@ import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.PowerPredicate; import mage.filter.predicate.mageobject.ToughnessPredicate; import mage.game.permanent.token.EldraziScionToken; +import mage.target.TargetPermanent; import mage.target.TargetSpell; import mage.target.common.TargetCreaturePermanent; @@ -42,7 +43,7 @@ public final class WarpingWail extends CardImpl { Effect effect = new ExileTargetEffect(); effect.setText("Exile target creature with power or toughness 1 or less."); this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filterCreature)); + this.getSpellAbility().addTarget(new TargetPermanent(filterCreature)); // Counter target sorcery spell. Mode mode = new Mode(new CounterTargetEffect()); diff --git a/Mage.Sets/src/mage/cards/w/WastescapeBattlemage.java b/Mage.Sets/src/mage/cards/w/WastescapeBattlemage.java index 1567b3ee686..75d5e4812b0 100644 --- a/Mage.Sets/src/mage/cards/w/WastescapeBattlemage.java +++ b/Mage.Sets/src/mage/cards/w/WastescapeBattlemage.java @@ -1,9 +1,9 @@ package mage.cards.w; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.KickedCostCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CastSourceTriggeredAbility; import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect; @@ -14,10 +14,9 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.TargetController; import mage.filter.FilterPermanent; -import mage.filter.StaticFilters; import mage.filter.common.FilterArtifactOrEnchantmentPermanent; import mage.target.TargetPermanent; -import mage.target.common.TargetCreaturePermanent; +import mage.target.common.TargetOpponentsCreaturePermanent; import java.util.UUID; @@ -33,6 +32,9 @@ public final class WastescapeBattlemage extends CardImpl { filter.add(TargetController.OPPONENT.getControllerPredicate()); } + private static final Condition condition = new KickedCostCondition("{G}"); + private static final Condition condition2 = new KickedCostCondition("{1}{U}"); + public WastescapeBattlemage(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{C}"); @@ -47,16 +49,14 @@ public final class WastescapeBattlemage extends CardImpl { this.addAbility(kickerAbility); // When you cast this spell, if it was kicked with its {G} kicker, exile target artifact or enchantment an opponent controls. - TriggeredAbility ability = new CastSourceTriggeredAbility(new ExileTargetEffect()); + Ability ability = new CastSourceTriggeredAbility(new ExileTargetEffect()).withInterveningIf(condition); ability.addTarget(new TargetPermanent(filter)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new KickedCostCondition("{G}"), - "When you cast this spell, if it was kicked with its {G} kicker, exile target artifact or enchantment an opponent controls.")); + this.addAbility(ability); // When you cast this spell, if it was kicked with its {1}{U} kicker, return target creature an opponent controls to its owner's hand. - TriggeredAbility ability2 = new CastSourceTriggeredAbility(new ReturnToHandTargetEffect()); - ability2.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability2, new KickedCostCondition("{1}{U}"), - "When you cast this spell, if it was kicked with its {1}{U} kicker, return target creature an opponent controls to its owner's hand.")); + ability = new CastSourceTriggeredAbility(new ReturnToHandTargetEffect()).withInterveningIf(condition2); + ability.addTarget(new TargetOpponentsCreaturePermanent()); + this.addAbility(ability); } private WastescapeBattlemage(final WastescapeBattlemage card) { diff --git a/Mage.Sets/src/mage/cards/w/WatcherOfTheSpheres.java b/Mage.Sets/src/mage/cards/w/WatcherOfTheSpheres.java index 636e7aa952d..2789d8db7d7 100644 --- a/Mage.Sets/src/mage/cards/w/WatcherOfTheSpheres.java +++ b/Mage.Sets/src/mage/cards/w/WatcherOfTheSpheres.java @@ -1,7 +1,7 @@ package mage.cards.w; import mage.MageInt; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; @@ -11,7 +11,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreatureCard; @@ -26,8 +25,8 @@ import java.util.UUID; public final class WatcherOfTheSpheres extends CardImpl { - private static final FilterCreatureCard filter = new FilterCreatureCard("Creature spells with flying"); - private static final FilterPermanent filter1 = new FilterControlledCreaturePermanent("another creature with flying"); + private static final FilterCreatureCard filter = new FilterCreatureCard("creature spells with flying"); + private static final FilterPermanent filter1 = new FilterControlledCreaturePermanent("another creature you control with flying"); static { filter.add(new AbilityPredicate(FlyingAbility.class)); @@ -50,7 +49,9 @@ public final class WatcherOfTheSpheres extends CardImpl { this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1))); // Whenever another creature with flying you control enters, Watcher of the Spheres gets +1/+1 until end of turn. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 1, Duration.EndOfTurn), filter1, false)); + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + new BoostSourceEffect(1, 1, Duration.EndOfTurn), filter1 + )); } private WatcherOfTheSpheres(final WatcherOfTheSpheres card) { diff --git a/Mage.Sets/src/mage/cards/w/WaterspoutElemental.java b/Mage.Sets/src/mage/cards/w/WaterspoutElemental.java index 38716a7d57f..26a3e86450a 100644 --- a/Mage.Sets/src/mage/cards/w/WaterspoutElemental.java +++ b/Mage.Sets/src/mage/cards/w/WaterspoutElemental.java @@ -1,11 +1,9 @@ - package mage.cards.w; -import java.util.UUID; import mage.MageInt; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToHandFromBattlefieldAllEffect; import mage.abilities.effects.common.turn.SkipNextTurnSourceEffect; import mage.abilities.keyword.FlyingAbility; @@ -17,8 +15,9 @@ import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; +import java.util.UUID; + /** - * * @author LoneFox */ public final class WaterspoutElemental extends CardImpl { @@ -30,20 +29,21 @@ public final class WaterspoutElemental extends CardImpl { } public WaterspoutElemental(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}"); this.subtype.add(SubType.ELEMENTAL); this.power = new MageInt(3); this.toughness = new MageInt(4); // Kicker {U} this.addAbility(new KickerAbility("{U}")); + // Flying this.addAbility(FlyingAbility.getInstance()); + // When Waterspout Elemental enters the battlefield, if it was kicked, return all other creatures to their owners' hands and you skip your next turn. - EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandFromBattlefieldAllEffect(filter)); - ability.addEffect(new SkipNextTurnSourceEffect()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.ONCE, - "When {this} enters, if it was kicked, return all other creatures to their owners' hands and you skip your next turn.")); + Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnToHandFromBattlefieldAllEffect(filter)).withInterveningIf(KickedCondition.ONCE); + ability.addEffect(new SkipNextTurnSourceEffect().concatBy("and")); + this.addAbility(ability); } private WaterspoutElemental(final WaterspoutElemental card) { diff --git a/Mage.Sets/src/mage/cards/w/WaterspoutWarden.java b/Mage.Sets/src/mage/cards/w/WaterspoutWarden.java index b464c08d1dd..c81394c0420 100644 --- a/Mage.Sets/src/mage/cards/w/WaterspoutWarden.java +++ b/Mage.Sets/src/mage/cards/w/WaterspoutWarden.java @@ -5,7 +5,6 @@ import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -35,12 +34,9 @@ public final class WaterspoutWarden extends CardImpl { this.toughness = new MageInt(2); // Whenever Waterspout Warden attacks, if another creature entered the battlefield under your control this turn, Waterspout Warden gains flying until end of turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new GainAbilitySourceEffect( - FlyingAbility.getInstance(), Duration.EndOfTurn - )), WaterspoutWardenCondition.instance, "Whenever {this} attacks, if another creature entered " + - "the battlefield under your control this turn, {this} gains flying until end of turn." - ), new WaterspoutWardenWatcher()); + this.addAbility(new AttacksTriggeredAbility(new GainAbilitySourceEffect( + FlyingAbility.getInstance(), Duration.EndOfTurn + )).withInterveningIf(WaterspoutWardenCondition.instance), new WaterspoutWardenWatcher()); } private WaterspoutWarden(final WaterspoutWarden card) { @@ -60,6 +56,11 @@ enum WaterspoutWardenCondition implements Condition { public boolean apply(Game game, Ability source) { return WaterspoutWardenWatcher.checkPermanent(game, source); } + + @Override + public String toString() { + return "another creature entered the battlefield under your control this turn"; + } } class WaterspoutWardenWatcher extends Watcher { diff --git a/Mage.Sets/src/mage/cards/w/WatertrapWeaver.java b/Mage.Sets/src/mage/cards/w/WatertrapWeaver.java index 69117a4272b..baebf8288df 100644 --- a/Mage.Sets/src/mage/cards/w/WatertrapWeaver.java +++ b/Mage.Sets/src/mage/cards/w/WatertrapWeaver.java @@ -11,8 +11,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author TheElk801 @@ -30,7 +33,7 @@ public final class WatertrapWeaver extends CardImpl { // When Watertrap Weaver enters the battlefield, tap target creature an opponent controls. That creature doesn't untap during its controller's next untap step. EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new TapTargetEffect()); ability.addEffect(new DontUntapInControllersNextUntapStepTargetEffect("that creature")); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/w/WaveOfRats.java b/Mage.Sets/src/mage/cards/w/WaveOfRats.java index 76977bd1c24..d45d161bfcd 100644 --- a/Mage.Sets/src/mage/cards/w/WaveOfRats.java +++ b/Mage.Sets/src/mage/cards/w/WaveOfRats.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlSourceEffect; import mage.abilities.keyword.BlitzAbility; import mage.abilities.keyword.TrampleAbility; @@ -34,12 +33,8 @@ public class WaveOfRats extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // When Wave of Rats dies, if it dealt combat damage to a player this turn, return it to the battlefield under its owner’s control. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new DiesSourceTriggeredAbility(new ReturnToBattlefieldUnderOwnerControlSourceEffect()), - WaveOfRatsDealtDamageToPlayerCondition.instance, - "When Wave of Rats dies, if it dealt combat damage to a player this turn, return it to the battlefield under its owner's control."), - new DamageDoneWatcher() - ); + this.addAbility(new DiesSourceTriggeredAbility(new ReturnToBattlefieldUnderOwnerControlSourceEffect().setText("return it to the battlefield under its owner's control")) + .withInterveningIf(WaveOfRatsDealtDamageToPlayerCondition.instance), new DamageDoneWatcher()); // Blitz {4}{B} (If you cast this spell for its blitz cost, it gains haste and “When this creature dies, draw a card.” Sacrifice it at the beginning of the next end step.) this.addAbility(new BlitzAbility(this, "{4}{B}")); @@ -70,4 +65,9 @@ enum WaveOfRatsDealtDamageToPlayerCondition implements Condition { } return watcher.damagedAPlayer(waveOfRats.getId(), waveOfRats.getZoneChangeCounter(game), game); } + + @Override + public String toString() { + return "it dealt combat damage to a player this turn"; + } } diff --git a/Mage.Sets/src/mage/cards/w/WavecrashTriton.java b/Mage.Sets/src/mage/cards/w/WavecrashTriton.java index 902c3bfb60d..20dde47ffdf 100644 --- a/Mage.Sets/src/mage/cards/w/WavecrashTriton.java +++ b/Mage.Sets/src/mage/cards/w/WavecrashTriton.java @@ -12,8 +12,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -30,7 +33,7 @@ public final class WavecrashTriton extends CardImpl { // Heroic - Whenever you cast a spell that targets Wavecrash Triton, tap target creature an opponent controls. That creature doesn't untap during its controller's next untap step. Ability ability = new HeroicAbility(new TapTargetEffect()); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); ability.addEffect(new DontUntapInControllersNextUntapStepTargetEffect("That creature")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/w/WaylayingPirates.java b/Mage.Sets/src/mage/cards/w/WaylayingPirates.java index 5f8a6d9c807..52106b352f2 100644 --- a/Mage.Sets/src/mage/cards/w/WaylayingPirates.java +++ b/Mage.Sets/src/mage/cards/w/WaylayingPirates.java @@ -5,7 +5,6 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.TapTargetEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.hint.ConditionHint; @@ -16,6 +15,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.counters.CounterType; import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledArtifactPermanent; import mage.target.TargetPermanent; import java.util.UUID; @@ -25,8 +25,10 @@ import java.util.UUID; */ public final class WaylayingPirates extends CardImpl { - private static final Condition condition = new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT); - private static final Hint hint = new ConditionHint(condition, "You control an artifact"); + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterControlledArtifactPermanent("you control an artifact") + ); + private static final Hint hint = new ConditionHint(condition); public WaylayingPirates(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); @@ -37,12 +39,8 @@ public final class WaylayingPirates extends CardImpl { this.toughness = new MageInt(3); // When Waylaying Pirates enters the battlefield, if you control an artifact, tap target artifact or creature an opponent controls and put a stun counter on it. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new TapTargetEffect()), - condition, "When {this} enters, if you control an artifact, " + - "tap target artifact or creature an opponent controls and put a stun counter on it." - ); - ability.addEffect(new AddCountersTargetEffect(CounterType.STUN.createInstance())); + Ability ability = new EntersBattlefieldTriggeredAbility(new TapTargetEffect()).withInterveningIf(condition); + ability.addEffect(new AddCountersTargetEffect(CounterType.STUN.createInstance()).setText("and put a stun counter on it")); ability.addTarget(new TargetPermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_ARTIFACT_OR_CREATURE)); this.addAbility(ability.addHint(hint)); } diff --git a/Mage.Sets/src/mage/cards/w/WaytaTrainerProdigy.java b/Mage.Sets/src/mage/cards/w/WaytaTrainerProdigy.java index c7e7e20a89e..cf67c8fc49c 100644 --- a/Mage.Sets/src/mage/cards/w/WaytaTrainerProdigy.java +++ b/Mage.Sets/src/mage/cards/w/WaytaTrainerProdigy.java @@ -24,12 +24,15 @@ import mage.game.events.GameEvent; import mage.game.events.NumberOfTriggersEvent; import mage.game.permanent.Permanent; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import mage.util.CardUtil; import java.util.UUID; +import static mage.filter.StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2; + /** * @@ -60,7 +63,7 @@ public final class WaytaTrainerProdigy extends CardImpl { ability.addTarget(controlledTarget); Target secondTarget = - new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_CREATURE_TARGET_2).setTargetTag(2); + new TargetPermanent(FILTER_ANOTHER_CREATURE_TARGET_2).setTargetTag(2); ability.addTarget(secondTarget); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/w/WeatheredWayfarer.java b/Mage.Sets/src/mage/cards/w/WeatheredWayfarer.java index 5805aa12f84..571a4af7fd4 100644 --- a/Mage.Sets/src/mage/cards/w/WeatheredWayfarer.java +++ b/Mage.Sets/src/mage/cards/w/WeatheredWayfarer.java @@ -1,10 +1,9 @@ - package mage.cards.w; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.OpponentControlsMoreCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; @@ -13,19 +12,20 @@ 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.FilterLandCard; import mage.target.common.TargetCardInLibrary; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class WeatheredWayfarer extends CardImpl { + private static final Condition condition = new OpponentControlsMoreCondition(StaticFilters.FILTER_LANDS); + public WeatheredWayfarer(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.NOMAD); this.subtype.add(SubType.CLERIC); @@ -35,10 +35,10 @@ public final class WeatheredWayfarer extends CardImpl { // {W}, {tap}: Search your library for a land card, reveal it, and put it into your hand. Then shuffle your library. Activate this ability only if an opponent controls more lands than you. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, - new SearchLibraryPutInHandEffect(new TargetCardInLibrary(new FilterLandCard()), true), - new ManaCostsImpl<>("{W}"), - new OpponentControlsMoreCondition(StaticFilters.FILTER_LANDS)); + new SearchLibraryPutInHandEffect( + new TargetCardInLibrary(StaticFilters.FILTER_CARD_LAND_A), true + ), new ManaCostsImpl<>("{W}"), condition + ); ability.addCost(new TapSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/w/WeatherseedTotem.java b/Mage.Sets/src/mage/cards/w/WeatherseedTotem.java index 7a7a03a5c22..e7cdf48fcd2 100644 --- a/Mage.Sets/src/mage/cards/w/WeatherseedTotem.java +++ b/Mage.Sets/src/mage/cards/w/WeatherseedTotem.java @@ -5,7 +5,6 @@ import mage.abilities.common.PutIntoGraveFromBattlefieldSourceTriggeredAbility; 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.common.ReturnSourceFromGraveyardToHandEffect; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.keyword.TrampleAbility; @@ -43,11 +42,9 @@ public final class WeatherseedTotem extends CardImpl { ), new ManaCostsImpl<>("{2}{G}{G}{G}"))); // When Weatherseed Totem is put into a graveyard from the battlefield, if it was a creature, return this card to its owner's hand. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new PutIntoGraveFromBattlefieldSourceTriggeredAbility(new ReturnSourceFromGraveyardToHandEffect()), - WeatherseedTotemCondition.instance, "When {this} is put into a graveyard from the battlefield, " - + "if it was a creature, return this card to its owner's hand" - )); + this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility( + new ReturnSourceFromGraveyardToHandEffect().setText("return this card to its owner's hand") + ).withInterveningIf(WeatherseedTotemCondition.instance)); } private WeatherseedTotem(final WeatherseedTotem card) { @@ -69,4 +66,9 @@ enum WeatherseedTotemCondition implements Condition { .getEffectValueFromAbility(source, "permanentWasCreature", Boolean.class) .orElse(false); } + + @Override + public String toString() { + return "it was a creature"; + } } diff --git a/Mage.Sets/src/mage/cards/w/WeaverOfLies.java b/Mage.Sets/src/mage/cards/w/WeaverOfLies.java index e52eacded1b..23d2e47dd66 100644 --- a/Mage.Sets/src/mage/cards/w/WeaverOfLies.java +++ b/Mage.Sets/src/mage/cards/w/WeaverOfLies.java @@ -1,11 +1,8 @@ - package mage.cards.w; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.TurnedFaceUpSourceTriggeredAbility; -import mage.constants.SubType; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.BecomesFaceDownCreatureAllEffect; @@ -14,6 +11,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicate; import mage.filter.predicate.Predicates; @@ -22,10 +20,11 @@ import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.game.Game; import mage.target.Target; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class WeaverOfLies extends CardImpl { @@ -49,7 +48,7 @@ public final class WeaverOfLies extends CardImpl { // When Weaver of Lies is turned face up, turn any number of target creatures with a morph ability other than Weaver of Lies face down. Ability ability = new TurnedFaceUpSourceTriggeredAbility(new WeaverOfLiesEffect(), false, false); - ability.addTarget(new TargetCreaturePermanent(0, Integer.MAX_VALUE, filter, false)); + ability.addTarget(new TargetPermanent(0, Integer.MAX_VALUE, filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/w/WeaverOfLightning.java b/Mage.Sets/src/mage/cards/w/WeaverOfLightning.java index 6e9c4cc3ccd..fe7c2d46ba6 100644 --- a/Mage.Sets/src/mage/cards/w/WeaverOfLightning.java +++ b/Mage.Sets/src/mage/cards/w/WeaverOfLightning.java @@ -11,8 +11,11 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -30,7 +33,7 @@ public final class WeaverOfLightning extends CardImpl { this.addAbility(ReachAbility.getInstance()); // Whenever you cast an instant or sorcery spell, Weaver of Lightning deals 1 damage to target creature an opponent controls. Ability ability = new SpellCastControllerTriggeredAbility(new DamageTargetEffect(1), StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/w/WebstrikeElite.java b/Mage.Sets/src/mage/cards/w/WebstrikeElite.java index bc5997fa765..3a2995fc469 100644 --- a/Mage.Sets/src/mage/cards/w/WebstrikeElite.java +++ b/Mage.Sets/src/mage/cards/w/WebstrikeElite.java @@ -1,9 +1,10 @@ package mage.cards.w; import mage.MageInt; -import mage.abilities.common.ZoneChangeTriggeredAbility; +import mage.abilities.Ability; +import mage.abilities.common.CycleTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.dynamicvalue.common.GetXValue; +import mage.abilities.dynamicvalue.common.EffectKeyValue; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.CyclingAbility; import mage.abilities.keyword.ReachAbility; @@ -12,14 +13,10 @@ 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.common.FilterArtifactOrEnchantmentPermanent; -import mage.filter.predicate.mageobject.ManaValuePredicate; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.stack.StackObject; import mage.target.TargetPermanent; +import mage.target.targetadjustment.ManaValueTargetAdjuster; import java.util.UUID; @@ -28,6 +25,8 @@ import java.util.UUID; */ public final class WebstrikeElite extends CardImpl { + private static final FilterPermanent filter = new FilterArtifactOrEnchantmentPermanent("artifact or enchantment with mana value X"); + public WebstrikeElite(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{G}"); @@ -43,7 +42,10 @@ public final class WebstrikeElite extends CardImpl { this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{X}{G}{G}"))); // When you cycle this card, destroy up to one target artifact or enchantment with mana value X. - this.addAbility(new WebstrikeEliteTriggeredAbility()); + Ability ability = new CycleTriggeredAbility(new DestroyTargetEffect()); + ability.addTarget(new TargetPermanent(0, 1, filter)); + ability.setTargetAdjuster(new ManaValueTargetAdjuster(new EffectKeyValue("cycleXValue"), ComparisonType.EQUAL_TO)); + this.addAbility(ability); } private WebstrikeElite(final WebstrikeElite card) { @@ -55,47 +57,3 @@ public final class WebstrikeElite extends CardImpl { return new WebstrikeElite(this); } } - -class WebstrikeEliteTriggeredAbility extends ZoneChangeTriggeredAbility { - - WebstrikeEliteTriggeredAbility() { - super(Zone.ALL, new DestroyTargetEffect(), "", false); - } - - private WebstrikeEliteTriggeredAbility(final WebstrikeEliteTriggeredAbility ability) { - super(ability); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ACTIVATED_ABILITY; - } - - @Override - public WebstrikeEliteTriggeredAbility copy() { - return new WebstrikeEliteTriggeredAbility(this); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (!event.getSourceId().equals(this.getSourceId())) { - return false; - } - StackObject object = game.getStack().getStackObject(event.getSourceId()); - if (object == null || !(object.getStackAbility() instanceof CyclingAbility)) { - return false; - } - FilterPermanent filter = new FilterArtifactOrEnchantmentPermanent("artifact or enchantment with mana value X"); - filter.add(new ManaValuePredicate( - ComparisonType.EQUAL_TO, GetXValue.instance.calculate(game, object.getStackAbility(), null) - )); - this.getTargets().clear(); - this.addTarget(new TargetPermanent(0, 1, filter)); - return true; - } - - @Override - public String getRule() { - return "When you cycle this card, destroy up to one target artifact or enchantment with mana value X."; - } -} diff --git a/Mage.Sets/src/mage/cards/w/WebweaverChangeling.java b/Mage.Sets/src/mage/cards/w/WebweaverChangeling.java index e0fd5c9f4da..393acd48945 100644 --- a/Mage.Sets/src/mage/cards/w/WebweaverChangeling.java +++ b/Mage.Sets/src/mage/cards/w/WebweaverChangeling.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.CardsInControllerGraveyardCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.keyword.ChangelingAbility; import mage.abilities.keyword.ReachAbility; @@ -22,7 +21,7 @@ import java.util.UUID; public final class WebweaverChangeling extends CardImpl { private static final Condition condition - = new CardsInControllerGraveyardCondition(3, StaticFilters.FILTER_CARD_CREATURE); + = new CardsInControllerGraveyardCondition(3, StaticFilters.FILTER_CARD_CREATURES); public WebweaverChangeling(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}"); @@ -38,11 +37,7 @@ public final class WebweaverChangeling extends CardImpl { this.addAbility(ReachAbility.getInstance()); // When Webweaver Changeling enters the battlefield, if there are three or more creature cards in your graveyard, you gain 5 life. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new GainLifeEffect(5)), condition, - "When {this} enters, if there are three or more " + - "creature cards in your graveyard, you gain 5 life." - )); + this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(5)).withInterveningIf(condition)); } private WebweaverChangeling(final WebweaverChangeling card) { diff --git a/Mage.Sets/src/mage/cards/w/WeddingRing.java b/Mage.Sets/src/mage/cards/w/WeddingRing.java index 08402474cca..e62812386e1 100644 --- a/Mage.Sets/src/mage/cards/w/WeddingRing.java +++ b/Mage.Sets/src/mage/cards/w/WeddingRing.java @@ -4,7 +4,6 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromEverywhereSourceCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenCopyTargetEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; @@ -35,11 +34,8 @@ public final class WeddingRing extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{W}{W}"); // When Wedding Ring enters the battlefield, if it was cast, target opponent creates a token that's a copy of it. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new WeddingRingEffect()), - CastFromEverywhereSourceCondition.instance, "When {this} enters, " + - "if it was cast, target opponent creates a token that's a copy of it." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new WeddingRingEffect()) + .withInterveningIf(CastFromEverywhereSourceCondition.instance); ability.addTarget(new TargetOpponent()); this.addAbility(ability); @@ -64,6 +60,7 @@ class WeddingRingEffect extends OneShotEffect { WeddingRingEffect() { super(Outcome.Benefit); + staticText = "target opponent creates a token that's a copy of it"; } private WeddingRingEffect(final WeddingRingEffect effect) { diff --git a/Mage.Sets/src/mage/cards/w/WeedPrunerPoplar.java b/Mage.Sets/src/mage/cards/w/WeedPrunerPoplar.java index 7e337a7ab21..afcad218844 100644 --- a/Mage.Sets/src/mage/cards/w/WeedPrunerPoplar.java +++ b/Mage.Sets/src/mage/cards/w/WeedPrunerPoplar.java @@ -13,6 +13,7 @@ import mage.constants.SubType; import mage.constants.Duration; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -36,7 +37,7 @@ public final class WeedPrunerPoplar extends CardImpl { // At the beginning of your upkeep, target creature other than Weed-Pruner Poplar gets -1/-1 until end of turn. Ability ability = new BeginningOfUpkeepTriggeredAbility(new BoostTargetEffect(-1, -1, Duration.EndOfTurn)); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/w/WeightOfConscience.java b/Mage.Sets/src/mage/cards/w/WeightOfConscience.java index b7218100ba9..063c4dec9a6 100644 --- a/Mage.Sets/src/mage/cards/w/WeightOfConscience.java +++ b/Mage.Sets/src/mage/cards/w/WeightOfConscience.java @@ -14,6 +14,7 @@ import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.Predicate; import mage.filter.predicate.mageobject.SharesCreatureTypePredicate; import mage.filter.predicate.permanent.TappedPredicate; @@ -21,7 +22,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPermanent; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.*; @@ -59,9 +60,9 @@ public final class WeightOfConscience extends CardImpl { } } -class WeightOfConscienceTarget extends TargetControlledCreaturePermanent { +class WeightOfConscienceTarget extends TargetControlledPermanent { - private static final FilterControlledCreaturePermanent filterUntapped = new FilterControlledCreaturePermanent("untapped creatures you control that share a creature type"); + private static final FilterControlledPermanent filterUntapped = new FilterControlledCreaturePermanent("untapped creatures you control that share a creature type"); static { filterUntapped.add(TappedPredicate.UNTAPPED); diff --git a/Mage.Sets/src/mage/cards/w/WelcomingVampire.java b/Mage.Sets/src/mage/cards/w/WelcomingVampire.java index 1b3ffd7a0c2..507783572ea 100644 --- a/Mage.Sets/src/mage/cards/w/WelcomingVampire.java +++ b/Mage.Sets/src/mage/cards/w/WelcomingVampire.java @@ -21,7 +21,7 @@ import java.util.UUID; */ public final class WelcomingVampire extends CardImpl { - private static final FilterPermanent filter = new FilterControlledCreaturePermanent("one or more other creatures with power 2 or less"); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("one or more other creatures you control with power 2 or less"); static { filter.add(AnotherPredicate.instance); diff --git a/Mage.Sets/src/mage/cards/w/WellOfDiscovery.java b/Mage.Sets/src/mage/cards/w/WellOfDiscovery.java index 82c184366f2..68d0d68d94b 100644 --- a/Mage.Sets/src/mage/cards/w/WellOfDiscovery.java +++ b/Mage.Sets/src/mage/cards/w/WellOfDiscovery.java @@ -1,38 +1,37 @@ - package mage.cards.w; -import java.util.UUID; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; -import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledLandPermanent; import mage.filter.predicate.permanent.TappedPredicate; +import java.util.UUID; + /** - * * @author LoneFox */ public final class WellOfDiscovery extends CardImpl { - private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent(); + private static final FilterPermanent filter = new FilterControlledLandPermanent("you control no untapped lands"); static { filter.add(TappedPredicate.UNTAPPED); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.EQUAL_TO, 0); + public WellOfDiscovery(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{6}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}"); // At the beginning of your end step, if you control no untapped lands, draw a card. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfEndStepTriggeredAbility( - new DrawCardSourceControllerEffect(1)), - new InvertCondition(new PermanentsOnTheBattlefieldCondition(filter)), - "At the beginning of your end step, if you control no untapped lands, draw a card.")); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new DrawCardSourceControllerEffect(1)).withInterveningIf(condition)); } private WellOfDiscovery(final WellOfDiscovery card) { diff --git a/Mage.Sets/src/mage/cards/w/WellOfLife.java b/Mage.Sets/src/mage/cards/w/WellOfLife.java index 003a4b691d7..6d6a2043da0 100644 --- a/Mage.Sets/src/mage/cards/w/WellOfLife.java +++ b/Mage.Sets/src/mage/cards/w/WellOfLife.java @@ -1,37 +1,38 @@ package mage.cards.w; -import java.util.UUID; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; -import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledLandPermanent; import mage.filter.predicate.permanent.TappedPredicate; +import java.util.UUID; + /** - * * @author LoneFox */ public final class WellOfLife extends CardImpl { - private static final FilterControlledLandPermanent filter = new FilterControlledLandPermanent(); + private static final FilterPermanent filter = new FilterControlledLandPermanent("you control no untapped lands"); static { filter.add(TappedPredicate.UNTAPPED); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.EQUAL_TO, 0); + public WellOfLife(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); // At the beginning of your end step, if you control no untapped lands, you gain 2 life. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfEndStepTriggeredAbility( - new GainLifeEffect(2)), new InvertCondition(new PermanentsOnTheBattlefieldCondition(filter)), - "At the beginning of your end step, if you control no untapped lands, you gain 2 life.")); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new GainLifeEffect(2)).withInterveningIf(condition)); } private WellOfLife(final WellOfLife card) { diff --git a/Mage.Sets/src/mage/cards/w/WellgabberApothecary.java b/Mage.Sets/src/mage/cards/w/WellgabberApothecary.java index 82797bc6f4d..19bd97e88bd 100644 --- a/Mage.Sets/src/mage/cards/w/WellgabberApothecary.java +++ b/Mage.Sets/src/mage/cards/w/WellgabberApothecary.java @@ -15,6 +15,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class WellgabberApothecary extends CardImpl { // {1}{W} : Prevent all damage that would be dealt to target tapped Merfolk or Kithkin creatuer this turn SimpleActivatedAbility ability = new SimpleActivatedAbility(new PreventDamageToTargetEffect(Duration.EndOfTurn, Integer.MAX_VALUE), new ManaCostsImpl<>("{1}{W}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/w/WerefoxBodyguard.java b/Mage.Sets/src/mage/cards/w/WerefoxBodyguard.java index b41bed744a6..d1d4ca8a24d 100644 --- a/Mage.Sets/src/mage/cards/w/WerefoxBodyguard.java +++ b/Mage.Sets/src/mage/cards/w/WerefoxBodyguard.java @@ -16,7 +16,7 @@ import mage.constants.SubType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AnotherPredicate; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -46,7 +46,7 @@ public final class WerefoxBodyguard extends CardImpl { // When Werefox Bodyguard enters the battlefield, exile up to one other target non-Fox creature until Werefox Bodyguard leaves the battlefield. Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect()); - ability.addTarget(new TargetCreaturePermanent(0, 1, filter, false)); + ability.addTarget(new TargetPermanent(0, 1, filter)); this.addAbility(ability); // {1}{W}, Sacrifice Werefox Bodyguard: You gain 2 life. diff --git a/Mage.Sets/src/mage/cards/w/WesternPaladin.java b/Mage.Sets/src/mage/cards/w/WesternPaladin.java index 1e814734d85..92a3545c42a 100644 --- a/Mage.Sets/src/mage/cards/w/WesternPaladin.java +++ b/Mage.Sets/src/mage/cards/w/WesternPaladin.java @@ -18,6 +18,7 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -41,7 +42,7 @@ public final class WesternPaladin extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new ManaCostsImpl<>("{B}{B}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); ability.addCost(new TapSourceCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/w/WhaleboneGlider.java b/Mage.Sets/src/mage/cards/w/WhaleboneGlider.java index c5fec2a8dc1..03492dbb68b 100644 --- a/Mage.Sets/src/mage/cards/w/WhaleboneGlider.java +++ b/Mage.Sets/src/mage/cards/w/WhaleboneGlider.java @@ -15,6 +15,7 @@ import mage.constants.ComparisonType; import mage.constants.Duration; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -41,7 +42,7 @@ public final class WhaleboneGlider extends CardImpl { new GenericManaCost(2) ); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/w/WhereAncientsTread.java b/Mage.Sets/src/mage/cards/w/WhereAncientsTread.java index e759b3d8b63..6d5644c4f9b 100644 --- a/Mage.Sets/src/mage/cards/w/WhereAncientsTread.java +++ b/Mage.Sets/src/mage/cards/w/WhereAncientsTread.java @@ -1,36 +1,39 @@ - package mage.cards.w; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; -import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** - * * @author Plopman */ - public final class WhereAncientsTread extends CardImpl { - - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a creature with power 5 or greater"); +public final class WhereAncientsTread extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("a creature you control with power 5 or greater"); + static { filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 4)); } public WhereAncientsTread(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{4}{R}"); - + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{R}"); // Whenever a creature with power 5 or greater you control enters, you may have Where Ancients Tread deal 5 damage to any target. - Ability ability = new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new DamageTargetEffect(5).setText("you may have {this} deal 5 damage to any target"), filter, true); + Ability ability = new EntersBattlefieldAllTriggeredAbility( + new DamageTargetEffect(5) + .setText("you may have {this} deal 5 damage to any target"), + filter, true + ); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/w/WhirlingDervish.java b/Mage.Sets/src/mage/cards/w/WhirlingDervish.java index 04625a17c03..cfff2e0e6dd 100644 --- a/Mage.Sets/src/mage/cards/w/WhirlingDervish.java +++ b/Mage.Sets/src/mage/cards/w/WhirlingDervish.java @@ -1,32 +1,27 @@ - package mage.cards.w; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; -import mage.abilities.TriggeredAbility; -import mage.abilities.common.OnEventTriggeredAbility; import mage.abilities.condition.common.DealtDamageToAnOpponent; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.ProtectionAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; 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.game.events.GameEvent; + +import java.util.UUID; /** - * * @author LevelX */ public final class WhirlingDervish extends CardImpl { - private static final String ruleText = "At the beginning of each end step, if {this} dealt damage to an opponent this turn, put a +1/+1 counter on it."; - public WhirlingDervish(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{G}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.MONK); @@ -36,9 +31,14 @@ public final class WhirlingDervish extends CardImpl { // Protection from black this.addAbility(ProtectionAbility.from(ObjectColor.BLACK)); + // At the beginning of each end step, if Whirling Dervish dealt damage to an opponent this turn, put a +1/+1 counter on it. - TriggeredAbility triggered = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of each end step", true, new AddCountersSourceEffect(CounterType.P1P1.createInstance())); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(triggered, DealtDamageToAnOpponent.instance, ruleText)); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.ANY, + new AddCountersSourceEffect(CounterType.P1P1.createInstance()) + .setText("put a +1/+1 counter on it"), + false, DealtDamageToAnOpponent.instance + )); } private WhirlingDervish(final WhirlingDervish card) { diff --git a/Mage.Sets/src/mage/cards/w/WhiskAway.java b/Mage.Sets/src/mage/cards/w/WhiskAway.java index aeda1bc88c6..93de2b9e7bb 100644 --- a/Mage.Sets/src/mage/cards/w/WhiskAway.java +++ b/Mage.Sets/src/mage/cards/w/WhiskAway.java @@ -11,6 +11,7 @@ import mage.filter.common.FilterAttackingOrBlockingCreature; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -26,7 +27,7 @@ public final class WhiskAway extends CardImpl { // Put target attacking or blocking creature on top of its owner's library. this.getSpellAbility().addEffect(new WhiskAwayEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private WhiskAway(final WhiskAway card) { diff --git a/Mage.Sets/src/mage/cards/w/WhiteGloveGourmand.java b/Mage.Sets/src/mage/cards/w/WhiteGloveGourmand.java index 8c8f068c4db..e8235d280eb 100644 --- a/Mage.Sets/src/mage/cards/w/WhiteGloveGourmand.java +++ b/Mage.Sets/src/mage/cards/w/WhiteGloveGourmand.java @@ -3,13 +3,12 @@ package mage.cards.w; import mage.MageInt; import mage.MageObjectReference; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.hint.ConditionHint; import mage.abilities.hint.Hint; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -42,11 +41,8 @@ public final class WhiteGloveGourmand extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new HumanSoldierToken(), 2))); // At the beginning of your end step, if another Human died under your control this turn, create a Food token. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility(new CreateTokenEffect(new FoodToken())), - WhiteGloveGourmandCondition.instance, - "At the beginning of your end step, if another Human died under your control this turn, create a Food token." - ).addHint(WhiteGloveGourmandCondition.hint), new WhiteGloveGourmandWatcher()); + this.addAbility(new BeginningOfEndStepTriggeredAbility(new CreateTokenEffect(new FoodToken())) + .withInterveningIf(WhiteGloveGourmandCondition.instance).addHint(WhiteGloveGourmandCondition.hint), new WhiteGloveGourmandWatcher()); } private WhiteGloveGourmand(final WhiteGloveGourmand card) { diff --git a/Mage.Sets/src/mage/cards/w/WickedPact.java b/Mage.Sets/src/mage/cards/w/WickedPact.java index 7af7624f848..c872ccf577c 100644 --- a/Mage.Sets/src/mage/cards/w/WickedPact.java +++ b/Mage.Sets/src/mage/cards/w/WickedPact.java @@ -1,26 +1,26 @@ package mage.cards.w; -import java.util.UUID; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.LoseLifeSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** - * * @author fireshoes */ public final class WickedPact extends CardImpl { public WickedPact(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}{B}"); // Destroy two target nonblack creatures. You lose 5 life. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(2, 2, StaticFilters.FILTER_PERMANENT_CREATURES_NON_BLACK, false)); + this.getSpellAbility().addTarget(new TargetPermanent(2, StaticFilters.FILTER_PERMANENT_CREATURES_NON_BLACK)); this.getSpellAbility().addEffect(new LoseLifeSourceControllerEffect(5)); } diff --git a/Mage.Sets/src/mage/cards/w/WickedSlumber.java b/Mage.Sets/src/mage/cards/w/WickedSlumber.java index 3e94e9849f8..1e5a0940f8d 100644 --- a/Mage.Sets/src/mage/cards/w/WickedSlumber.java +++ b/Mage.Sets/src/mage/cards/w/WickedSlumber.java @@ -1,6 +1,5 @@ package mage.cards.w; -import mage.MageItem; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.TapTargetEffect; @@ -12,8 +11,7 @@ import mage.constants.Outcome; import mage.counters.CounterType; import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.permanent.PermanentIdPredicate; +import mage.filter.predicate.permanent.PermanentReferenceInCollectionPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -87,13 +85,7 @@ class WickedSlumberEffect extends OneShotEffect { return true; } FilterPermanent filter = new FilterCreaturePermanent(); - filter.add(Predicates.or( - permanents - .stream() - .map(MageItem::getId) - .map(PermanentIdPredicate::new) - .collect(Collectors.toList()) - )); + filter.add(new PermanentReferenceInCollectionPredicate(permanents, game)); for (int i = 0; i < 2; i++) { TargetPermanent target = new TargetPermanent(filter); target.withNotTarget(true); diff --git a/Mage.Sets/src/mage/cards/w/WickerfolkThresher.java b/Mage.Sets/src/mage/cards/w/WickerfolkThresher.java index c22f8d62ab0..a0f3e10816c 100644 --- a/Mage.Sets/src/mage/cards/w/WickerfolkThresher.java +++ b/Mage.Sets/src/mage/cards/w/WickerfolkThresher.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.DeliriumCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.CardTypesInGraveyardCount; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; @@ -29,12 +28,10 @@ public final class WickerfolkThresher extends CardImpl { this.toughness = new MageInt(4); // Delirium -- Whenever Wickerfolk Thresher attacks, if there are four or more card types among cards in your graveyard, look at the top card of your library. If it's a land card, you may put it onto the battlefield. If you don't put the card onto the battlefield, put it into your hand. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new WickerfolkThresherEffect()), - DeliriumCondition.instance, "Whenever {this} attacks, if there are four or more card types " + - "among cards in your graveyard, look at the top card of your library. If it's a land card, you may " + - "put it onto the battlefield. If you don't put the card onto the battlefield, put it into your hand." - ).setAbilityWord(AbilityWord.DELIRIUM).addHint(CardTypesInGraveyardCount.YOU.getHint())); + this.addAbility(new AttacksTriggeredAbility(new WickerfolkThresherEffect()) + .withInterveningIf(DeliriumCondition.instance) + .setAbilityWord(AbilityWord.DELIRIUM) + .addHint(CardTypesInGraveyardCount.YOU.getHint())); } private WickerfolkThresher(final WickerfolkThresher card) { @@ -51,6 +48,8 @@ class WickerfolkThresherEffect extends OneShotEffect { WickerfolkThresherEffect() { super(Outcome.Benefit); + staticText = "look at the top card of your library. If it's a land card, you may put it onto the battlefield. " + + "If you don't put the card onto the battlefield, put it into your hand"; } private WickerfolkThresherEffect(final WickerfolkThresherEffect effect) { diff --git a/Mage.Sets/src/mage/cards/w/WildInstincts.java b/Mage.Sets/src/mage/cards/w/WildInstincts.java index eef26a7ebbf..eb6a829f5f3 100644 --- a/Mage.Sets/src/mage/cards/w/WildInstincts.java +++ b/Mage.Sets/src/mage/cards/w/WildInstincts.java @@ -12,9 +12,12 @@ import mage.constants.Duration; import mage.constants.TargetController; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE; + /** * * @author LevelX2 @@ -33,7 +36,7 @@ public final class WildInstincts extends CardImpl { "(Each deals damage equal to its power to the other.)"); getSpellAbility().addEffect(fightTargetsEffect); - getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE)); + getSpellAbility().addTarget(new TargetPermanent(FILTER_OPPONENTS_PERMANENT_CREATURE)); } private WildInstincts(final WildInstincts card) { diff --git a/Mage.Sets/src/mage/cards/w/WildernessHypnotist.java b/Mage.Sets/src/mage/cards/w/WildernessHypnotist.java index 795dd643a1c..f3a367217e3 100644 --- a/Mage.Sets/src/mage/cards/w/WildernessHypnotist.java +++ b/Mage.Sets/src/mage/cards/w/WildernessHypnotist.java @@ -17,6 +17,7 @@ import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class WildernessHypnotist extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(3); Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(-2, 0, Duration.EndOfTurn), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/w/WildwoodMentor.java b/Mage.Sets/src/mage/cards/w/WildwoodMentor.java index 283575f1e72..2c7461131db 100644 --- a/Mage.Sets/src/mage/cards/w/WildwoodMentor.java +++ b/Mage.Sets/src/mage/cards/w/WildwoodMentor.java @@ -18,6 +18,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.permanent.AttackingPredicate; import mage.filter.predicate.permanent.TokenPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -59,7 +60,7 @@ public final class WildwoodMentor extends CardImpl { .setText("another target attacking creature gets +X/+X until end of turn, where X is {this}'s power"), false ); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/w/WildwoodTracker.java b/Mage.Sets/src/mage/cards/w/WildwoodTracker.java index 80efe9ee458..7f957d121c1 100644 --- a/Mage.Sets/src/mage/cards/w/WildwoodTracker.java +++ b/Mage.Sets/src/mage/cards/w/WildwoodTracker.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.common.AttacksOrBlocksTriggeredAbility; 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.cards.CardImpl; import mage.cards.CardSetInfo; @@ -23,7 +22,7 @@ import java.util.UUID; */ public final class WildwoodTracker extends CardImpl { - private static final FilterPermanent filter = new FilterControlledCreaturePermanent(); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("you control another non-Human creature"); static { filter.add(AnotherPredicate.instance); @@ -41,12 +40,9 @@ public final class WildwoodTracker extends CardImpl { this.toughness = new MageInt(1); // Whenever Wildwood Tracker attacks or blocks, if you control another non-Human creature, Wildwood Tracker gets +1/+1 until end of turn. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksOrBlocksTriggeredAbility( - new BoostSourceEffect(1, 1, Duration.EndOfTurn), false - ), condition, "Whenever {this} attacks or blocks, if you control another non-Human creature, " + - "{this} gets +1/+1 until end of turn." - )); + this.addAbility(new AttacksOrBlocksTriggeredAbility( + new BoostSourceEffect(1, 1, Duration.EndOfTurn), false + ).withInterveningIf(condition)); } private WildwoodTracker(final WildwoodTracker card) { diff --git a/Mage.Sets/src/mage/cards/w/WillingTestSubject.java b/Mage.Sets/src/mage/cards/w/WillingTestSubject.java index 194197896d7..9a560536164 100644 --- a/Mage.Sets/src/mage/cards/w/WillingTestSubject.java +++ b/Mage.Sets/src/mage/cards/w/WillingTestSubject.java @@ -1,4 +1,3 @@ - package mage.cards.w; import mage.MageInt; @@ -58,8 +57,9 @@ public final class WillingTestSubject extends CardImpl { class WillingTestSubjectTriggeredAbility extends TriggeredAbilityImpl { - public WillingTestSubjectTriggeredAbility() { + WillingTestSubjectTriggeredAbility() { super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance())); + setTriggerPhrase("Whenever you roll a 4 or higher on a die, "); } private WillingTestSubjectTriggeredAbility(final WillingTestSubjectTriggeredAbility ability) { @@ -83,8 +83,4 @@ class WillingTestSubjectTriggeredAbility extends TriggeredAbilityImpl { return this.isControlledBy(event.getTargetId()) && drEvent.getResult() >= 4; } - @Override - public String getRule() { - return "Whenever you roll a 4 or higher on a die, put a +1/+1 counter on {this}"; - } } diff --git a/Mage.Sets/src/mage/cards/w/WillowSatyr.java b/Mage.Sets/src/mage/cards/w/WillowSatyr.java index 21cfb6aff04..f77829df12c 100644 --- a/Mage.Sets/src/mage/cards/w/WillowSatyr.java +++ b/Mage.Sets/src/mage/cards/w/WillowSatyr.java @@ -15,6 +15,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.SuperType; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -44,7 +45,7 @@ public final class WillowSatyr extends CardImpl { new GainControlTargetEffect(Duration.WhileControlled), SourceTappedCondition.TAPPED, "Gain control of target legendary creature for as long as you control {this} and {this} remains tapped" ), new TapSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/w/WindswiftSlice.java b/Mage.Sets/src/mage/cards/w/WindswiftSlice.java index bb74bc96156..0c9751e1c7a 100644 --- a/Mage.Sets/src/mage/cards/w/WindswiftSlice.java +++ b/Mage.Sets/src/mage/cards/w/WindswiftSlice.java @@ -12,9 +12,12 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.ElfWarriorToken; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * * @author bwsinger @@ -28,7 +31,7 @@ public final class WindswiftSlice extends CardImpl { // Target creature you control deals damage equal to its power to target creature you don't control. Create a number of 1/1 green Elf Warrior creature tokens equal to the amount of excess damage dealt this way. this.getSpellAbility().addEffect(new WindswiftSliceEffect()); this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); } private WindswiftSlice(final WindswiftSlice card) { diff --git a/Mage.Sets/src/mage/cards/w/WingPuncture.java b/Mage.Sets/src/mage/cards/w/WingPuncture.java index 8019f2b76ea..33c8f39bdcd 100644 --- a/Mage.Sets/src/mage/cards/w/WingPuncture.java +++ b/Mage.Sets/src/mage/cards/w/WingPuncture.java @@ -14,6 +14,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; @@ -34,7 +35,7 @@ public final class WingPuncture extends CardImpl { // Target creature you control deals damage equal to its power to target creature with flying. this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new WingPunctureEffect()); } diff --git a/Mage.Sets/src/mage/cards/w/WingSnare.java b/Mage.Sets/src/mage/cards/w/WingSnare.java index 2318052779d..f041ce1f5ea 100644 --- a/Mage.Sets/src/mage/cards/w/WingSnare.java +++ b/Mage.Sets/src/mage/cards/w/WingSnare.java @@ -9,6 +9,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -29,7 +30,7 @@ public final class WingSnare extends CardImpl { // Destroy target creature with flying. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); } private WingSnare(final WingSnare card) { diff --git a/Mage.Sets/src/mage/cards/w/WingmantleChaplain.java b/Mage.Sets/src/mage/cards/w/WingmantleChaplain.java index e12168835d7..d41032733df 100644 --- a/Mage.Sets/src/mage/cards/w/WingmantleChaplain.java +++ b/Mage.Sets/src/mage/cards/w/WingmantleChaplain.java @@ -2,7 +2,7 @@ package mage.cards.w; import mage.MageInt; import mage.MageObject; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; @@ -14,7 +14,6 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicate; import mage.filter.predicate.mageobject.AbilityPredicate; import mage.filter.predicate.mageobject.AnotherPredicate; @@ -30,7 +29,7 @@ public final class WingmantleChaplain extends CardImpl { private static final FilterPermanent filter = new FilterControlledCreaturePermanent("creature with defender you control"); private static final FilterPermanent filter2 - = new FilterCreaturePermanent("another creature with defender"); + = new FilterControlledCreaturePermanent("another creature you control with defender"); private static final Predicate predicate = new AbilityPredicate(DefenderAbility.class); @@ -57,7 +56,7 @@ public final class WingmantleChaplain extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new BirdToken(), xValue))); // Whenever another creature with defender you control enters, create a 1/1 white Bird creature token with flying. - this.addAbility(new EntersBattlefieldControlledTriggeredAbility(new CreateTokenEffect(new BirdToken()), filter2)); + this.addAbility(new EntersBattlefieldAllTriggeredAbility(new CreateTokenEffect(new BirdToken()), filter2)); } private WingmantleChaplain(final WingmantleChaplain card) { diff --git a/Mage.Sets/src/mage/cards/w/WingmateRoc.java b/Mage.Sets/src/mage/cards/w/WingmateRoc.java index c3ca3257cf9..5061a0f33e3 100644 --- a/Mage.Sets/src/mage/cards/w/WingmateRoc.java +++ b/Mage.Sets/src/mage/cards/w/WingmateRoc.java @@ -4,9 +4,8 @@ import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.RaidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.AttackingCreatureCount; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.hint.common.RaidHint; @@ -26,6 +25,8 @@ import java.util.UUID; */ public final class WingmateRoc extends CardImpl { + private static final DynamicValue xValue = new AttackingCreatureCount(); + public WingmateRoc(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); this.subtype.add(SubType.BIRD); @@ -37,16 +38,11 @@ public final class WingmateRoc extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Raid — When Wingmate Roc enters the battlefield, if you attacked this turn, create a 3/4 white Bird creature token with flying. - this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new WingmateRocToken())), RaidCondition.instance, - "When {this} enters, if you attacked this turn, create a 3/4 white Bird creature token with flying.") - .setAbilityWord(AbilityWord.RAID) - .addHint(RaidHint.instance), - new PlayerAttackedWatcher()); + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new WingmateRocToken())) + .withInterveningIf(RaidCondition.instance).setAbilityWord(AbilityWord.RAID).addHint(RaidHint.instance), new PlayerAttackedWatcher()); // Whenever Wingmate Roc attacks, you gain 1 life for each attacking creature. - Effect effect = new GainLifeEffect(new AttackingCreatureCount()); - effect.setText("you gain 1 life for each attacking creature"); - this.addAbility(new AttacksTriggeredAbility(effect, false)); + this.addAbility(new AttacksTriggeredAbility(new GainLifeEffect(xValue).setText("you gain 1 life for each attacking creature"))); } private WingmateRoc(final WingmateRoc card) { diff --git a/Mage.Sets/src/mage/cards/w/WishclawTalisman.java b/Mage.Sets/src/mage/cards/w/WishclawTalisman.java index 9b714024a9e..67496fc1887 100644 --- a/Mage.Sets/src/mage/cards/w/WishclawTalisman.java +++ b/Mage.Sets/src/mage/cards/w/WishclawTalisman.java @@ -8,18 +8,15 @@ import mage.abilities.costs.common.RemoveCountersSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.ContinuousEffect; -import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; -import mage.abilities.hint.common.MyTurnHint; 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.counters.CounterType; import mage.game.Game; import mage.players.Player; @@ -46,11 +43,12 @@ public final class WishclawTalisman extends CardImpl { // {1}, {T}, Remove a wish counter from Wishclaw Talisman: Search your library for a card, put it into your hand, then shuffle your library. An opponent gains control of Wishclaw Talisman. Activate this ability only during your turn. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new WishclawTalismanEffect(), new GenericManaCost(1), MyTurnCondition.instance + new SearchLibraryPutInHandEffect(new TargetCardInLibrary(), false), + new GenericManaCost(1), MyTurnCondition.instance ); + ability.addEffect(new WishclawTalismanEffect()); ability.addCost(new TapSourceCost()); ability.addCost(new RemoveCountersSourceCost(CounterType.WISH.createInstance())); - ability.addHint(MyTurnHint.instance); this.addAbility(ability); } @@ -66,12 +64,9 @@ public final class WishclawTalisman extends CardImpl { class WishclawTalismanEffect extends OneShotEffect { - private static final Effect effect = new SearchLibraryPutInHandEffect(new TargetCardInLibrary(), false); - WishclawTalismanEffect() { super(Outcome.Benefit); - staticText = "Search your library for a card, put it into your hand, then shuffle. " + - "An opponent gains control of {this}"; + staticText = "An opponent gains control of {this}"; } private WishclawTalismanEffect(final WishclawTalismanEffect effect) { @@ -85,7 +80,6 @@ class WishclawTalismanEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - effect.apply(game, source); Player player = game.getPlayer(source.getControllerId()); if (player == null) { return false; diff --git a/Mage.Sets/src/mage/cards/w/WispdrinkerVampire.java b/Mage.Sets/src/mage/cards/w/WispdrinkerVampire.java index 9194e34f0d9..4db6f2a0248 100644 --- a/Mage.Sets/src/mage/cards/w/WispdrinkerVampire.java +++ b/Mage.Sets/src/mage/cards/w/WispdrinkerVampire.java @@ -2,7 +2,7 @@ package mage.cards.w; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.GainLifeEffect; @@ -19,7 +19,6 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.mageobject.PowerPredicate; @@ -31,7 +30,7 @@ import java.util.UUID; public final class WispdrinkerVampire extends CardImpl { private static final FilterPermanent filter - = new FilterCreaturePermanent("another creature with power 2 or less"); + = new FilterControlledCreaturePermanent("another creature you control with power 2 or less"); private static final FilterPermanent filter2 = new FilterControlledCreaturePermanent(); static { @@ -52,7 +51,7 @@ public final class WispdrinkerVampire extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Whenever another creature with power 2 or less you control enters, each opponent loses 1 life and you gain 1 life. - Ability ability = new EntersBattlefieldControlledTriggeredAbility(new LoseLifeOpponentsEffect(1), filter); + Ability ability = new EntersBattlefieldAllTriggeredAbility(new LoseLifeOpponentsEffect(1), filter); ability.addEffect(new GainLifeEffect(1).concatBy("and")); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/w/WispweaverAngel.java b/Mage.Sets/src/mage/cards/w/WispweaverAngel.java index 5a6cb31661f..02a0c380183 100644 --- a/Mage.Sets/src/mage/cards/w/WispweaverAngel.java +++ b/Mage.Sets/src/mage/cards/w/WispweaverAngel.java @@ -10,7 +10,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import java.util.UUID; @@ -30,7 +30,7 @@ public final class WispweaverAngel extends CardImpl { // When Wispweaver Angel enters the battlefield, you may exile another target creature you control, then return that card to the battlefield under its owner's control. Ability ability = new EntersBattlefieldTriggeredAbility(new ExileThenReturnTargetEffect(false, true), true); - ability.addTarget(new TargetControlledCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE_YOU_CONTROL)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/w/WitchHunter.java b/Mage.Sets/src/mage/cards/w/WitchHunter.java index 6bf1516ecf8..c8b97743108 100644 --- a/Mage.Sets/src/mage/cards/w/WitchHunter.java +++ b/Mage.Sets/src/mage/cards/w/WitchHunter.java @@ -1,7 +1,5 @@ - package mage.cards.w; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -13,13 +11,12 @@ 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.TargetCreaturePermanent; +import mage.target.common.TargetOpponentsCreaturePermanent; import mage.target.common.TargetPlayerOrPlaneswalker; +import java.util.UUID; + /** - * * @author fireshoes */ public final class WitchHunter extends CardImpl { @@ -39,8 +36,7 @@ public final class WitchHunter extends CardImpl { // {1}{W}{W}, {tap}: Return target creature an opponent controls to its owner's hand. Ability returnAbility = new SimpleActivatedAbility(new ReturnToHandTargetEffect(), new ManaCostsImpl<>("{1}{W}{W}")); returnAbility.addCost(new TapSourceCost()); - TargetCreaturePermanent target = new TargetCreaturePermanent(StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE); - returnAbility.addTarget(target); + returnAbility.addTarget(new TargetOpponentsCreaturePermanent()); this.addAbility(returnAbility); } diff --git a/Mage.Sets/src/mage/cards/w/WitchOfTheMoors.java b/Mage.Sets/src/mage/cards/w/WitchOfTheMoors.java index 60bac2d662e..12aabc07124 100644 --- a/Mage.Sets/src/mage/cards/w/WitchOfTheMoors.java +++ b/Mage.Sets/src/mage/cards/w/WitchOfTheMoors.java @@ -2,14 +2,13 @@ package mage.cards.w; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.YouGainedLifeCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.ControllerGainedLifeCount; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; import mage.abilities.effects.common.SacrificeOpponentsEffect; import mage.abilities.keyword.DeathtouchAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -40,15 +39,10 @@ public final class WitchOfTheMoors extends CardImpl { // At the beginning of your end step, if you gained life this turn, each opponent sacrifices a // creature and you return up to one target creature card from your graveyard to your hand. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility(new SacrificeOpponentsEffect( - StaticFilters.FILTER_PERMANENT_A_CREATURE - )), - condition, "At the beginning of your end step, if you gained life this turn, " - + "each opponent sacrifices a creature and you return up to one target creature card " - + "from your graveyard to your hand." - ); - ability.addEffect(new ReturnFromGraveyardToHandTargetEffect()); + Ability ability = new BeginningOfEndStepTriggeredAbility( + new SacrificeOpponentsEffect(StaticFilters.FILTER_PERMANENT_A_CREATURE) + ).withInterveningIf(condition); + ability.addEffect(new ReturnFromGraveyardToHandTargetEffect().concatBy("and you")); ability.addTarget(new TargetCardInYourGraveyard( 0, 1, StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD )); diff --git a/Mage.Sets/src/mage/cards/w/Withdraw.java b/Mage.Sets/src/mage/cards/w/Withdraw.java index ca0d10c4a53..01666de77d1 100644 --- a/Mage.Sets/src/mage/cards/w/Withdraw.java +++ b/Mage.Sets/src/mage/cards/w/Withdraw.java @@ -16,6 +16,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; import mage.util.ManaUtil; @@ -32,13 +33,13 @@ public final class Withdraw extends CardImpl { // Return target creature to its owner's hand. Then return another target creature to its owner's hand unless its controller pays {1}. this.getSpellAbility().addEffect(new WithdrawEffect()); - Target target = new TargetCreaturePermanent(new FilterCreaturePermanent("creature to return unconditionally")); + Target target = new TargetPermanent(new FilterCreaturePermanent("creature to return unconditionally")); target.setTargetTag(1); this.getSpellAbility().addTarget(target); FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature to return unless {1} is paid"); filter.add(new AnotherTargetPredicate(2)); - target = new TargetCreaturePermanent(filter); + target = new TargetPermanent(filter); target.setTargetTag(2); this.getSpellAbility().addTarget(target); } diff --git a/Mage.Sets/src/mage/cards/w/WitheringWisps.java b/Mage.Sets/src/mage/cards/w/WitheringWisps.java index ec0ef84406a..9373b77c089 100644 --- a/Mage.Sets/src/mage/cards/w/WitheringWisps.java +++ b/Mage.Sets/src/mage/cards/w/WitheringWisps.java @@ -1,40 +1,37 @@ - package mage.cards.w; -import java.util.UUID; import mage.abilities.ActivatedAbilityImpl; -import mage.abilities.TriggeredAbility; -import mage.abilities.common.OnEventTriggeredAbility; -import mage.abilities.condition.common.CreatureCountCondition; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageEverythingEffect; import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.SubType; -import mage.constants.TargetController; -import mage.constants.SuperType; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; +import mage.constants.*; import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; + +import java.util.UUID; /** - * * @author L_J */ public final class WitheringWisps extends CardImpl { - private static final String ruleText = "At the beginning of the end step, if no creatures are on the battlefield, sacrifice {this}."; + private static final Condition condition = new PermanentsOnTheBattlefieldCondition( + new FilterCreaturePermanent("no creatures are on the battlefield"), + ComparisonType.EQUAL_TO, 0, false + ); public WitheringWisps(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}{B}"); // At the beginning of the end step, if no creatures are on the battlefield, sacrifice Withering Wisps. - TriggeredAbility triggered = new OnEventTriggeredAbility(GameEvent.EventType.END_TURN_STEP_PRE, "beginning of the end step", true, new SacrificeSourceEffect()); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(triggered, new CreatureCountCondition(0, TargetController.ANY), ruleText)); + this.addAbility(new BeginningOfEndStepTriggeredAbility(TargetController.NEXT, new SacrificeSourceEffect(), false, condition)); // {B}: Withering Wisps deals 1 damage to each creature and each player. Activate this ability no more times each turn than the number of snow Swamps you control. this.addAbility(new WitheringWispsActivatedAbility()); @@ -52,17 +49,15 @@ public final class WitheringWisps extends CardImpl { class WitheringWispsActivatedAbility extends ActivatedAbilityImpl { - private static final FilterPermanent filter = new FilterPermanent("snow Swamps you control"); + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.SWAMP, "snow Swamps you control"); static { filter.add(SuperType.SNOW.getPredicate()); - filter.add(SubType.SWAMP.getPredicate()); - filter.add(TargetController.YOU.getControllerPredicate()); } @Override public int getMaxActivationsPerTurn(Game game) { - return game.getBattlefield().getAllActivePermanents(filter, game).size(); + return game.getBattlefield().getActivePermanents(filter, getControllerId(), this, game).size(); } public WitheringWispsActivatedAbility() { @@ -76,7 +71,7 @@ class WitheringWispsActivatedAbility extends ActivatedAbilityImpl { @Override public String getRule() { - return super.getRule() + " Activate this ability no more times each turn than the number of snow Swamps you control."; + return super.getRule() + " Activate no more times each turn than the number of snow Swamps you control."; } @Override diff --git a/Mage.Sets/src/mage/cards/w/WolfStrike.java b/Mage.Sets/src/mage/cards/w/WolfStrike.java index 6a7e7288350..552c59514e2 100644 --- a/Mage.Sets/src/mage/cards/w/WolfStrike.java +++ b/Mage.Sets/src/mage/cards/w/WolfStrike.java @@ -13,9 +13,12 @@ import mage.constants.Duration; import mage.constants.Outcome; import mage.filter.StaticFilters; import mage.game.Game; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL; + /** * * @author weirddan455 @@ -28,7 +31,7 @@ public final class WolfStrike extends CardImpl { // Target creature you control gets +2/+0 until end of turn if it's night. // Then it deals damage equal to its power to target creature you don't control. this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL)); + this.getSpellAbility().addTarget(new TargetPermanent(FILTER_CREATURE_YOU_DONT_CONTROL)); this.getSpellAbility().addEffect(new WolfStikeEffect()); this.getSpellAbility().addEffect(new DamageWithPowerFromOneToAnotherTargetEffect("it").concatBy("Then")); } diff --git a/Mage.Sets/src/mage/cards/w/WolfhuntersQuiver.java b/Mage.Sets/src/mage/cards/w/WolfhuntersQuiver.java index 192954a6937..aa094c3e46a 100644 --- a/Mage.Sets/src/mage/cards/w/WolfhuntersQuiver.java +++ b/Mage.Sets/src/mage/cards/w/WolfhuntersQuiver.java @@ -14,6 +14,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetAnyTarget; import mage.target.common.TargetCreaturePermanent; @@ -42,7 +43,7 @@ public final class WolfhuntersQuiver extends CardImpl { // and "{T}: This creature deals 3 damage to target Werewolf creature." abilityToGain = new SimpleActivatedAbility(new DamageTargetEffect(3), new TapSourceCost()); - abilityToGain.addTarget(new TargetCreaturePermanent(filter)); + abilityToGain.addTarget(new TargetPermanent(filter)); effect = new GainAbilityAttachedEffect(abilityToGain, AttachmentType.EQUIPMENT); effect.setText("and \"{T}: This creature deals 3 damage to target Werewolf creature.\""); ability.addEffect(effect); diff --git a/Mage.Sets/src/mage/cards/w/WolfwillowHaven.java b/Mage.Sets/src/mage/cards/w/WolfwillowHaven.java index 532db353ad8..b36ba498e75 100644 --- a/Mage.Sets/src/mage/cards/w/WolfwillowHaven.java +++ b/Mage.Sets/src/mage/cards/w/WolfwillowHaven.java @@ -9,12 +9,14 @@ import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.mana.AddManaToManaPoolTargetControllerEffect; -import mage.abilities.hint.common.MyTurnHint; import mage.abilities.keyword.EnchantAbility; import mage.abilities.mana.EnchantedTappedTriggeredManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.ColoredManaSymbol; +import mage.constants.Outcome; +import mage.constants.SubType; import mage.game.permanent.token.WolfToken; import mage.target.TargetPermanent; import mage.target.common.TargetLandPermanent; @@ -45,11 +47,9 @@ public final class WolfwillowHaven extends CardImpl { // {4}{G}, Sacrifice Wolfwillow Haven: Create a 2/2 green Wolf creature token. Activate this ability only during your turn. ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new CreateTokenEffect(new WolfToken()), - new ManaCostsImpl<>("{4}{G}"), MyTurnCondition.instance + new CreateTokenEffect(new WolfToken()), new ManaCostsImpl<>("{4}{G}"), MyTurnCondition.instance ); ability.addCost(new SacrificeSourceCost()); - ability.addHint(MyTurnHint.instance); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/w/WoodcallerAutomaton.java b/Mage.Sets/src/mage/cards/w/WoodcallerAutomaton.java index c8ab4ac80ad..300c6a2c8d8 100644 --- a/Mage.Sets/src/mage/cards/w/WoodcallerAutomaton.java +++ b/Mage.Sets/src/mage/cards/w/WoodcallerAutomaton.java @@ -1,14 +1,15 @@ package mage.cards.w; import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.CastFromEverywhereSourceCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.dynamicvalue.common.SourcePermanentPowerValue; +import mage.abilities.dynamicvalue.common.SourcePermanentToughnessValue; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.effects.common.continuous.BecomesCreatureTargetEffect; +import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.PrototypeAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -18,12 +19,9 @@ import mage.constants.Outcome; import mage.constants.SubType; import mage.filter.StaticFilters; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.game.permanent.token.custom.CreatureToken; import mage.target.TargetPermanent; -import java.util.Objects; -import java.util.Optional; import java.util.UUID; /** @@ -42,12 +40,8 @@ public final class WoodcallerAutomaton extends CardImpl { this.addAbility(new PrototypeAbility(this, "{2}{G}{G}", 3, 3)); // When Woodcaller Automaton enters the battlefield, if you cast it, untap target land you control. It becomes a Treefolk creature with haste and base power and toughness equal to Woodcaller Automaton's power and toughness. It's still a land. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new UntapTargetEffect()), - CastFromEverywhereSourceCondition.instance, "When {this} enters, " + - "if you cast it, untap target land you control. It becomes a Treefolk creature with haste " + - "and base power and toughness equal to {this}'s power and toughness. It's still a land." - ); + Ability ability = new EntersBattlefieldTriggeredAbility(new UntapTargetEffect()) + .withInterveningIf(CastFromEverywhereSourceCondition.instance); ability.addEffect(new WoodcallerAutomatonEffect()); ability.addTarget(new TargetPermanent(StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND)); this.addAbility(ability); @@ -67,6 +61,7 @@ class WoodcallerAutomatonEffect extends OneShotEffect { WoodcallerAutomatonEffect() { super(Outcome.Benefit); + staticText = "It becomes a Treefolk creature with haste and base power and toughness equal to {this}'s power and toughness. It's still a land"; } private WoodcallerAutomatonEffect(final WoodcallerAutomatonEffect effect) { @@ -80,19 +75,10 @@ class WoodcallerAutomatonEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Optional optionalPermanent = Optional - .ofNullable(source.getSourcePermanentOrLKI(game)) - .filter(Objects::nonNull); - int power = optionalPermanent - .map(MageObject::getPower) - .map(MageInt::getValue) - .orElse(0); - int toughness = optionalPermanent - .map(MageObject::getToughness) - .map(MageInt::getValue) - .orElse(0); + int power = SourcePermanentPowerValue.ALLOW_NEGATIVE.calculate(game, source, this); + int toughness = SourcePermanentToughnessValue.instance.calculate(game, source, this); game.addEffect(new BecomesCreatureTargetEffect( - new CreatureToken(power, toughness, "", SubType.TREEFOLK), + new CreatureToken(power, toughness, "", SubType.TREEFOLK).withAbility(HasteAbility.getInstance()), false, true, Duration.Custom ), source); return true; diff --git a/Mage.Sets/src/mage/cards/w/WoodlandSleuth.java b/Mage.Sets/src/mage/cards/w/WoodlandSleuth.java index abc9d5e1e6f..e181039a0b8 100644 --- a/Mage.Sets/src/mage/cards/w/WoodlandSleuth.java +++ b/Mage.Sets/src/mage/cards/w/WoodlandSleuth.java @@ -1,14 +1,13 @@ package mage.cards.w; import mage.MageInt; -import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.MorbidCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.ReturnFromGraveyardAtRandomEffect; import mage.abilities.hint.common.MorbidHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; @@ -17,13 +16,10 @@ import mage.filter.StaticFilters; import java.util.UUID; /** - * * @author North */ public final class WoodlandSleuth extends CardImpl { - private static final String staticText = "Morbid — When {this} enters, if a creature died this turn, return a creature card at random from your graveyard to your hand."; - public WoodlandSleuth(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); this.subtype.add(SubType.HUMAN); @@ -34,9 +30,9 @@ public final class WoodlandSleuth extends CardImpl { this.toughness = new MageInt(3); // Morbid — When Woodland Sleuth enters the battlefield, if a creature died this turn, return a creature card at random from your graveyard to your hand. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility( - new ReturnFromGraveyardAtRandomEffect(StaticFilters.FILTER_CARD_CREATURE, Zone.HAND)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, MorbidCondition.instance, staticText).addHint(MorbidHint.instance)); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new ReturnFromGraveyardAtRandomEffect(StaticFilters.FILTER_CARD_CREATURE, Zone.HAND) + ).withInterveningIf(MorbidCondition.instance).setAbilityWord(AbilityWord.MORBID).addHint(MorbidHint.instance)); } private WoodlandSleuth(final WoodlandSleuth card) { diff --git a/Mage.Sets/src/mage/cards/w/WookieeRaidleader.java b/Mage.Sets/src/mage/cards/w/WookieeRaidleader.java index 55e00ec7391..d783d02f98b 100644 --- a/Mage.Sets/src/mage/cards/w/WookieeRaidleader.java +++ b/Mage.Sets/src/mage/cards/w/WookieeRaidleader.java @@ -13,8 +13,11 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Duration; import mage.filter.StaticFilters; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_ANOTHER_TARGET_CREATURE; + /** * * @author Styxo @@ -30,7 +33,7 @@ public final class WookieeRaidleader extends CardImpl { // Whenever Wookiee Raidleader attacks, antoher target creature gains trample until end of turn Ability ability = new AttacksTriggeredAbility(new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn), false); - ability.addTarget(new TargetCreaturePermanent(StaticFilters.FILTER_ANOTHER_TARGET_CREATURE)); + ability.addTarget(new TargetPermanent(FILTER_ANOTHER_TARGET_CREATURE)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/w/WowzerTheAspirational.java b/Mage.Sets/src/mage/cards/w/WowzerTheAspirational.java index 55cfdf03022..59d23c16e76 100644 --- a/Mage.Sets/src/mage/cards/w/WowzerTheAspirational.java +++ b/Mage.Sets/src/mage/cards/w/WowzerTheAspirational.java @@ -5,13 +5,10 @@ import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.CompoundCondition; import mage.abilities.condition.Condition; -import mage.abilities.condition.IntCompareCondition; import mage.abilities.condition.common.CitysBlessingCondition; import mage.abilities.condition.common.HaveInitiativeCondition; import mage.abilities.condition.common.MonarchIsSourceControllerCondition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.dynamicvalue.common.CountersControllerCount; import mage.abilities.effects.common.WinGameSourceControllerEffect; import mage.abilities.hint.ConditionHint; import mage.abilities.hint.Hint; @@ -21,13 +18,14 @@ import mage.abilities.hint.common.MonarchHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.ComparisonType; import mage.constants.SubType; import mage.constants.SuperType; import mage.counters.CounterType; import mage.filter.common.FilterControlledPermanent; +import mage.game.Controllable; import mage.game.Game; +import java.util.Optional; import java.util.UUID; /** @@ -35,7 +33,7 @@ import java.util.UUID; */ public class WowzerTheAspirational extends CardImpl { - private static final Condition energyCondition = new WowzerTheAspirationalCondition(); + private static final Condition energyCondition = WowzerTheAspirationalCondition.instance; private static final Condition bloodCondition = new PermanentsOnTheBattlefieldCondition(new FilterControlledPermanent(SubType.BLOOD)); private static final Condition clueCondition @@ -50,6 +48,8 @@ public class WowzerTheAspirational extends CardImpl { = new PermanentsOnTheBattlefieldCondition(new FilterControlledPermanent(SubType.TREASURE)); private static final Condition winCondition = new CompoundCondition( + "you have an {E}, control a Blood, a Clue, a Food, a Map, a Powerstone, and a Treasure, " + + "are the monarch, and have the city's blessing and the initiative", energyCondition, bloodCondition, clueCondition, @@ -59,7 +59,8 @@ public class WowzerTheAspirational extends CardImpl { treasureCondition, MonarchIsSourceControllerCondition.instance, CitysBlessingCondition.instance, - HaveInitiativeCondition.instance); + HaveInitiativeCondition.instance + ); private static final Hint energyHint = new ConditionHint(energyCondition, "You have an {E}"); private static final Hint bloodHint = new ConditionHint(bloodCondition, "You control a Blood"); @@ -83,13 +84,9 @@ public class WowzerTheAspirational extends CardImpl { // Whenever Wowzer, the Aspirational attacks, // if you have an {E}, control a Blood, a Clue, a Food, a Map, a Powerstone, and a Treasure, // are the monarch, and have the city's blessing and the initiative, you win the game. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new AttacksTriggeredAbility(new WinGameSourceControllerEffect()), - winCondition, - "Whenever {this} attacks, " + - "if you have an {E}, control a Blood, a Clue, a Food, a Map, a Powerstone, and a Treasure, " + - "are the monarch, and have the city's blessing and the initiative, you win the game." - ).addHint(energyHint) + this.addAbility(new AttacksTriggeredAbility(new WinGameSourceControllerEffect()) + .withInterveningIf(winCondition) + .addHint(energyHint) .addHint(bloodHint) .addHint(clueHint) .addHint(foodHint) @@ -111,14 +108,16 @@ public class WowzerTheAspirational extends CardImpl { } } -class WowzerTheAspirationalCondition extends IntCompareCondition { - - WowzerTheAspirationalCondition() { - super(ComparisonType.MORE_THAN, 0); - } +enum WowzerTheAspirationalCondition implements Condition { + instance; @Override - protected int getInputValue(Game game, Ability source) { - return new CountersControllerCount(CounterType.ENERGY).calculate(game, source, null); + public boolean apply(Game game, Ability source) { + return Optional + .of(source) + .map(Controllable::getControllerId) + .map(game::getPlayer) + .filter(player -> player.getCountersCount(CounterType.ENERGY) > 0) + .isPresent(); } } diff --git a/Mage.Sets/src/mage/cards/w/Wrangle.java b/Mage.Sets/src/mage/cards/w/Wrangle.java index ec9db18fbfa..e3503135c8c 100644 --- a/Mage.Sets/src/mage/cards/w/Wrangle.java +++ b/Mage.Sets/src/mage/cards/w/Wrangle.java @@ -14,6 +14,7 @@ import mage.constants.ComparisonType; import mage.constants.Duration; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -32,7 +33,7 @@ public final class Wrangle extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{R}"); // Gain control of target creature with power 4 or less until end of turn. Untap that creature. It gains haste until end of turn. - this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.EndOfTurn)); Effect effect = new UntapTargetEffect(); effect.setText("Untap that creature"); diff --git a/Mage.Sets/src/mage/cards/w/WretchedCamel.java b/Mage.Sets/src/mage/cards/w/WretchedCamel.java index 1a865b57a42..d7e59681720 100644 --- a/Mage.Sets/src/mage/cards/w/WretchedCamel.java +++ b/Mage.Sets/src/mage/cards/w/WretchedCamel.java @@ -4,7 +4,6 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.condition.common.DesertControlledOrGraveyardCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -28,11 +27,7 @@ public final class WretchedCamel extends CardImpl { this.toughness = new MageInt(1); // When Wretched Camel dies, if you control a Desert or there is a Desert card in your graveyard, target player discards a card. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new DiesSourceTriggeredAbility(new DiscardTargetEffect(1)), - DesertControlledOrGraveyardCondition.instance, "When {this} dies, " + - "if you control a Desert or there is a Desert card in your graveyard, target player discards a card." - ); + Ability ability = new DiesSourceTriggeredAbility(new DiscardTargetEffect(1)).withInterveningIf(DesertControlledOrGraveyardCondition.instance); ability.addTarget(new TargetPlayer()); this.addAbility(ability.addHint(DesertControlledOrGraveyardCondition.getHint())); } diff --git a/Mage.Sets/src/mage/cards/w/WritOfPassage.java b/Mage.Sets/src/mage/cards/w/WritOfPassage.java index 7787b1c3bc0..c2053b11018 100644 --- a/Mage.Sets/src/mage/cards/w/WritOfPassage.java +++ b/Mage.Sets/src/mage/cards/w/WritOfPassage.java @@ -2,10 +2,9 @@ package mage.cards.w; import mage.abilities.Ability; import mage.abilities.common.AttacksAttachedTriggeredAbility; -import mage.abilities.condition.common.AttachedToMatchesFilterCondition; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.SourceMatchesFilterCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.RestrictionEffect; import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.combat.CantBeBlockedTargetEffect; import mage.abilities.keyword.EnchantAbility; @@ -16,8 +15,6 @@ import mage.constants.*; import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; @@ -28,6 +25,16 @@ import java.util.UUID; */ public final class WritOfPassage extends CardImpl { + private static final FilterPermanent filter = new FilterPermanent("its power is 2 or less"); + private static final FilterPermanent filter2 = new FilterCreaturePermanent("creature with power 2 or less"); + + static { + filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 3)); + filter2.add(new PowerPredicate(ComparisonType.FEWER_THAN, 3)); + } + + private static final Condition condition = new SourceMatchesFilterCondition(filter); + public WritOfPassage(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}"); @@ -37,22 +44,18 @@ public final class WritOfPassage extends CardImpl { TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); - Ability ability = new EnchantAbility(auraTarget); - this.addAbility(ability); + this.addAbility(new EnchantAbility(auraTarget)); // Whenever enchanted creature attacks, if its power is 2 or less, it's unblockable this turn. - FilterPermanent filter = new FilterPermanent("if enchanted creature's power is 2 or less"); - filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 3)); - ability = new ConditionalInterveningIfTriggeredAbility(new AttacksAttachedTriggeredAbility( - new WritOfPassageAttachedEffect(AttachmentType.AURA), AttachmentType.AURA, false), - new AttachedToMatchesFilterCondition(filter), "Whenever enchanted creature attacks, if its power is 2 or less, it can't be blocked this turn."); - this.addAbility(ability); + this.addAbility(new AttacksAttachedTriggeredAbility( + new CantBeBlockedTargetEffect().setText("it can't be blocked this turn"), + AttachmentType.AURA, false, SetTargetPointer.PERMANENT + ).withInterveningIf(condition)); + // Forecast - {1}{U}, Reveal Writ of Passage from your hand: Target creature with power 2 or less is unblockable this turn. - ForecastAbility ability2 = new ForecastAbility(new CantBeBlockedTargetEffect(), new ManaCostsImpl<>("{1}{U}")); - FilterCreaturePermanent filter2 = new FilterCreaturePermanent("creature with power 2 or less"); - filter2.add(new PowerPredicate(ComparisonType.FEWER_THAN, 3)); - ability2.addTarget(new TargetCreaturePermanent(filter2)); - this.addAbility(ability2); + Ability ability = new ForecastAbility(new CantBeBlockedTargetEffect(), new ManaCostsImpl<>("{1}{U}")); + ability.addTarget(new TargetPermanent(filter2)); + this.addAbility(ability); } private WritOfPassage(final WritOfPassage card) { @@ -64,31 +67,3 @@ public final class WritOfPassage extends CardImpl { return new WritOfPassage(this); } } - -class WritOfPassageAttachedEffect extends RestrictionEffect { - - WritOfPassageAttachedEffect(AttachmentType attachmentType) { - super(Duration.EndOfTurn); - this.staticText = attachmentType.verb() + " creature can't be blocked"; - } - - private WritOfPassageAttachedEffect(final WritOfPassageAttachedEffect effect) { - super(effect); - } - - @Override - public WritOfPassageAttachedEffect copy() { - return new WritOfPassageAttachedEffect(this); - } - - @Override - public boolean canBeBlocked(Permanent attacker, Permanent blocker, Ability source, Game game, boolean canUseChooseDialogs) { - return false; - } - - @Override - public boolean applies(Permanent permanent, Ability source, Game game) { - Permanent attachment = game.getPermanent(source.getSourceId()); - return attachment != null && attachment.isAttachedTo(permanent.getId()); - } -} diff --git a/Mage.Sets/src/mage/cards/w/WuLongbowman.java b/Mage.Sets/src/mage/cards/w/WuLongbowman.java index 1f808131064..45addd2fd47 100644 --- a/Mage.Sets/src/mage/cards/w/WuLongbowman.java +++ b/Mage.Sets/src/mage/cards/w/WuLongbowman.java @@ -1,7 +1,5 @@ - package mage.cards.w; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; @@ -12,17 +10,17 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** - * * @author fireshoes */ public final class WuLongbowman extends CardImpl { public WuLongbowman(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.subtype.add(SubType.SOLDIER); this.subtype.add(SubType.ARCHER); @@ -30,8 +28,9 @@ public final class WuLongbowman extends CardImpl { this.toughness = new MageInt(1); // {tap}: Wu Longbowman deals 1 damage to any target. Activate this ability only during your turn, before attackers are declared. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new DamageTargetEffect(1), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new DamageTargetEffect(1), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance + ); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/w/WumpusAberration.java b/Mage.Sets/src/mage/cards/w/WumpusAberration.java index 43cd3f14568..342c1580104 100644 --- a/Mage.Sets/src/mage/cards/w/WumpusAberration.java +++ b/Mage.Sets/src/mage/cards/w/WumpusAberration.java @@ -1,28 +1,30 @@ package mage.cards.w; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; +import mage.abilities.condition.Condition; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.ManaWasSpentCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.CastSourceTriggeredAbility; import mage.abilities.effects.common.PutCardFromHandOntoBattlefieldEffect; -import mage.constants.SubType; import mage.abilities.keyword.DevoidAbility; 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.TargetOpponent; +import java.util.UUID; + /** - * * @author DominionSpy */ public final class WumpusAberration extends CardImpl { + private static final Condition condition = new InvertCondition(ManaWasSpentCondition.COLORLESS, "{C} wasn't spent to cast it"); + public WumpusAberration(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); @@ -35,13 +37,9 @@ public final class WumpusAberration extends CardImpl { this.addAbility(new DevoidAbility(this.color)); // When you cast this spell, if {C} wasn't spent to cast it, target opponent may put a creature card from their hand onto the battlefield. - Ability ability = new ConditionalInterveningIfTriggeredAbility( - new CastSourceTriggeredAbility( - new PutCardFromHandOntoBattlefieldEffect(StaticFilters.FILTER_CARD_CREATURE, true)), - new InvertCondition(ManaWasSpentCondition.COLORLESS), - "When you cast this spell, if {C} wasn't spent to cast it, " + - "target opponent may put a creature card from their hand onto the battlefield." - ); + Ability ability = new CastSourceTriggeredAbility(new PutCardFromHandOntoBattlefieldEffect( + StaticFilters.FILTER_CARD_CREATURE, true + ).setText("target opponent may put a creature card from their hand onto the battlefield")).withInterveningIf(condition); ability.addTarget(new TargetOpponent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/w/WurmweaverCoil.java b/Mage.Sets/src/mage/cards/w/WurmweaverCoil.java index 0b005173f1c..9fdb0c32ae8 100644 --- a/Mage.Sets/src/mage/cards/w/WurmweaverCoil.java +++ b/Mage.Sets/src/mage/cards/w/WurmweaverCoil.java @@ -41,7 +41,7 @@ public final class WurmweaverCoil extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{4}{G}{G}"); this.subtype.add(SubType.AURA); - TargetPermanent auraTarget = new TargetCreaturePermanent(filter); + TargetPermanent auraTarget = new TargetPermanent(filter); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.Benefit)); Ability ability = new EnchantAbility(auraTarget); diff --git a/Mage.Sets/src/mage/cards/x/XerexStrobeKnight.java b/Mage.Sets/src/mage/cards/x/XerexStrobeKnight.java index c97b78a4f0b..1139273654d 100644 --- a/Mage.Sets/src/mage/cards/x/XerexStrobeKnight.java +++ b/Mage.Sets/src/mage/cards/x/XerexStrobeKnight.java @@ -12,7 +12,6 @@ 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.KnightWhiteBlueToken; import mage.watchers.common.CastSpellLastTurnWatcher; @@ -40,7 +39,7 @@ public final class XerexStrobeKnight extends CardImpl { // {T}: Create a 2/2 white and blue Knight creature token with vigilance. Activate only if you've cast two or more spells this turn. this.addAbility(new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new CreateTokenEffect(new KnightWhiteBlueToken()), + new CreateTokenEffect(new KnightWhiteBlueToken()), new TapSourceCost(), XerexStrobeKnightCondition.instance )); } @@ -70,4 +69,4 @@ enum XerexStrobeKnightCondition implements Condition { public String toString() { return "you've cast two or more spells this turn"; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/x/XiahouDunTheOneEyed.java b/Mage.Sets/src/mage/cards/x/XiahouDunTheOneEyed.java index 960f837c52b..2d2c89ba9cb 100644 --- a/Mage.Sets/src/mage/cards/x/XiahouDunTheOneEyed.java +++ b/Mage.Sets/src/mage/cards/x/XiahouDunTheOneEyed.java @@ -44,7 +44,7 @@ public final class XiahouDunTheOneEyed extends CardImpl { this.addAbility(HorsemanshipAbility.getInstance()); // Sacrifice Xiahou Dun, the One-Eyed: Return target black card from your graveyard to your hand. Activate this ability only during your turn, before attackers are declared. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, + Ability ability = new ActivateIfConditionActivatedAbility( new ReturnFromGraveyardToHandTargetEffect(), new SacrificeSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); ability.addTarget(new TargetCardInYourGraveyard(filter)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/x/XunYuWeiAdvisor.java b/Mage.Sets/src/mage/cards/x/XunYuWeiAdvisor.java index 62ac471e703..6f705ae3957 100644 --- a/Mage.Sets/src/mage/cards/x/XunYuWeiAdvisor.java +++ b/Mage.Sets/src/mage/cards/x/XunYuWeiAdvisor.java @@ -1,7 +1,5 @@ - package mage.cards.x; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; @@ -12,19 +10,18 @@ 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.target.common.TargetControlledCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class XunYuWeiAdvisor extends CardImpl { public XunYuWeiAdvisor(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.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.ADVISOR); @@ -32,8 +29,10 @@ public final class XunYuWeiAdvisor extends CardImpl { this.toughness = new MageInt(1); // {tap}: Target creature you control gets +2/+0 until end of turn. Activate this ability only during your turn, before attackers are declared. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new BoostTargetEffect(2, 0, Duration.EndOfTurn), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new BoostTargetEffect(2, 0), new TapSourceCost(), + MyTurnBeforeAttackersDeclaredCondition.instance + ); ability.addTarget(new TargetControlledCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/y/YasovaDragonclaw.java b/Mage.Sets/src/mage/cards/y/YasovaDragonclaw.java index 165c9c2c20e..6e6c1848776 100644 --- a/Mage.Sets/src/mage/cards/y/YasovaDragonclaw.java +++ b/Mage.Sets/src/mage/cards/y/YasovaDragonclaw.java @@ -25,6 +25,7 @@ import mage.filter.predicate.ObjectSourcePlayer; import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -57,7 +58,7 @@ public final class YasovaDragonclaw extends CardImpl { effect.addEffect(effect2); effect.addEffect(new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn, ", and it gains haste until end of turn")); Ability ability = new BeginningOfCombatTriggeredAbility(effect); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/y/YavimayaIconoclast.java b/Mage.Sets/src/mage/cards/y/YavimayaIconoclast.java index 8b2d2c09950..5ff6c7e99c3 100644 --- a/Mage.Sets/src/mage/cards/y/YavimayaIconoclast.java +++ b/Mage.Sets/src/mage/cards/y/YavimayaIconoclast.java @@ -1,10 +1,9 @@ package mage.cards.y; import mage.MageInt; -import mage.abilities.TriggeredAbility; +import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.KickedCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.keyword.HasteAbility; @@ -37,10 +36,13 @@ public final class YavimayaIconoclast extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // When Yavimaya Iconoclast enters the battlefield, if it was kicked, it gets +1/+1 and gains haste until end of turn. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new BoostSourceEffect(1, 1, Duration.EndOfTurn)); - ability.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.EndOfTurn)); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, KickedCondition.ONCE, - "When {this} enters, if it was kicked, it gets +1/+1 and gains haste until end of turn.")); + Ability ability = new EntersBattlefieldTriggeredAbility(new BoostSourceEffect( + 1, 1, Duration.EndOfTurn + ).setText("it gets +1/+1")).withInterveningIf(KickedCondition.ONCE); + ability.addEffect(new GainAbilitySourceEffect( + HasteAbility.getInstance(), Duration.EndOfTurn + ).setText("and gains haste until end of turn")); + this.addAbility(ability); } private YavimayaIconoclast(final YavimayaIconoclast card) { diff --git a/Mage.Sets/src/mage/cards/y/YawgmothsVileOffering.java b/Mage.Sets/src/mage/cards/y/YawgmothsVileOffering.java index e8851a48ccd..bd619465ade 100644 --- a/Mage.Sets/src/mage/cards/y/YawgmothsVileOffering.java +++ b/Mage.Sets/src/mage/cards/y/YawgmothsVileOffering.java @@ -11,7 +11,6 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SuperType; import mage.constants.Zone; -import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent; import mage.filter.common.FilterPermanentCard; import mage.filter.predicate.Predicates; import mage.game.Game; @@ -47,7 +46,7 @@ public final class YawgmothsVileOffering extends CardImpl { // Destroy up to one target creature or planeswalker. Exile Yawgmoth's Vile Offering. this.getSpellAbility().addEffect(new YawgmothsVileOfferingEffect()); this.getSpellAbility().addTarget(new TargetCardInGraveyard(0, 1, cardFilter)); - this.getSpellAbility().addTarget(new TargetCreatureOrPlaneswalker(0, 1, new FilterCreatureOrPlaneswalkerPermanent(), false)); + this.getSpellAbility().addTarget(new TargetCreatureOrPlaneswalker(0, 1)); this.getSpellAbility().addEffect(new ExileSpellEffect()); } diff --git a/Mage.Sets/src/mage/cards/y/YesManPersonalSecuritron.java b/Mage.Sets/src/mage/cards/y/YesManPersonalSecuritron.java index 0db344a9708..c2a3593240f 100644 --- a/Mage.Sets/src/mage/cards/y/YesManPersonalSecuritron.java +++ b/Mage.Sets/src/mage/cards/y/YesManPersonalSecuritron.java @@ -1,6 +1,5 @@ package mage.cards.y; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; @@ -14,10 +13,11 @@ import mage.abilities.effects.common.CreateTokenTargetEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.TargetPlayerGainControlSourceEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; -import mage.abilities.hint.common.MyTurnHint; -import mage.constants.*; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; @@ -25,29 +25,31 @@ import mage.game.permanent.token.SoldierToken; import mage.target.common.TargetOpponent; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author Grath */ public final class YesManPersonalSecuritron extends CardImpl { public YesManPersonalSecuritron(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}{W}"); - + this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.ROBOT); this.power = new MageInt(2); this.toughness = new MageInt(2); // {T}: Target opponent gains control of Yes Man, Personal Securitron. When they do, you draw two cards and put a quest counter on Yes Man. Activate only during your turn. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new YesManPersonalSecuritronControlEffect(), new TapSourceCost(), MyTurnCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new YesManPersonalSecuritronControlEffect(), + new TapSourceCost(), MyTurnCondition.instance + ); ability.addTarget(new TargetOpponent()); - ability.addHint(MyTurnHint.instance); this.addAbility(ability); // Wild Card -- When Yes Man leaves the battlefield, its owner creates a tapped 1/1 white Soldier creature token for each quest counter on it. - this.addAbility(new LeavesBattlefieldTriggeredAbility(new YesManPersonalSecuritronLeavesEffect(), false)); + this.addAbility(new LeavesBattlefieldTriggeredAbility(new YesManPersonalSecuritronLeavesEffect()).withFlavorWord("Wild Card")); } private YesManPersonalSecuritron(final YesManPersonalSecuritron card) { @@ -61,6 +63,7 @@ public final class YesManPersonalSecuritron extends CardImpl { } class YesManPersonalSecuritronControlEffect extends TargetPlayerGainControlSourceEffect { + YesManPersonalSecuritronControlEffect() { super(); this.staticText = "Target opponent gains control of {this}. When they do, you draw two cards and put a quest counter on Yes Man."; @@ -91,6 +94,7 @@ class YesManPersonalSecuritronControlEffect extends TargetPlayerGainControlSourc } class YesManPersonalSecuritronLeavesEffect extends CreateTokenTargetEffect { + YesManPersonalSecuritronLeavesEffect() { super(new SoldierToken(), new CountersSourceCount(CounterType.QUEST), true); this.staticText = "its owner creates a tapped 1/1 white Soldier creature token for each quest counter on it."; @@ -114,4 +118,4 @@ class YesManPersonalSecuritronLeavesEffect extends CreateTokenTargetEffect { this.setTargetPointer(new FixedTarget(yesman.getOwnerId())); return super.apply(game, source); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/y/YshtolaNightsBlessed.java b/Mage.Sets/src/mage/cards/y/YshtolaNightsBlessed.java index d3e1214ef55..835f8223562 100644 --- a/Mage.Sets/src/mage/cards/y/YshtolaNightsBlessed.java +++ b/Mage.Sets/src/mage/cards/y/YshtolaNightsBlessed.java @@ -1,28 +1,28 @@ package mage.cards.y; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamagePlayersEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.hint.ConditionHint; -import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; -import mage.constants.*; +import mage.abilities.hint.Hint; import mage.abilities.keyword.VigilanceAbility; +import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.*; import mage.filter.FilterSpell; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.game.Game; import mage.watchers.common.PlayerLostLifeWatcher; +import java.util.UUID; + /** - * * @author inuenc */ public final class YshtolaNightsBlessed extends CardImpl { @@ -36,7 +36,7 @@ public final class YshtolaNightsBlessed extends CardImpl { public YshtolaNightsBlessed(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{U}{B}"); - + this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.CAT); this.subtype.add(SubType.WARLOCK); @@ -47,22 +47,16 @@ public final class YshtolaNightsBlessed extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // At the beginning of each end step, if a player lost 4 or more life this turn, you draw a card. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfEndStepTriggeredAbility( - TargetController.ANY, - new DrawCardSourceControllerEffect(1), - false - ), YshtolaNightsBlessedCondition.instance, "At the beginning of each end step, " + - "if a player lost 4 or more life this turn, you draw a card." - ).addHint(new ConditionHint(YshtolaNightsBlessedCondition.instance, "A player lost 4 or more life this turn"))); + this.addAbility(new BeginningOfEndStepTriggeredAbility( + TargetController.ANY, new DrawCardSourceControllerEffect(1, true), + false, YshtolaNightsBlessedCondition.instance + ).addHint(YshtolaNightsBlessedCondition.getHint())); // Whenever you cast a noncreature spell with mana value 3 or greater, Y'shtola deals 2 damage to each opponent and you gain 2 life. Ability ability = new SpellCastControllerTriggeredAbility( - new DamagePlayersEffect( - 2, TargetController.OPPONENT, "Y'shtola"), - filter, false + new DamagePlayersEffect(2, TargetController.OPPONENT), filter, false ); - ability.addEffect(new GainLifeEffect(2).setText("and you gain 2 life")); + ability.addEffect(new GainLifeEffect(2).concatBy("and")); this.addAbility(ability); } @@ -78,6 +72,11 @@ public final class YshtolaNightsBlessed extends CardImpl { enum YshtolaNightsBlessedCondition implements Condition { instance; + private static final Hint hint = new ConditionHint(instance); + + public static Hint getHint() { + return hint; + } @Override public boolean apply(Game game, Ability source) { @@ -85,10 +84,16 @@ enum YshtolaNightsBlessedCondition implements Condition { if (watcher == null) { return false; } - return game + return watcher != null + && game .getState() .getPlayersInRange(source.getControllerId(), game) .stream() - .anyMatch(uuid -> watcher.getLifeLost(uuid) > 3); + .anyMatch(uuid -> watcher.getLifeLost(uuid) >= 4); + } + + @Override + public String toString() { + return "a player lost 4 or more life this turn"; } } diff --git a/Mage.Sets/src/mage/cards/z/ZacamaPrimalCalamity.java b/Mage.Sets/src/mage/cards/z/ZacamaPrimalCalamity.java index c5ffe9fe2a6..7f60af05f18 100644 --- a/Mage.Sets/src/mage/cards/z/ZacamaPrimalCalamity.java +++ b/Mage.Sets/src/mage/cards/z/ZacamaPrimalCalamity.java @@ -1,14 +1,11 @@ - package mage.cards.z; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.condition.common.CastFromEverywhereSourceCondition; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.GainLifeEffect; @@ -21,13 +18,13 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; -import mage.constants.Zone; import mage.filter.StaticFilters; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class ZacamaPrimalCalamity extends CardImpl { @@ -51,10 +48,8 @@ public final class ZacamaPrimalCalamity extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // When Zacama, Primal Calamity enters the battlefield, if you cast it, untap all lands you control. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility(new UntapAllLandsControllerEffect(), false), - CastFromEverywhereSourceCondition.instance, - "When {this} enters, if you cast it, untap all lands you control.")); + this.addAbility(new EntersBattlefieldTriggeredAbility(new UntapAllLandsControllerEffect()) + .withInterveningIf(CastFromEverywhereSourceCondition.instance)); // {2}{R}: Zacama deals 3 damage to target creature. Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(3), new ManaCostsImpl<>("{2}{R}")); diff --git a/Mage.Sets/src/mage/cards/z/ZackFair.java b/Mage.Sets/src/mage/cards/z/ZackFair.java index 96ee7515874..af99fd6f41c 100644 --- a/Mage.Sets/src/mage/cards/z/ZackFair.java +++ b/Mage.Sets/src/mage/cards/z/ZackFair.java @@ -20,8 +20,7 @@ import mage.constants.SubType; import mage.constants.SuperType; import mage.counters.CounterType; import mage.filter.FilterPermanent; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.permanent.PermanentIdPredicate; +import mage.filter.predicate.permanent.PermanentReferenceInCollectionPredicate; import mage.game.Controllable; import mage.game.Game; import mage.game.permanent.Permanent; @@ -117,13 +116,7 @@ class ZackFairEffect extends OneShotEffect { FilterPermanent filter = new FilterPermanent( SubType.EQUIPMENT, "Equipment to attach to " + creature.getIdName() ); - filter.add(Predicates.or( - permanents - .stream() - .map(MageItem::getId) - .map(PermanentIdPredicate::new) - .collect(Collectors.toList()) - )); + filter.add(new PermanentReferenceInCollectionPredicate(permanents, game)); TargetPermanent target = new TargetPermanent(filter); target.withNotTarget(true); Optional.ofNullable(source) diff --git a/Mage.Sets/src/mage/cards/z/ZaskSkitteringSwarmlord.java b/Mage.Sets/src/mage/cards/z/ZaskSkitteringSwarmlord.java index 856abc25f6e..92206d080d9 100644 --- a/Mage.Sets/src/mage/cards/z/ZaskSkitteringSwarmlord.java +++ b/Mage.Sets/src/mage/cards/z/ZaskSkitteringSwarmlord.java @@ -18,6 +18,7 @@ import mage.filter.FilterCard; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -65,7 +66,7 @@ public final class ZaskSkitteringSwarmlord extends CardImpl { ); ability2.addEffect(new GainAbilityTargetEffect(DeathtouchAbility.getInstance(), Duration.EndOfTurn) .setText(" and gains deathtouch until end of turn")); - ability2.addTarget(new TargetCreaturePermanent(filter3)); + ability2.addTarget(new TargetPermanent(filter3)); this.addAbility(ability2); } diff --git a/Mage.Sets/src/mage/cards/z/ZealotsEnDal.java b/Mage.Sets/src/mage/cards/z/ZealotsEnDal.java index 714cc57e277..8da0251b702 100644 --- a/Mage.Sets/src/mage/cards/z/ZealotsEnDal.java +++ b/Mage.Sets/src/mage/cards/z/ZealotsEnDal.java @@ -1,35 +1,38 @@ package mage.cards.z; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.condition.InvertCondition; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; -import mage.constants.SubType; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; 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.FilterControlledPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class ZealotsEnDal extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent(); + private static final FilterPermanent filter = new FilterControlledPermanent("all nonland permanents you control are white"); static { filter.add(Predicates.not(new ColorPredicate(ObjectColor.WHITE))); filter.add(Predicates.not(CardType.LAND.getPredicate())); } + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.EQUAL_TO, 0); + public ZealotsEnDal(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); @@ -39,11 +42,7 @@ public final class ZealotsEnDal extends CardImpl { this.toughness = new MageInt(4); // At the beginning of your upkeep, if all nonland permanents you control are white, you gain 1 life. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new BeginningOfUpkeepTriggeredAbility(new GainLifeEffect(1)), - new InvertCondition(new PermanentsOnTheBattlefieldCondition(filter)), - "At the beginning of your upkeep, if all nonland permanents you control are white, you gain 1 life." - )); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new GainLifeEffect(1)).withInterveningIf(condition)); } private ZealotsEnDal(final ZealotsEnDal card) { diff --git a/Mage.Sets/src/mage/cards/z/ZeganaUtopianSpeaker.java b/Mage.Sets/src/mage/cards/z/ZeganaUtopianSpeaker.java index 220c79c1331..c29b1afdb59 100644 --- a/Mage.Sets/src/mage/cards/z/ZeganaUtopianSpeaker.java +++ b/Mage.Sets/src/mage/cards/z/ZeganaUtopianSpeaker.java @@ -3,16 +3,23 @@ package mage.cards.z; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.abilities.keyword.AdaptAbility; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.AnotherPredicate; import java.util.UUID; @@ -21,6 +28,15 @@ import java.util.UUID; */ public final class ZeganaUtopianSpeaker extends CardImpl { + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("you control another creature with a +1/+1 counter on it"); + + static { + filter.add(AnotherPredicate.instance); + filter.add(CounterType.P1P1.getPredicate()); + } + + private static final Condition condition = new PermanentsOnTheBattlefieldCondition(filter); + public ZeganaUtopianSpeaker(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{U}"); @@ -31,26 +47,16 @@ public final class ZeganaUtopianSpeaker extends CardImpl { this.toughness = new MageInt(4); // When Zegana, Utopian Speaker enters the battlefield, if you control another creature with a +1/+1 counter on it, draw a card. - this.addAbility(new ConditionalInterveningIfTriggeredAbility( - new EntersBattlefieldTriggeredAbility( - new DrawCardSourceControllerEffect(1), false - ), new PermanentsOnTheBattlefieldCondition(StaticFilters.FILTER_OTHER_CONTROLLED_CREATURE_P1P1), - "When {this} enters, " + - "if you control another creature " + - "with a +1/+1 counter on it, draw a card." - ) - ); + this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)).withInterveningIf(condition)); // {4}{G}{U}: Adapt 4. this.addAbility(new AdaptAbility(4, "{4}{G}{U}")); // Each creature you control with a +1/+1 counter on it has trample. - this.addAbility(new SimpleStaticAbility( - new GainAbilityAllEffect( - TrampleAbility.getInstance(), Duration.WhileOnBattlefield, - StaticFilters.FILTER_EACH_CONTROLLED_CREATURE_P1P1) - ) - ); + this.addAbility(new SimpleStaticAbility(new GainAbilityAllEffect( + TrampleAbility.getInstance(), Duration.WhileOnBattlefield, + StaticFilters.FILTER_EACH_CONTROLLED_CREATURE_P1P1 + ))); } private ZeganaUtopianSpeaker(final ZeganaUtopianSpeaker card) { diff --git a/Mage.Sets/src/mage/cards/z/ZephyrSentinel.java b/Mage.Sets/src/mage/cards/z/ZephyrSentinel.java index d0d6d54b835..bec1a7bba71 100644 --- a/Mage.Sets/src/mage/cards/z/ZephyrSentinel.java +++ b/Mage.Sets/src/mage/cards/z/ZephyrSentinel.java @@ -17,8 +17,9 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; +import java.util.Optional; import java.util.UUID; /** @@ -42,7 +43,7 @@ public final class ZephyrSentinel extends CardImpl { // When Zephyr Sentinel enters the battlefield, return up to one other target creature you control to its owner's hand. If it was a Soldier, put a +1/+1 counter on Zephyr Sentinel. Ability ability = new EntersBattlefieldTriggeredAbility(new ZephyrSentinelEffect()); - ability.addTarget(new TargetControlledCreaturePermanent(0, 1, StaticFilters.FILTER_OTHER_CONTROLLED_CREATURE, false)); + ability.addTarget(new TargetPermanent(0, 1, StaticFilters.FILTER_OTHER_CONTROLLED_CREATURE)); this.addAbility(ability); } @@ -74,21 +75,16 @@ class ZephyrSentinelEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent targetPermanent = game.getPermanent(source.getFirstTarget()); - if (targetPermanent == null) { - return false; - } Player controller = game.getPlayer(source.getControllerId()); - if (controller == null) { + Permanent targetPermanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (controller == null || targetPermanent == null) { return false; } boolean soldier = targetPermanent.hasSubtype(SubType.SOLDIER, game); controller.moveCards(targetPermanent, Zone.HAND, source, game); if (soldier) { - Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game); - if (sourcePermanent != null) { - sourcePermanent.addCounters(CounterType.P1P1.createInstance(), source, game); - } + Optional.ofNullable(source.getSourcePermanentIfItStillExists(game)) + .ifPresent(permanent -> permanent.addCounters(CounterType.P1P1.createInstance(), source, game)); } return true; } diff --git a/Mage.Sets/src/mage/cards/z/ZhalfirinCommander.java b/Mage.Sets/src/mage/cards/z/ZhalfirinCommander.java index 516b3c24a85..e22f33026ba 100644 --- a/Mage.Sets/src/mage/cards/z/ZhalfirinCommander.java +++ b/Mage.Sets/src/mage/cards/z/ZhalfirinCommander.java @@ -15,6 +15,7 @@ import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -40,7 +41,7 @@ public final class ZhalfirinCommander extends CardImpl { this.addAbility(new FlankingAbility()); // {1}{W}{W}: Target Knight creature gets +1/+1 until end of turn. Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(1, 1, Duration.EndOfTurn), new ManaCostsImpl<>("{1}{W}{W}")); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/z/ZhalfirinDecoy.java b/Mage.Sets/src/mage/cards/z/ZhalfirinDecoy.java index 9b7aa396539..eb088f1ec36 100644 --- a/Mage.Sets/src/mage/cards/z/ZhalfirinDecoy.java +++ b/Mage.Sets/src/mage/cards/z/ZhalfirinDecoy.java @@ -10,7 +10,6 @@ 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.target.common.TargetCreaturePermanent; import mage.watchers.common.CreatureEnteredControllerWatcher; @@ -32,8 +31,7 @@ public final class ZhalfirinDecoy extends CardImpl { // {T}: Tap target creature. Activate this ability only if you had a creature enter the battlefield under your control this turn. Ability ability = new ActivateIfConditionActivatedAbility( - Zone.BATTLEFIELD, new TapTargetEffect(), - new TapSourceCost(), ZhalfirinDecoyCondition.instance + new TapTargetEffect(), new TapSourceCost(), ZhalfirinDecoyCondition.instance ); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability, new CreatureEnteredControllerWatcher()); diff --git a/Mage.Sets/src/mage/cards/z/ZhugeJinWuStrategist.java b/Mage.Sets/src/mage/cards/z/ZhugeJinWuStrategist.java index ef546c171d6..e3ba7d435a0 100644 --- a/Mage.Sets/src/mage/cards/z/ZhugeJinWuStrategist.java +++ b/Mage.Sets/src/mage/cards/z/ZhugeJinWuStrategist.java @@ -1,7 +1,5 @@ - package mage.cards.z; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; @@ -10,17 +8,21 @@ import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.common.combat.CantBeBlockedTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class ZhugeJinWuStrategist extends CardImpl { public ZhugeJinWuStrategist(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{U}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN, SubType.ADVISOR); @@ -28,8 +30,10 @@ public final class ZhugeJinWuStrategist extends CardImpl { this.toughness = new MageInt(1); // {tap}: Target creature can't be blocked this turn. Activate this ability only during your turn, before attackers are declared. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, - new CantBeBlockedTargetEffect(Duration.EndOfTurn), new TapSourceCost(), MyTurnBeforeAttackersDeclaredCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new CantBeBlockedTargetEffect(Duration.EndOfTurn), new TapSourceCost(), + MyTurnBeforeAttackersDeclaredCondition.instance + ); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/z/ZimoneParadoxSculptor.java b/Mage.Sets/src/mage/cards/z/ZimoneParadoxSculptor.java index 5f5ce39c441..2f5c267e606 100644 --- a/Mage.Sets/src/mage/cards/z/ZimoneParadoxSculptor.java +++ b/Mage.Sets/src/mage/cards/z/ZimoneParadoxSculptor.java @@ -17,30 +17,24 @@ import mage.constants.SuperType; import mage.counters.Counter; import mage.counters.CounterType; import mage.filter.FilterPermanent; -import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.Predicates; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.target.Target; import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import java.util.UUID; /** - * * @author ciaccona007 */ public final class ZimoneParadoxSculptor extends CardImpl { - private static final FilterControlledCreaturePermanent filterCreature = new FilterControlledCreaturePermanent(); - private static final FilterPermanent filterArtifactOrCreature = new FilterControlledPermanent(); + private static final FilterPermanent filter = new FilterControlledPermanent("up to two artifacts and/or creatures you control"); static { - filterCreature.setMessage("up to two creatures you control"); - filterArtifactOrCreature.setMessage("up to two artifacts and/or creatures you control"); - filterArtifactOrCreature.add(Predicates.or( + filter.add(Predicates.or( CardType.ARTIFACT.getPredicate(), CardType.CREATURE.getPredicate() )); @@ -48,7 +42,7 @@ public final class ZimoneParadoxSculptor extends CardImpl { public ZimoneParadoxSculptor(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{U}"); - + this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WIZARD); @@ -57,19 +51,15 @@ public final class ZimoneParadoxSculptor extends CardImpl { // At the beginning of combat on your turn, put a +1/+1 counter on each of up to two target creatures you control. Ability triggeredAbility = new BeginningOfCombatTriggeredAbility( - new AddCountersTargetEffect( - CounterType.P1P1.createInstance() - ).setText("put a +1/+1 counter on each of up to two target creatures you control") - ); - triggeredAbility.addTarget( - new TargetControlledCreaturePermanent(0, 2, filterCreature, false) + new AddCountersTargetEffect(CounterType.P1P1.createInstance()) ); + triggeredAbility.addTarget(new TargetControlledCreaturePermanent(0, 2)); this.addAbility(triggeredAbility); // {G}{U}, {T}: Double the number of each kind of counter on up to two target creatures and/or artifacts you control. Ability ability = new SimpleActivatedAbility(new ZimoneParadoxSculptorEffect(), new ManaCostsImpl<>("{G}{U}")); ability.addCost(new TapSourceCost()); - ability.addTarget(new TargetPermanent(0, 2, filterArtifactOrCreature)); + ability.addTarget(new TargetPermanent(0, 2, filter)); this.addAbility(ability); } @@ -102,20 +92,16 @@ class ZimoneParadoxSculptorEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - boolean didOne = false; - - for (Target target : source.getTargets()) { - for (UUID targetID : target.getTargets()) { - Permanent permanent = game.getPermanent(targetID); - if (permanent != null) { - for (Counter counter : permanent.getCounters(game).values()) { - Counter newCounter = new Counter(counter.getName(), counter.getCount()); - permanent.addCounters(newCounter, source.getControllerId(), source, game); - didOne = true; - } - } + for (UUID targetId : getTargetPointer().getTargets(game, source)) { + Permanent permanent = game.getPermanent(targetId); + if (permanent == null) { + continue; + } + for (Counter counter : permanent.getCounters(game).values()) { + Counter newCounter = new Counter(counter.getName(), counter.getCount()); + permanent.addCounters(newCounter, source.getControllerId(), source, game); } } - return didOne; + return true; } } diff --git a/Mage.Sets/src/mage/cards/z/ZndrspltsJudgment.java b/Mage.Sets/src/mage/cards/z/ZndrspltsJudgment.java index 7d894bfaee6..0ae82739bea 100644 --- a/Mage.Sets/src/mage/cards/z/ZndrspltsJudgment.java +++ b/Mage.Sets/src/mage/cards/z/ZndrspltsJudgment.java @@ -1,7 +1,5 @@ - package mage.cards.z; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; @@ -16,11 +14,12 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.players.Player; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class ZndrspltsJudgment extends CardImpl { @@ -72,7 +71,8 @@ class ZndrspltsJudgmentEffect extends OneShotEffect { } FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you control"); filter.add(new ControllerIdPredicate(player.getId())); - TargetCreaturePermanent target = new TargetCreaturePermanent(1, 1, filter, true); + TargetPermanent target = new TargetPermanent(filter); + target.withNotTarget(true); if (!player.choose(Outcome.Copy, target, source, game)) { continue; } @@ -83,7 +83,8 @@ class ZndrspltsJudgmentEffect extends OneShotEffect { for (Player player : choice.getFoes()) { FilterCreaturePermanent filter = new FilterCreaturePermanent("creature you control"); filter.add(new ControllerIdPredicate(player.getId())); - TargetCreaturePermanent target = new TargetCreaturePermanent(1, 1, filter, true); + TargetPermanent target = new TargetPermanent(filter); + target.withNotTarget(true); if (!player.choose(Outcome.ReturnToHand, target, source, game)) { continue; } diff --git a/Mage.Sets/src/mage/cards/z/ZombieAssassin.java b/Mage.Sets/src/mage/cards/z/ZombieAssassin.java index d5ef339caf1..4fea3ce2bf8 100644 --- a/Mage.Sets/src/mage/cards/z/ZombieAssassin.java +++ b/Mage.Sets/src/mage/cards/z/ZombieAssassin.java @@ -15,9 +15,12 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.StaticFilters; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetCreaturePermanent; +import static mage.filter.StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK; + /** * * @author cbt33 @@ -33,7 +36,7 @@ public final class ZombieAssassin extends CardImpl { // {tap}, Exile two cards from your graveyard and Zombie Assassin: Destroy target nonblack creature. It can't be regenerated. Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(true), new TapSourceCost()); - Target target = new TargetCreaturePermanent(StaticFilters.FILTER_PERMANENT_CREATURE_NON_BLACK); + Target target = new TargetPermanent(FILTER_PERMANENT_CREATURE_NON_BLACK); ability.addTarget(target); ability.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard(2,2,StaticFilters.FILTER_CARDS_FROM_YOUR_GRAVEYARD))); ability.addCost(new ExileSourceCost()); diff --git a/Mage.Sets/src/mage/cards/z/ZuranEnchanter.java b/Mage.Sets/src/mage/cards/z/ZuranEnchanter.java index e9dccf2d273..c63633158a5 100644 --- a/Mage.Sets/src/mage/cards/z/ZuranEnchanter.java +++ b/Mage.Sets/src/mage/cards/z/ZuranEnchanter.java @@ -7,12 +7,10 @@ import mage.abilities.condition.common.MyTurnCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.discard.DiscardTargetEffect; -import mage.abilities.hint.common.MyTurnHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; import mage.target.TargetPlayer; import java.util.UUID; @@ -29,10 +27,11 @@ public final class ZuranEnchanter extends CardImpl { this.toughness = new MageInt(1); // {2}{B}, {T}: Target player discards a card. Activate this ability only during your turn. - Ability ability = new ActivateIfConditionActivatedAbility(Zone.BATTLEFIELD, new DiscardTargetEffect(1), new ManaCostsImpl<>("{2}{B}"), MyTurnCondition.instance); + Ability ability = new ActivateIfConditionActivatedAbility( + new DiscardTargetEffect(1), new ManaCostsImpl<>("{2}{B}"), MyTurnCondition.instance + ); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetPlayer()); - ability.addHint(MyTurnHint.instance); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java new file mode 100644 index 00000000000..4cfe962a30a --- /dev/null +++ b/Mage.Sets/src/mage/sets/AvatarTheLastAirbender.java @@ -0,0 +1,23 @@ +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.constants.SetType; + +/** + * @author TheElk801 + */ +public final class AvatarTheLastAirbender extends ExpansionSet { + + private static final AvatarTheLastAirbender instance = new AvatarTheLastAirbender(); + + public static AvatarTheLastAirbender getInstance() { + return instance; + } + + private AvatarTheLastAirbender() { + super("Avatar: The Last Airbender", "TLA", ExpansionSet.buildDate(2025, 11, 21), SetType.EXPANSION); + this.blockName = "Avatar: The Last Airbender"; // for sorting in GUI + this.rotationSet = true; + this.hasBasicLands = false; // temporary + } +} diff --git a/Mage.Sets/src/mage/sets/BloomburrowCommander.java b/Mage.Sets/src/mage/sets/BloomburrowCommander.java index 854ec0853ea..cf26ee2d650 100644 --- a/Mage.Sets/src/mage/sets/BloomburrowCommander.java +++ b/Mage.Sets/src/mage/sets/BloomburrowCommander.java @@ -93,6 +93,7 @@ public final class BloomburrowCommander extends ExpansionSet { cards.add(new SetCardInfo("Devilish Valet", 195, Rarity.RARE, mage.cards.d.DevilishValet.class)); cards.add(new SetCardInfo("Domri, Anarch of Bolas", 98, Rarity.RARE, mage.cards.d.DomriAnarchOfBolas.class)); cards.add(new SetCardInfo("Dusk // Dawn", 138, Rarity.RARE, mage.cards.d.DuskDawn.class)); + cards.add(new SetCardInfo("Echoing Assault", 24, Rarity.RARE, mage.cards.e.EchoingAssault.class)); cards.add(new SetCardInfo("Elspeth, Sun's Champion", 97, Rarity.MYTHIC, mage.cards.e.ElspethSunsChampion.class)); cards.add(new SetCardInfo("End-Raze Forerunners", 214, Rarity.RARE, mage.cards.e.EndRazeForerunners.class)); cards.add(new SetCardInfo("Esika's Chariot", 215, Rarity.RARE, mage.cards.e.EsikasChariot.class)); diff --git a/Mage.Sets/src/mage/sets/EdgeOfEternities.java b/Mage.Sets/src/mage/sets/EdgeOfEternities.java new file mode 100644 index 00000000000..b8d4b5138d4 --- /dev/null +++ b/Mage.Sets/src/mage/sets/EdgeOfEternities.java @@ -0,0 +1,49 @@ +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.constants.Rarity; +import mage.constants.SetType; + +/** + * @author TheElk801 + */ +public final class EdgeOfEternities extends ExpansionSet { + + private static final EdgeOfEternities instance = new EdgeOfEternities(); + + public static EdgeOfEternities getInstance() { + return instance; + } + + private EdgeOfEternities() { + super("Edge of Eternities", "EOE", ExpansionSet.buildDate(2025, 8, 1), SetType.EXPANSION); + this.blockName = "Edge of Eternities"; // for sorting in GUI + this.rotationSet = true; + + cards.add(new SetCardInfo("Alpharael, Dreaming Acolyte", 212, Rarity.UNCOMMON, mage.cards.a.AlpharaelDreamingAcolyte.class)); + cards.add(new SetCardInfo("Breeding Pool", 251, Rarity.RARE, mage.cards.b.BreedingPool.class)); + cards.add(new SetCardInfo("Forest", 266, Rarity.LAND, mage.cards.basiclands.Forest.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Forest", 371, Rarity.LAND, mage.cards.basiclands.Forest.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Godless Shrine", 254, Rarity.RARE, mage.cards.g.GodlessShrine.class)); + cards.add(new SetCardInfo("Harmonious Grovestrider", 189, Rarity.UNCOMMON, mage.cards.h.HarmoniousGrovestrider.class)); + cards.add(new SetCardInfo("Island", 263, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Island", 368, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 265, Rarity.LAND, mage.cards.basiclands.Mountain.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 370, Rarity.LAND, mage.cards.basiclands.Mountain.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Plains", 262, Rarity.LAND, mage.cards.basiclands.Plains.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Plains", 367, Rarity.LAND, mage.cards.basiclands.Plains.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Sacred Foundry", 256, Rarity.RARE, mage.cards.s.SacredFoundry.class)); + cards.add(new SetCardInfo("Sami, Ship's Engineer", 225, Rarity.UNCOMMON, mage.cards.s.SamiShipsEngineer.class)); + cards.add(new SetCardInfo("Sothera, the Supervoid", 115, Rarity.MYTHIC, mage.cards.s.SotheraTheSupervoid.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sothera, the Supervoid", 360, Rarity.MYTHIC, mage.cards.s.SotheraTheSupervoid.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sothera, the Supervoid", 382, Rarity.MYTHIC, mage.cards.s.SotheraTheSupervoid.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Sothera, the Supervoid", 386, Rarity.MYTHIC, mage.cards.s.SotheraTheSupervoid.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Stomping Ground", 258, Rarity.RARE, mage.cards.s.StompingGround.class)); + cards.add(new SetCardInfo("Swamp", 264, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 369, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Tannuk, Memorial Ensign", 233, Rarity.UNCOMMON, mage.cards.t.TannukMemorialEnsign.class)); + cards.add(new SetCardInfo("Tezzeret, Cruel Captain", 2, Rarity.MYTHIC, mage.cards.t.TezzeretCruelCaptain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Tezzeret, Cruel Captain", 287, Rarity.MYTHIC, mage.cards.t.TezzeretCruelCaptain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Watery Grave", 261, Rarity.RARE, mage.cards.w.WateryGrave.class)); + } +} diff --git a/Mage.Sets/src/mage/sets/EdgeOfEternitiesCommander.java b/Mage.Sets/src/mage/sets/EdgeOfEternitiesCommander.java new file mode 100644 index 00000000000..4b361a8935a --- /dev/null +++ b/Mage.Sets/src/mage/sets/EdgeOfEternitiesCommander.java @@ -0,0 +1,25 @@ +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.constants.Rarity; +import mage.constants.SetType; + +/** + * @author TheElk801 + */ +public final class EdgeOfEternitiesCommander extends ExpansionSet { + + private static final EdgeOfEternitiesCommander instance = new EdgeOfEternitiesCommander(); + + public static EdgeOfEternitiesCommander getInstance() { + return instance; + } + + private EdgeOfEternitiesCommander() { + super("Edge of Eternities Commander", "EOC", ExpansionSet.buildDate(2025, 8, 1), SetType.SUPPLEMENTAL); + this.hasBasicLands = false; + + cards.add(new SetCardInfo("Kilo, Apogee Mind", 3, Rarity.MYTHIC, mage.cards.k.KiloApogeeMind.class)); + cards.add(new SetCardInfo("Szarel, Genesis Shepherd", 4, Rarity.MYTHIC, mage.cards.s.SzarelGenesisShepherd.class)); + } +} diff --git a/Mage.Sets/src/mage/sets/Fallout.java b/Mage.Sets/src/mage/sets/Fallout.java index 0cf9a4160b3..e2e92d8770e 100644 --- a/Mage.Sets/src/mage/sets/Fallout.java +++ b/Mage.Sets/src/mage/sets/Fallout.java @@ -430,10 +430,10 @@ public final class Fallout extends ExpansionSet { cards.add(new SetCardInfo("Intelligence Bobblehead", 1061, Rarity.UNCOMMON, mage.cards.i.IntelligenceBobblehead.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Intelligence Bobblehead", 134, Rarity.UNCOMMON, mage.cards.i.IntelligenceBobblehead.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Intelligence Bobblehead", 662, Rarity.UNCOMMON, mage.cards.i.IntelligenceBobblehead.class, NON_FULL_USE_VARIOUS)); - //cards.add(new SetCardInfo("Inventory Management", 105, Rarity.RARE, mage.cards.i.InventoryManagement.class, NON_FULL_USE_VARIOUS)); - //cards.add(new SetCardInfo("Inventory Management", 342, Rarity.RARE, mage.cards.i.InventoryManagement.class, NON_FULL_USE_VARIOUS)); - //cards.add(new SetCardInfo("Inventory Management", 633, Rarity.RARE, mage.cards.i.InventoryManagement.class, NON_FULL_USE_VARIOUS)); - //cards.add(new SetCardInfo("Inventory Management", 870, Rarity.RARE, mage.cards.i.InventoryManagement.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Inventory Management", 105, Rarity.RARE, mage.cards.i.InventoryManagement.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Inventory Management", 342, Rarity.RARE, mage.cards.i.InventoryManagement.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Inventory Management", 633, Rarity.RARE, mage.cards.i.InventoryManagement.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Inventory Management", 870, Rarity.RARE, mage.cards.i.InventoryManagement.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Irrigated Farmland", 1027, Rarity.RARE, mage.cards.i.IrrigatedFarmland.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Irrigated Farmland", 268, Rarity.RARE, mage.cards.i.IrrigatedFarmland.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Irrigated Farmland", 499, Rarity.RARE, mage.cards.i.IrrigatedFarmland.class, NON_FULL_USE_VARIOUS)); @@ -571,10 +571,10 @@ public final class Fallout extends ExpansionSet { cards.add(new SetCardInfo("Mutational Advantage", 950, Rarity.RARE, mage.cards.m.MutationalAdvantage.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Myriad Landscape", 274, Rarity.UNCOMMON, mage.cards.m.MyriadLandscape.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Myriad Landscape", 802, Rarity.UNCOMMON, mage.cards.m.MyriadLandscape.class, NON_FULL_USE_VARIOUS)); - //cards.add(new SetCardInfo("Mysterious Stranger", 334, Rarity.RARE, mage.cards.m.MysteriousStranger.class, NON_FULL_USE_VARIOUS)); - //cards.add(new SetCardInfo("Mysterious Stranger", 591, Rarity.RARE, mage.cards.m.MysteriousStranger.class, NON_FULL_USE_VARIOUS)); - //cards.add(new SetCardInfo("Mysterious Stranger", 63, Rarity.RARE, mage.cards.m.MysteriousStranger.class, NON_FULL_USE_VARIOUS)); - //cards.add(new SetCardInfo("Mysterious Stranger", 862, Rarity.RARE, mage.cards.m.MysteriousStranger.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mysterious Stranger", 334, Rarity.RARE, mage.cards.m.MysteriousStranger.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mysterious Stranger", 591, Rarity.RARE, mage.cards.m.MysteriousStranger.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mysterious Stranger", 63, Rarity.RARE, mage.cards.m.MysteriousStranger.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mysterious Stranger", 862, Rarity.RARE, mage.cards.m.MysteriousStranger.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mystic Forge", 1012, Rarity.RARE, mage.cards.m.MysticForge.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mystic Forge", 236, Rarity.RARE, mage.cards.m.MysticForge.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mystic Forge", 484, Rarity.RARE, mage.cards.m.MysticForge.class, NON_FULL_USE_VARIOUS)); @@ -603,10 +603,10 @@ public final class Fallout extends ExpansionSet { cards.add(new SetCardInfo("Nuka-Cola Vending Machine", 358, Rarity.UNCOMMON, mage.cards.n.NukaColaVendingMachine.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Nuka-Cola Vending Machine", 665, Rarity.UNCOMMON, mage.cards.n.NukaColaVendingMachine.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Nuka-Cola Vending Machine", 886, Rarity.UNCOMMON, mage.cards.n.NukaColaVendingMachine.class, NON_FULL_USE_VARIOUS)); - //cards.add(new SetCardInfo("Nuka-Nuke Launcher", 138, Rarity.RARE, mage.cards.n.NukaNukeLauncher.class, NON_FULL_USE_VARIOUS)); - //cards.add(new SetCardInfo("Nuka-Nuke Launcher", 434, Rarity.RARE, mage.cards.n.NukaNukeLauncher.class, NON_FULL_USE_VARIOUS)); - //cards.add(new SetCardInfo("Nuka-Nuke Launcher", 666, Rarity.RARE, mage.cards.n.NukaNukeLauncher.class, NON_FULL_USE_VARIOUS)); - //cards.add(new SetCardInfo("Nuka-Nuke Launcher", 962, Rarity.RARE, mage.cards.n.NukaNukeLauncher.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Nuka-Nuke Launcher", 138, Rarity.RARE, mage.cards.n.NukaNukeLauncher.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Nuka-Nuke Launcher", 434, Rarity.RARE, mage.cards.n.NukaNukeLauncher.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Nuka-Nuke Launcher", 666, Rarity.RARE, mage.cards.n.NukaNukeLauncher.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Nuka-Nuke Launcher", 962, Rarity.RARE, mage.cards.n.NukaNukeLauncher.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("One with the Machine", 179, Rarity.RARE, mage.cards.o.OneWithTheMachine.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("One with the Machine", 462, Rarity.RARE, mage.cards.o.OneWithTheMachine.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("One with the Machine", 707, Rarity.RARE, mage.cards.o.OneWithTheMachine.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage.Sets/src/mage/sets/MurdersAtKarlovManorCommander.java b/Mage.Sets/src/mage/sets/MurdersAtKarlovManorCommander.java index b397fe215df..5054600618e 100644 --- a/Mage.Sets/src/mage/sets/MurdersAtKarlovManorCommander.java +++ b/Mage.Sets/src/mage/sets/MurdersAtKarlovManorCommander.java @@ -115,6 +115,7 @@ public final class MurdersAtKarlovManorCommander extends ExpansionSet { cards.add(new SetCardInfo("Finale of Revelation", 106, Rarity.MYTHIC, mage.cards.f.FinaleOfRevelation.class)); cards.add(new SetCardInfo("Follow the Bodies", 23, Rarity.RARE, mage.cards.f.FollowTheBodies.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Follow the Bodies", 333, Rarity.RARE, mage.cards.f.FollowTheBodies.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Foreboding Steamboat", 28, Rarity.RARE, mage.cards.f.ForebodingSteamboat.class)); cards.add(new SetCardInfo("Fortified Village", 262, Rarity.RARE, mage.cards.f.FortifiedVillage.class)); cards.add(new SetCardInfo("Frontier Warmonger", 154, Rarity.RARE, mage.cards.f.FrontierWarmonger.class)); cards.add(new SetCardInfo("Fumigate", 66, Rarity.RARE, mage.cards.f.Fumigate.class)); diff --git a/Mage.Sets/src/mage/sets/RavnicaClueEdition.java b/Mage.Sets/src/mage/sets/RavnicaClueEdition.java index 6111eb31787..b66b3f9823e 100644 --- a/Mage.Sets/src/mage/sets/RavnicaClueEdition.java +++ b/Mage.Sets/src/mage/sets/RavnicaClueEdition.java @@ -78,7 +78,7 @@ public final class RavnicaClueEdition extends ExpansionSet { cards.add(new SetCardInfo("Dimir Guildgate", 234, Rarity.COMMON, mage.cards.d.DimirGuildgate.class)); cards.add(new SetCardInfo("Dimir Guildmage", 186, Rarity.UNCOMMON, mage.cards.d.DimirGuildmage.class)); cards.add(new SetCardInfo("Dimir Signet", 221, Rarity.COMMON, mage.cards.d.DimirSignet.class)); - //cards.add(new SetCardInfo("Dimir Strandcatcher", 30, Rarity.RARE, mage.cards.d.DimirStrandcatcher.class)); + cards.add(new SetCardInfo("Dimir Strandcatcher", 30, Rarity.RARE, mage.cards.d.DimirStrandcatcher.class)); cards.add(new SetCardInfo("Dining Room", 15, Rarity.UNCOMMON, mage.cards.d.DiningRoom.class)); cards.add(new SetCardInfo("Direct Current", 132, Rarity.COMMON, mage.cards.d.DirectCurrent.class)); cards.add(new SetCardInfo("Discovery // Dispersal", 187, Rarity.UNCOMMON, mage.cards.d.DiscoveryDispersal.class)); @@ -195,7 +195,7 @@ public final class RavnicaClueEdition extends ExpansionSet { cards.add(new SetCardInfo("Plains", 255, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Plains", 256, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Plains", 257, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); - //cards.add(new SetCardInfo("Portal Manipulator", 40, Rarity.UNCOMMON, mage.cards.p.PortalManipulator.class)); + cards.add(new SetCardInfo("Portal Manipulator", 40, Rarity.UNCOMMON, mage.cards.p.PortalManipulator.class)); cards.add(new SetCardInfo("Predatory Impetus", 172, Rarity.COMMON, mage.cards.p.PredatoryImpetus.class)); cards.add(new SetCardInfo("Psychic Impetus", 92, Rarity.COMMON, mage.cards.p.PsychicImpetus.class)); cards.add(new SetCardInfo("Pyrewild Shaman", 144, Rarity.UNCOMMON, mage.cards.p.PyrewildShaman.class)); diff --git a/Mage.Sets/src/mage/sets/SecretLairDrop.java b/Mage.Sets/src/mage/sets/SecretLairDrop.java index 6e0085ed7b0..d8a6eb5b0f3 100644 --- a/Mage.Sets/src/mage/sets/SecretLairDrop.java +++ b/Mage.Sets/src/mage/sets/SecretLairDrop.java @@ -365,7 +365,7 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Blood Moon", 366, Rarity.RARE, mage.cards.b.BloodMoon.class)); cards.add(new SetCardInfo("Cut // Ribbons", 367, Rarity.RARE, mage.cards.c.CutRibbons.class)); cards.add(new SetCardInfo("Teferi's Puzzle Box", 368, Rarity.RARE, mage.cards.t.TeferisPuzzleBox.class)); - cards.add(new SetCardInfo("Generous Gift", 369, Rarity.RARE, mage.cards.g.GenerousGift.class)); + cards.add(new SetCardInfo("Generous Gift", 369, Rarity.RARE, mage.cards.g.GenerousGift.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Chain Lightning", 370, Rarity.RARE, mage.cards.c.ChainLightning.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Kodama's Reach", 371, Rarity.RARE, mage.cards.k.KodamasReach.class)); cards.add(new SetCardInfo("Heirloom Blade", 372, Rarity.RARE, mage.cards.h.HeirloomBlade.class)); @@ -607,7 +607,7 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Eldrazi Monument", 603, Rarity.MYTHIC, mage.cards.e.EldraziMonument.class)); cards.add(new SetCardInfo("Ornithopter", 604, Rarity.RARE, mage.cards.o.Ornithopter.class)); cards.add(new SetCardInfo("Panharmonicon", 605, Rarity.RARE, mage.cards.p.Panharmonicon.class)); - cards.add(new SetCardInfo("Swiftfoot Boots", 606, Rarity.RARE, mage.cards.s.SwiftfootBoots.class)); + cards.add(new SetCardInfo("Swiftfoot Boots", 606, Rarity.RARE, mage.cards.s.SwiftfootBoots.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Rogue's Passage", 607, Rarity.RARE, mage.cards.r.RoguesPassage.class)); cards.add(new SetCardInfo("Darksteel Citadel", 608, Rarity.RARE, mage.cards.d.DarksteelCitadel.class)); cards.add(new SetCardInfo("Havengul Laboratory", 609, Rarity.RARE, mage.cards.h.HavengulLaboratory.class)); @@ -824,6 +824,7 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Norin the Wary", "827b", Rarity.RARE, mage.cards.n.NorinTheWary.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Keen Duelist", 828, Rarity.RARE, mage.cards.k.KeenDuelist.class)); cards.add(new SetCardInfo("Fatestitcher", 835, Rarity.RARE, mage.cards.f.Fatestitcher.class, RETRO_ART)); + cards.add(new SetCardInfo("Undead Alchemist", 836, Rarity.RARE, mage.cards.u.UndeadAlchemist.class, RETRO_ART)); cards.add(new SetCardInfo("Champion of the Perished", 837, Rarity.RARE, mage.cards.c.ChampionOfThePerished.class, RETRO_ART)); cards.add(new SetCardInfo("Corpse Connoisseur", 838, Rarity.RARE, mage.cards.c.CorpseConnoisseur.class, RETRO_ART)); cards.add(new SetCardInfo("Cryptbreaker", 839, Rarity.RARE, mage.cards.c.Cryptbreaker.class, RETRO_ART)); @@ -1957,7 +1958,7 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Dragonlord Ojutai", "1973b", Rarity.MYTHIC, mage.cards.d.DragonlordOjutai.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Dragonlord Silumgar", 1974, Rarity.MYTHIC, mage.cards.d.DragonlordSilumgar.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Dragonlord Silumgar", "1974b", Rarity.MYTHIC, mage.cards.d.DragonlordSilumgar.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Deadly Dispute", 1980, Rarity.RARE, mage.cards.d.DeadlyDispute.class)); + cards.add(new SetCardInfo("Deadly Dispute", 1980, Rarity.RARE, mage.cards.d.DeadlyDispute.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Murderous Rider", 1981, Rarity.RARE, mage.cards.m.MurderousRider.class)); cards.add(new SetCardInfo("Zulaport Cutthroat", 1982, Rarity.RARE, mage.cards.z.ZulaportCutthroat.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Aggravated Assault", 1983, Rarity.RARE, mage.cards.a.AggravatedAssault.class, NON_FULL_USE_VARIOUS)); @@ -2017,13 +2018,38 @@ public class SecretLairDrop extends ExpansionSet { cards.add(new SetCardInfo("Swamp", 2078, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Mountain", 2079, Rarity.LAND, mage.cards.basiclands.Mountain.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Forest", 2080, Rarity.LAND, mage.cards.basiclands.Forest.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Super State", 2081, Rarity.MYTHIC, mage.cards.s.SuperState.class)); + cards.add(new SetCardInfo("Knuckles the Echidna", 2082, Rarity.MYTHIC, mage.cards.k.KnucklesTheEchidna.class)); + cards.add(new SetCardInfo("Amy Rose", 2083, Rarity.MYTHIC, mage.cards.a.AmyRose.class)); + cards.add(new SetCardInfo("Dr. Eggman", 2084, Rarity.MYTHIC, mage.cards.d.DrEggman.class)); + cards.add(new SetCardInfo("Miles \"Tails\" Prower", 2085, Rarity.MYTHIC, mage.cards.m.MilesTailsPrower.class)); + cards.add(new SetCardInfo("Shadow the Hedgehog", 2086, Rarity.MYTHIC, mage.cards.s.ShadowTheHedgehog.class)); + cards.add(new SetCardInfo("Sonic the Hedgehog", 2087, Rarity.MYTHIC, mage.cards.s.SonicTheHedgehog.class)); + cards.add(new SetCardInfo("Generous Gift", 2088, Rarity.RARE, mage.cards.g.GenerousGift.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Open the Armory", 2089, Rarity.RARE, mage.cards.o.OpenTheArmory.class)); + cards.add(new SetCardInfo("Fabricate", 2090, Rarity.RARE, mage.cards.f.Fabricate.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Deadly Dispute", 2091, Rarity.RARE, mage.cards.d.DeadlyDispute.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Unexpected Windfall", 2092, Rarity.RARE, mage.cards.u.UnexpectedWindfall.class)); + cards.add(new SetCardInfo("Sol Ring", 2093, Rarity.RARE, mage.cards.s.SolRing.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("The Reaver Cleaver", 2095, Rarity.RARE, mage.cards.t.TheReaverCleaver.class)); + cards.add(new SetCardInfo("Swiftfoot Boots", 2096, Rarity.RARE, mage.cards.s.SwiftfootBoots.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Myr Battlesphere", 2097, Rarity.RARE, mage.cards.m.MyrBattlesphere.class)); + cards.add(new SetCardInfo("Hammer of Nazahn", 2098, Rarity.RARE, mage.cards.h.HammerOfNazahn.class)); + cards.add(new SetCardInfo("Lightning Greaves", 2099, Rarity.RARE, mage.cards.l.LightningGreaves.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Weatherlight", 2100, Rarity.MYTHIC, mage.cards.w.Weatherlight.class)); cards.add(new SetCardInfo("Feed the Swarm", 7001, Rarity.RARE, mage.cards.f.FeedTheSwarm.class)); cards.add(new SetCardInfo("Forge Anew", 7002, Rarity.RARE, mage.cards.f.ForgeAnew.class)); cards.add(new SetCardInfo("Silence", 7003, Rarity.RARE, mage.cards.s.Silence.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Solitude", 7004, Rarity.MYTHIC, mage.cards.s.Solitude.class)); + cards.add(new SetCardInfo("Subtlety", 7005, Rarity.MYTHIC, mage.cards.s.Subtlety.class)); + cards.add(new SetCardInfo("Grief", 7006, Rarity.MYTHIC, mage.cards.g.Grief.class)); + cards.add(new SetCardInfo("Fury", 7007, Rarity.MYTHIC, mage.cards.f.Fury.class)); + cards.add(new SetCardInfo("Endurance", 7008, Rarity.MYTHIC, mage.cards.e.Endurance.class)); cards.add(new SetCardInfo("Smothering Tithe", 7009, Rarity.RARE, mage.cards.s.SmotheringTithe.class)); cards.add(new SetCardInfo("Counterspell", 7010, Rarity.RARE, mage.cards.c.Counterspell.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Dismember", 7011, Rarity.RARE, mage.cards.d.Dismember.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Command Tower", 7012, Rarity.RARE, mage.cards.c.CommandTower.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Tibalt's Trickery", 7027, Rarity.RARE, mage.cards.t.TibaltsTrickery.class)); cards.add(new SetCardInfo("Minds Aglow", 7028, Rarity.RARE, mage.cards.m.MindsAglow.class)); cards.add(new SetCardInfo("Command Tower", 7029, Rarity.RARE, mage.cards.c.CommandTower.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Jace, the Mind Sculptor", 8001, Rarity.MYTHIC, mage.cards.j.JaceTheMindSculptor.class)); diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/LandTest.java b/Mage.Tests/src/frozen/org/mage/test/clientside/LandTest.java deleted file mode 100644 index 01ac0f9f94d..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/LandTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.mage.test.clientside; - -import org.junit.Test; -import org.mage.test.clientside.base.MageAPI; -import org.mage.test.clientside.bdd.and.And; -import org.mage.test.clientside.bdd.given.Given; -import org.mage.test.clientside.bdd.then.Then; -import org.mage.test.clientside.bdd.when.When; - -import static org.mage.test.clientside.base.MageAPI.Owner.*; - -public class LandTest extends MageAPI { - - @Test - public void testPlayingLandInMainPhase() throws Exception { - Given.I.have.a.card("Mountain"); - And.phase.is("Precombat Main", mine); - When.I.play("Mountain"); - Then.battlefield.has("Mountain"); - And.graveyards.empty(); - } -} diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/LandTestExtended.java b/Mage.Tests/src/frozen/org/mage/test/clientside/LandTestExtended.java deleted file mode 100644 index aeb8693ab56..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/LandTestExtended.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.mage.test.clientside; - -import mage.constants.Zone; -import org.junit.Test; -import org.mage.test.clientside.base.MageAPIExtended; - -import static org.mage.test.clientside.base.MageAPI.Owner.mine; - -public class LandTestExtended extends MageAPIExtended { - - @Test - public void testPlayingLandInMainPhase() throws Exception { - addCard("Mountain", Zone.HAND); - setPhase("Precombat Main", mine); - play("Mountain"); - assertBattlefield("Mountain"); - assertGraveyardsCount(0); - } -} diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/LightningHelixTest.java b/Mage.Tests/src/frozen/org/mage/test/clientside/LightningHelixTest.java deleted file mode 100644 index 01f034a06d0..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/LightningHelixTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.mage.test.clientside; - -import org.junit.Test; -import org.mage.test.clientside.base.MageAPI; - -public class LightningHelixTest extends MageAPI { - - @Test - public void testPlayTargetOpponent() throws Exception { - //Given.I.have.a.card("Lightning Helix"); - //And.battlefield.has("Mountain","Plains"); - //And.phase.is("Precombat Main", mine); - //And.phase.is("End of Turn", ai); - //And.lifes(20,20); - //When.I.play("Lightning Helix"); - //Then.my.life(23); - //And.ai.life(17); - //And.my.graveyard.has("Lightning Helix"); - //And.ai.graveyard.empty(); - //Then.graveyards.empty(); - } -} diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/base/Command.java b/Mage.Tests/src/frozen/org/mage/test/clientside/base/Command.java deleted file mode 100644 index 32728710a90..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/base/Command.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.mage.test.clientside.base; - -/** - * Command pattern. - * - * @author nantuko - */ -abstract public class Command { - abstract public void execute() throws Exception; -} diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/base/MageAPI.java b/Mage.Tests/src/frozen/org/mage/test/clientside/base/MageAPI.java deleted file mode 100644 index adbcd73db6c..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/base/MageAPI.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.mage.test.clientside.base; - -import org.junit.BeforeClass; -import org.mage.test.clientside.bdd.StepController; -import org.mage.test.clientside.bdd.StepState; - -/** - * Parent class for all Mage tests. - * Provides basic actions in mage game and assert functions to check game state. - */ -public class MageAPI { - - public enum Owner { - mine, - me, - ai - } - - @BeforeClass - public static void startServer() throws Exception { - MageBase.getInstance().start(); - } - - /** - * Defined step depending on input parameter. - * If step is UNKNOWN, then use previous remember step, otherwise remember it as current. - * - * Used for replacing "And." by "Given", "When", "Then" - * - * @param step - * @return - */ - public static StepState defineStep(StepState step) { - StepState current = step; - if (!step.equals(StepState.UNKNOWN)) { - StepController.currentState = step; - } else { - current = StepController.currentState; - } - return current; - } -} diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/base/MageAPIExtended.java b/Mage.Tests/src/frozen/org/mage/test/clientside/base/MageAPIExtended.java deleted file mode 100644 index 224777caab7..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/base/MageAPIExtended.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.mage.test.clientside.base; - -import mage.constants.Zone; -import org.mage.test.clientside.bdd.and.And; -import org.mage.test.clientside.bdd.given.Given; -import org.mage.test.clientside.bdd.then.Then; -import org.mage.test.clientside.bdd.when.When; - -import static org.mage.test.clientside.base.MageAPI.Owner.mine; - -/** - * Contains wrappers for bdd calls. - */ -public class MageAPIExtended extends MageAPI { - - public void addCard(String cardName, Zone zone) throws Exception { - Given.I.have.a.card("Mountain"); - } - - public void setPhase(String phase, Owner owner) throws Exception { - And.phase.is("Precombat Main", mine); - } - - public void play(String cardName) throws Exception { - When.I.play("Mountain"); - } - - public void assertBattlefield(String cardName) throws Exception { - Then.battlefield.has("Mountain"); - } - - public void assertGraveyardsCount(int count) throws Exception { - And.graveyards.empty(); - } -} diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/base/MageBase.java b/Mage.Tests/src/frozen/org/mage/test/clientside/base/MageBase.java deleted file mode 100644 index 5bd7fcc6e29..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/base/MageBase.java +++ /dev/null @@ -1,262 +0,0 @@ -package org.mage.test.clientside.base; - -import mage.constants.MultiplayerAttackOption; -import mage.constants.RangeOfInfluence; -import mage.game.match.MatchOptions; -import mage.interfaces.MageException; -import mage.interfaces.Server; -import mage.interfaces.ServerState; -import mage.interfaces.callback.CallbackClient; -import mage.interfaces.callback.CallbackClientDaemon; -import mage.interfaces.callback.ClientCallback; -import mage.server.Main; -import mage.sets.Sets; -import mage.util.Logging; - -import java.rmi.NotBoundException; -import java.rmi.RemoteException; -import java.rmi.registry.LocateRegistry; -import java.rmi.registry.Registry; -import java.util.Date; -import java.util.UUID; - -/** - * Base for starting Mage server. Controls interactions between MageAPI and Mage - * Server. - * - * @author nantuko - */ -public class MageBase { - - /** - * MageBase single instance - */ - private static MageBase instance = new MageBase(); - - /** - * Default logger - */ - private static Logger logger = Logging.getLogger(MageBase.class.getName()); - - public static MageBase getInstance() { - return instance; - } - - private static UUID sessionId; - public static Server server; - private static String userName; - private static ServerState serverState; - private static CallbackClientDaemon callbackDaemon; - private static UUID gameId; - private static UUID playerId; - private static CardView cardPlayed; - - private static GameView gameView; - private static String phaseToWait; - private static Object sync = new Object(); - private static Object syncStart = new Object(); - - public void start() throws Exception { - if (server == null) { - String[] args = new String[]{"-testMode=true"}; - Main.main(args); - connect("player", "localhost", 17171); - UUID roomId = server.getMainRoomId(); - - MatchOptions options = new MatchOptions("1", "Two Player Duel", false); - options.getPlayerTypes().add("Human"); - options.getPlayerTypes().add("Computer - default"); - options.setDeckType("Limited"); - options.setAttackOption(MultiplayerAttackOption.LEFT); - options.setRange(RangeOfInfluence.ALL); - options.setWinsNeeded(1); - TableView table = server.createTable(sessionId, roomId, options); - System.out.println("Cards in the deck: " + Sets.loadDeck("UW Control.dck").getCards().size()); - server.joinTable(sessionId, roomId, table.getTableId(), "Human", "Human", Sets.loadDeck("UW Control.dck")); - server.joinTable(sessionId, roomId, table.getTableId(), "Computer", "Computer - default", Sets.loadDeck("UW Control.dck")); - server.startMatch(sessionId, roomId, table.getTableId()); - - synchronized (syncStart) { - int waitTime = 7000; - Date prev = new Date(); - syncStart.wait(waitTime); - Date intermediate = new Date(); - if (intermediate.getTime() - prev.getTime() > waitTime - 500) { - throw new IllegalStateException("Couldn't start server"); - } - } - } - } - - public static void connect(String userName, String serverName, int port) { - try { - System.setSecurityManager(null); - Registry reg = LocateRegistry.getRegistry(serverName, port); - server = (Server) reg.lookup("mage-server"); - sessionId = server.registerClient(userName, UUID.randomUUID()); - CallbackClient client = new CallbackClient() { - @Override - public void processCallback(ClientCallback callback) { - logger.log(Level.INFO, "IN >> {0} - {1}", new Object[]{callback.getMessageId(), callback.getMethod()}); - try { - if (callback.getMethod().equals("startGame")) { - TableClientMessage data = (TableClientMessage) callback.getData(); - gameId = data.getGameId(); - playerId = data.getPlayerId(); - server.joinGame(gameId, sessionId); - } else if (callback.getMethod().equals("gameInit")) { - server.ack("gameInit", sessionId); - } else if (callback.getMethod().equals("gameAsk")) { - GameClientMessage message = (GameClientMessage) callback.getData(); - logger.log(Level.INFO, "ASK >> {0}", message.getMessage()); - if (message.getMessage().equals("Do you want to take a mulligan?")) { - server.sendPlayerBoolean(gameId, sessionId, false); - } - synchronized (syncStart) { - syncStart.notify(); - } - } else if (callback.getMethod().equals("gameTarget")) { - GameClientMessage message = (GameClientMessage) callback.getData(); - logger.log(Level.INFO, "TARGET >> {0} >> {1}", new Object[]{message.getMessage(), message.getTargets()}); - if (message.getMessage().equals("Select a starting player")) { - logger.log(Level.INFO, " Sending >> {0}", playerId); - server.sendPlayerUUID(gameId, sessionId, playerId); - } - } else if (callback.getMethod().equals("gameSelect")) { - GameClientMessage message = (GameClientMessage) callback.getData(); - logger.log(Level.INFO, "SELECT >> {0}", message.getMessage()); - if (phaseToWait == null) { - synchronized (sync) { - sync.wait(); - } - } - if (!message.getMessage().startsWith(phaseToWait)) { - server.sendPlayerBoolean(gameId, sessionId, false); - } else { - phaseToWait = null; - } - - /*if (!message.getMessage().startsWith("Precombat Main - play spells and sorceries.")) { - server.sendPlayerBoolean(gameId, sessionId, false); - } else { - if (cardPlayed == null) { - CardsView cards = message.getGameView().getHand(); - CardView landToPlay = null; - for (CardView card : cards.values()) { - //System.out.println(card.getName()); - if (card.getName().equals("Plains") || card.getName().equals("Island")) { - landToPlay = card; - } - } - if (landToPlay != null) { - logger.info("Playing " + landToPlay); - server.sendPlayerUUID(gameId, sessionId, landToPlay.getId()); - cardPlayed = landToPlay; - } else { - logger.warning("Couldn't find land to play"); - } - } else { - logger.info("Checking battlefield..."); - boolean foundPlayer = false; - boolean foundLand = false; - for (PlayerView player: message.getGameView().getPlayers()) { - if (player.getPlayerId().equals(playerId)) { - foundPlayer = true; - for (PermanentView permanent : player.getBattlefield().values()) { - if (permanent.getId().equals(cardPlayed.getId())) { - foundLand = true; - } - } - break; - } - } - logger.info(" found player: " + foundPlayer); - logger.info(" found land: " + foundLand); - System.exit(0); - } - - } */ - } - } catch (Exception e) { - logger.info(e.getMessage()); - } - } - }; - callbackDaemon = new CallbackClientDaemon(sessionId, client, server); - serverState = server.getServerState(); - } catch (MageException ex) { - logger.log(Level.SEVERE, null, ex); - } catch (RemoteException ex) { - logger.log(Level.SEVERE, "Unable connect to server - ", ex); - } catch (NotBoundException ex) { - logger.log(Level.SEVERE, "Unable connect to server - ", ex); - } - } - - public boolean giveme(String cardName) throws Exception { - return server.cheat(gameId, sessionId, playerId, cardName); - } - - public boolean checkIhave(String cardName) throws Exception { - if (cardName == null) { - return false; - } - gameView = server.getGameView(gameId, sessionId, playerId); - for (CardView card : gameView.getHand().values()) { - if (CardUtil.haveSameNames(card.getName(), cardName)) { - return true; - } - } - return false; - } - - public void goToPhase(String phase) { - phaseToWait = phase; - synchronized (sync) { - sync.notify(); - } - } - - public void playCard(String cardName) throws Exception { - gameView = server.getGameView(gameId, sessionId, playerId); - CardsView cards = gameView.getHand(); - CardView cardToPlay = null; - for (CardView card : cards.values()) { - if (CardUtil.haveSameNames(card.getName(), cardName)) { - cardToPlay = card; - } - } - if (cardToPlay == null) { - throw new IllegalArgumentException("Couldn't find " + cardName + " in the hand."); - } - if (cardToPlay != null) { - logger.info("Playing " + cardToPlay); - server.sendPlayerUUID(gameId, sessionId, cardToPlay.getId()); - cardPlayed = cardToPlay; - } - } - - public boolean checkBattlefield(String cardName) throws Exception { - gameView = server.getGameView(gameId, sessionId, playerId); - for (PlayerView player : gameView.getPlayers()) { - if (player.getPlayerId().equals(playerId)) { - for (PermanentView permanent : player.getBattlefield().values()) { - if (permanent.getName().equals(cardName)) { - return true; - } - } - } - } - return false; - } - - public boolean checkGraveyardsEmpty() throws Exception { - gameView = server.getGameView(gameId, sessionId, playerId); - for (PlayerView player : gameView.getPlayers()) { - if (player.getGraveyard().size() > 0) { - return false; - } - } - return true; - } -} diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/base/exception/CardNotFoundException.java b/Mage.Tests/src/frozen/org/mage/test/clientside/base/exception/CardNotFoundException.java deleted file mode 100644 index e123b5e1ad6..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/base/exception/CardNotFoundException.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.mage.test.clientside.base.exception; - -/** - * Thrown when server couldn't create card with given name. - * - * @author nantuko - */ -public class CardNotFoundException extends RuntimeException { - public CardNotFoundException(String s) { - super(s); - } -} diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/BDDTests.java b/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/BDDTests.java deleted file mode 100644 index ee3028f8207..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/BDDTests.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.mage.test.clientside.bdd; - -import org.junit.Test; -import org.mage.test.clientside.base.Command; -import org.mage.test.clientside.base.MageAPI; -import org.mage.test.clientside.base.exception.CardNotFoundException; -import org.mage.test.clientside.bdd.and.And; -import org.mage.test.clientside.bdd.given.Given; -import org.mage.test.clientside.bdd.then.Then; -import org.mage.test.clientside.bdd.when.When; - -import static org.mage.test.clientside.base.MageAPI.Owner.mine; - -/** - * Tests BDD classes. - */ -public class BDDTests extends MageAPI { - - @Test - public void testNonExistingCard() throws Exception { - Expect.expect(CardNotFoundException.class, new Command() { - @Override - public void execute() throws Exception { - Given.I.have.a.card("Super Puper Card"); - And.phase.is("Precombat Main", mine); - When.I.play("Super Puper Card"); - Then.battlefield.has("Mountain"); - And.graveyards.empty(); - } - }); - } -} diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/Expect.java b/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/Expect.java deleted file mode 100644 index 97e0ff0c8c9..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/Expect.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.mage.test.clientside.bdd; - -import org.junit.Assert; -import org.mage.test.clientside.base.Command; - -import static junit.framework.TestCase.*; - -/** - * Asserts expecting exception. - * - * @author nantuko - */ -public class Expect { - public static void expect(Class t, Command command) { - try { - command.execute(); - } catch (Throwable e) { - assertEquals(e.getClass().getName(), t.getName()) - return; - } - throw new AssertionError("Expected exception wasn't thrown: " + t.getName()); - } -} diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/StepController.java b/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/StepController.java deleted file mode 100644 index 36330e94a23..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/StepController.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.mage.test.clientside.bdd; - -/** - * Controls steps of bdd calls. - * Uses step for the same "And" calls depending on previous calls. - * So "And." can be either "Given." or "Then." depending on "Given" or "Then" was called previously. - * - * Example: - * - * Given.I.have.a.card("Island"); // remember step here - * And.battlefield.has("Plains"); // "And" replaced and Given.battlefield.has("Plains"); is called - * - * Then.graveyards.empty(); // remember step here - * And.battlefield.has("Plains"); // "And" replaced and Then.battlefield.has("Plains"); is called - * - */ -public class StepController { - public static StepState currentState = StepState.UNKNOWN; -} diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/StepState.java b/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/StepState.java deleted file mode 100644 index 327c4fd99cd..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/StepState.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.mage.test.clientside.bdd; - -public enum StepState { - GIVEN, - WHEN, - THEN, - UNKNOWN -} \ No newline at end of file diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/and/And.java b/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/and/And.java deleted file mode 100644 index 013d70444de..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/and/And.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.mage.test.clientside.bdd.and; - -import org.mage.test.clientside.bdd.StepState; -import org.mage.test.clientside.bdd.given.I; - -public class And { - public static Phase phase = new Phase(StepState.UNKNOWN); - public static Graveyards graveyards = new Graveyards(StepState.UNKNOWN); - public static I I = new I(StepState.UNKNOWN); -} diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/and/Graveyards.java b/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/and/Graveyards.java deleted file mode 100644 index 43fba7cf46b..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/and/Graveyards.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.mage.test.clientside.bdd.and; - -import org.junit.Assert; -import org.mage.test.clientside.base.MageAPI; -import org.mage.test.clientside.base.MageBase; -import org.mage.test.clientside.bdd.StepState; - -import static junit.framework.TestCase.*; - -public class Graveyards { - private StepState step; - public Graveyards(StepState step) { - this.step = step; - } - public boolean empty() throws Exception { - StepState current = MageAPI.defineStep(this.step); - if (current.equals(StepState.THEN)) { - boolean empty = MageBase.getInstance().checkGraveyardsEmpty(); - assertTrue(empty); - return empty; - } else { - throw new AssertionError("Not implemented for step="+current); - } - } -} diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/and/Phase.java b/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/and/Phase.java deleted file mode 100644 index 1cea712dcc5..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/and/Phase.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.mage.test.clientside.bdd.and; - -import org.mage.test.clientside.base.MageAPI; -import org.mage.test.clientside.base.MageBase; -import org.mage.test.clientside.bdd.StepState; - -import static org.mage.test.clientside.base.MageAPI.Owner.*; - -public class Phase { - private StepState step; - public Phase(StepState step) { - this.step = step; - } - public void is(String phase, MageAPI.Owner owner) throws Exception { - StepState current = MageAPI.defineStep(this.step); - if (current.equals(StepState.GIVEN)) { - if ("Precombat Main".equals(phase) && (owner.equals(mine) || owner.equals(me))) { - MageBase.getInstance().goToPhase("Precombat Main - play spells and sorceries."); - return; - } - System.err.println("waitForPhase not implemented for phase="+phase+", owner="+owner.name()); - throw new RuntimeException("Not implemented."); - } else { - throw new RuntimeException("Not implemented for step = " + current); - } - } -} diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/given/A.java b/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/given/A.java deleted file mode 100644 index a6b9865abe3..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/given/A.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.mage.test.clientside.bdd.given; - -import org.mage.test.clientside.base.MageAPI; -import org.mage.test.clientside.base.MageBase; -import org.mage.test.clientside.base.exception.CardNotFoundException; -import org.mage.test.clientside.bdd.StepState; - -public class A { - private StepState step; - public A(StepState step) { - this.step = step; - } - public void card(String cardName) throws Exception { - StepState current = MageAPI.defineStep(this.step); - if (current.equals(StepState.GIVEN)) { - if (!MageBase.getInstance().giveme(cardName)) { - throw new CardNotFoundException("Couldn't create card: " + cardName); - } - } else if (current.equals(StepState.THEN)) { - if (!MageBase.getInstance().checkIhave(cardName)) { - throw new CardNotFoundException("Couldn't find requested card in hand: " + cardName); - } - } - } -} diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/given/Given.java b/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/given/Given.java deleted file mode 100644 index 17763083c76..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/given/Given.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.mage.test.clientside.bdd.given; - -import org.mage.test.clientside.bdd.StepState; -import org.mage.test.clientside.bdd.and.Phase; - -public class Given { - public static I I = new I(StepState.GIVEN); - public static Phase phase = new Phase(StepState.GIVEN); -} diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/given/Have.java b/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/given/Have.java deleted file mode 100644 index b897e22a44f..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/given/Have.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.mage.test.clientside.bdd.given; - -import org.mage.test.clientside.bdd.StepState; - -public class Have { - public Have(StepState step) { - a = new A(step); - } - public A a; -} \ No newline at end of file diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/given/I.java b/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/given/I.java deleted file mode 100644 index e06c383c64a..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/given/I.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.mage.test.clientside.bdd.given; - -import org.mage.test.clientside.bdd.StepState; - -public class I { - public I(StepState step) { - have = new Have(step); - } - public Have have; -} \ No newline at end of file diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/then/Battlefield.java b/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/then/Battlefield.java deleted file mode 100644 index 4fb0fc6d3d5..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/then/Battlefield.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.mage.test.clientside.bdd.then; - -import org.mage.test.clientside.base.MageAPI; -import org.mage.test.clientside.base.MageBase; -import org.mage.test.clientside.bdd.StepState; - -public class Battlefield { - private StepState step; - public Battlefield(StepState step) { - this.step = step; - } - public boolean has(String cardName) throws Exception { - StepState current = MageAPI.defineStep(this.step); - if (current.equals(StepState.THEN)) { - return MageBase.getInstance().checkBattlefield(cardName); - } else { - throw new AssertionError("Not implemented for step="+current); - } - } -} diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/then/Then.java b/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/then/Then.java deleted file mode 100644 index 978cb7e1c11..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/then/Then.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.mage.test.clientside.bdd.then; - -import org.mage.test.clientside.bdd.StepState; -import org.mage.test.clientside.bdd.and.Graveyards; - -public class Then { - public static Battlefield battlefield = new Battlefield(StepState.THEN); - public static Graveyards graveyards = new Graveyards(StepState.THEN); -} diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/when/I.java b/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/when/I.java deleted file mode 100644 index fa15e96d3f0..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/when/I.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.mage.test.clientside.bdd.when; - -import org.mage.test.clientside.base.MageBase; - -public class I { - public void play(String cardName) throws Exception { - MageBase.getInstance().playCard(cardName); - } -} \ No newline at end of file diff --git a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/when/When.java b/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/when/When.java deleted file mode 100644 index 6133b8c9440..00000000000 --- a/Mage.Tests/src/frozen/org/mage/test/clientside/bdd/when/When.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.mage.test.clientside.bdd.when; - -public class When { - public static I I = new I(); -} diff --git a/Mage.Tests/src/test/java/org/mage/test/AI/basic/PossibleTargetsSelectorAITest.java b/Mage.Tests/src/test/java/org/mage/test/AI/basic/PossibleTargetsSelectorAITest.java new file mode 100644 index 00000000000..2ac5a37f76c --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/AI/basic/PossibleTargetsSelectorAITest.java @@ -0,0 +1,149 @@ +package org.mage.test.AI.basic; + +import mage.MageItem; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.InfoEffect; +import mage.constants.Outcome; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.player.ai.PossibleTargetsSelector; +import mage.players.Player; +import mage.target.Target; +import mage.target.common.TargetDiscard; +import mage.target.common.TargetPermanentOrPlayer; +import org.junit.Assert; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author JayDi85 + */ +public class PossibleTargetsSelectorAITest extends CardTestPlayerBase { + + @Test + public void test_SortByOutcome() { + addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1); // 2/2 + addCard(Zone.BATTLEFIELD, playerA, "Arbor Elf", 1); // 1/1 + addCard(Zone.BATTLEFIELD, playerA, "Spectral Bears", 1); // 3/3 + addCard(Zone.BATTLEFIELD, playerA, "Forest", 1); // land + addCard(Zone.BATTLEFIELD, playerA, "Gideon, Martial Paragon", 1); // planeswalker + // + addCard(Zone.BATTLEFIELD, playerB, "Forest", 1); // land + addCard(Zone.BATTLEFIELD, playerB, "Goblin Brigand", 1); // 2/2 + addCard(Zone.BATTLEFIELD, playerB, "Battering Sliver", 1); // 4/4 + + + runCode("check", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> { + // most valuable (planeswalker -> player -> bigger -> smaller) + + // good effect + PossibleTargetsSelector selector = prepareAnyTargetSelector(Outcome.Benefit); + selector.findNewTargets(null); + assertTargets("good effect must return my most valuable and biggest as priority", selector.getGoodTargets(), Arrays.asList( + "Gideon, Martial Paragon", // pw + "PlayerA", // p + "Spectral Bears", // 3/3 + "Balduvian Bears", // 2/2 + "Arbor Elf", // 1/1 + "Forest" // l + )); + assertTargets("good effect must return opponent's lowest as optional", selector.getBadTargets(), Arrays.asList( + "Forest", // l + "Goblin Brigand", // 2/2 + "Battering Sliver", // 4/4 + "PlayerB" // p + )); + + // bad effect - must be inverted + selector = prepareAnyTargetSelector(Outcome.Detriment); + selector.findNewTargets(null); + assertTargets("bad effect must return opponent's most valuable and biggest as priority", selector.getGoodTargets(), Arrays.asList( + "PlayerB", // p + "Battering Sliver", // 4/4 + "Goblin Brigand", // 1/1 + "Forest" // l + )); + assertTargets("bad effect must return my lowest as optional", selector.getBadTargets(), Arrays.asList( + "Forest", // l + "Arbor Elf", // 1/1 + "Balduvian Bears", // 2/2 + "Spectral Bears", // 3/3 + "PlayerA", // p + "Gideon, Martial Paragon" // pw + )); + }); + + setStopAt(1, PhaseStep.END_TURN); + setStrictChooseMode(true); + execute(); + } + + @Test + public void test_SortByPlayable() { + addCard(Zone.HAND, playerA, "Balduvian Bears", 1); // 2/2, {1}{G} + addCard(Zone.HAND, playerA, "Arbor Elf", 1); // 1/1, {G}, playable + addCard(Zone.HAND, playerA, "Spectral Bears", 1); // 3/3, {1}{G} + addCard(Zone.HAND, playerA, "Forest", 1); // land + addCard(Zone.HAND, playerA, "Gideon, Martial Paragon", 1); // planeswalker, {4}{W} + // + addCard(Zone.BATTLEFIELD, playerA, "Forest", 1); + + runCode("check", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> { + // discard logic (remove the biggest unplayable first, land at the end) + + PossibleTargetsSelector selector = prepareDiscardCardSelector(); + selector.findNewTargets(null); + assertTargets("discard must return biggest unplayable first", selector.getGoodTargets(), Arrays.asList( + "Gideon, Martial Paragon", // pw + "Spectral Bears", // 3/3 + "Balduvian Bears", // 2/2 + "Arbor Elf", // 1/1 - playable + "Forest" // l + )); + }); + + setStopAt(1, PhaseStep.END_TURN); + setStrictChooseMode(true); + execute(); + } + + private PossibleTargetsSelector prepareAnyTargetSelector(Outcome outcome) { + Target target = new TargetPermanentOrPlayer(); + Ability fakeAbility = new SimpleStaticAbility(new InfoEffect("fake")); + return new PossibleTargetsSelector(outcome, target, playerA.getId(), fakeAbility, currentGame); + } + + private PossibleTargetsSelector prepareDiscardCardSelector() { + Target target = new TargetDiscard(playerA.getId()); + Ability fakeAbility = new SimpleStaticAbility(new InfoEffect("fake")); + // discard sorting do not use outcome + return new PossibleTargetsSelector(Outcome.Benefit, target, playerA.getId(), fakeAbility, currentGame); + } + + private void assertTargets(String info, List targets, List needTargets) { + List currentTargets = targets.stream() + .map(item -> { + if (item instanceof Player) { + return ((Player) item).getName(); + } else if (item instanceof MageObject) { + return ((MageObject) item).getName(); + } else { + return "unknown item"; + } + }) + .collect(Collectors.toList()); + String current = String.join("\n", currentTargets); + String need = String.join("\n", needTargets); + if (!current.equals(need)) { + Assert.fail(info + "\n\n" + + "NEED targets:\n" + need + "\n\n" + + "FOUND targets:\n" + current + "\n"); + } + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/AI/basic/TargetPriorityTest.java b/Mage.Tests/src/test/java/org/mage/test/AI/basic/TargetPriorityTest.java index 17dc5e580e3..753d4bbc9fe 100644 --- a/Mage.Tests/src/test/java/org/mage/test/AI/basic/TargetPriorityTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/AI/basic/TargetPriorityTest.java @@ -21,52 +21,81 @@ import org.mage.test.serverside.base.CardTestPlayerBaseAI; public class TargetPriorityTest extends CardTestPlayerBaseAI { // TODO: enable _target_ tests after computerPlayer.chooseTarget will be reworks like chooseTargetAmount + @Test - @Ignore - public void test_target_PriorityKillByBigPT() { + public void test_Target_PriorityDamageToGoodOpponent() { addCard(Zone.HAND, playerA, "Lightning Bolt"); addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); // addCard(Zone.BATTLEFIELD, playerB, "Memnite", 3); // 1/1 addCard(Zone.BATTLEFIELD, playerB, "Balduvian Bears", 3); // 2/2 - addCard(Zone.BATTLEFIELD, playerB, "Ashcoat Bear", 3); // 2/2 with ability - addCard(Zone.BATTLEFIELD, playerB, "Golden Bear", 3); // 4/3 - addCard(Zone.BATTLEFIELD, playerB, "Battering Sliver", 3); // 4/4 with ability + addCard(Zone.BATTLEFIELD, playerA, "Ashcoat Bear", 3); // 2/2 with ability + // AI must make damage to opponent castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt"); + setStrictChooseMode(false); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); + assertLife(playerA, 20); + assertLife(playerB, 20 - 3); + } + + @Test + public void test_Target_PriorityDamageToBadLowestCreature() { + addCard(Zone.HAND, playerA, "Lightning Bolt"); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); + // + // You have shroud. + addCard(Zone.BATTLEFIELD, playerB, "Ivory Mask", 1); + // + addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 3); // 2/2 + addCard(Zone.BATTLEFIELD, playerA, "Memnite", 3); // 1/1 + addCard(Zone.BATTLEFIELD, playerA, "Ashcoat Bear", 3); // 2/2 with ability + + // AI can't target opponent so target own lowest creature + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt"); + + setStrictChooseMode(false); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 20); + assertPermanentCount(playerA, "Memnite", 3 - 1); + } + + @Test + public void test_Target_PriorityDamageToBiggestCreature() { + addCard(Zone.HAND, playerA, "Lightning Bolt"); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); + // + // You have shroud. + addCard(Zone.BATTLEFIELD, playerA, "Ivory Mask", 1); + addCard(Zone.BATTLEFIELD, playerB, "Ivory Mask", 1); + // + addCard(Zone.BATTLEFIELD, playerB, "Memnite", 3); // 1/1 + addCard(Zone.BATTLEFIELD, playerB, "Balduvian Bears", 3); // 2/2 + addCard(Zone.BATTLEFIELD, playerB, "Ashcoat Bear", 3); // 2/2 with ability + addCard(Zone.BATTLEFIELD, playerB, "Golden Bear", 3); // 4/3 + //addCard(Zone.BATTLEFIELD, playerB, "Battering Sliver", 3); // 4/4 with ability TODO: add after AI will simulation simple choices too + + // AI must choose biggest creature to kill from opponent - 4/3 + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt"); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + showBattlefield("as", 1, PhaseStep.PRECOMBAT_MAIN, playerB); + + setStrictChooseMode(false); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 20); assertPermanentCount(playerB, "Memnite", 3); assertPermanentCount(playerB, "Balduvian Bears", 3); assertPermanentCount(playerB, "Ashcoat Bear", 3); assertPermanentCount(playerB, "Golden Bear", 3 - 1); - assertPermanentCount(playerB, "Battering Sliver", 3); - } - - @Test - @Ignore - public void test_target_PriorityByKillByLowPT() { - addCard(Zone.HAND, playerA, "Lightning Bolt"); - addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); - // - addCard(Zone.BATTLEFIELD, playerB, "Memnite", 3); // 1/1 - //addCard(Zone.BATTLEFIELD, playerB, "Balduvian Bears", 3); // 2/2 - //addCard(Zone.BATTLEFIELD, playerB, "Ashcoat Bear", 3); // 2/2 with ability - //addCard(Zone.BATTLEFIELD, playerB, "Golden Bear", 3); // 4/3 - addCard(Zone.BATTLEFIELD, playerB, "Battering Sliver", 3); // 4/4 with ability - - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt"); - - setStopAt(1, PhaseStep.BEGIN_COMBAT); - execute(); - - assertPermanentCount(playerB, "Memnite", 3 - 1); - //assertPermanentCount(playerB, "Balduvian Bears", 3); - //assertPermanentCount(playerB, "Ashcoat Bear", 3); - //assertPermanentCount(playerB, "Golden Bear", 3); - assertPermanentCount(playerB, "Battering Sliver", 3); } @Test @@ -153,7 +182,7 @@ public class TargetPriorityTest extends CardTestPlayerBaseAI { // TARGET AMOUNT @Test - public void test_targetAmount_PriorityKillByBigPT() { + public void test_TargetAmount_PriorityKillByBigPT() { addCard(Zone.HAND, playerA, "Flames of the Firebrand"); // damage 3 addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); // @@ -176,7 +205,7 @@ public class TargetPriorityTest extends CardTestPlayerBaseAI { } @Test - public void test_targetAmount_PriorityByKillByLowPT() { + public void test_TargetAmount_PriorityByKillByLowPT() { addCard(Zone.HAND, playerA, "Flames of the Firebrand"); // damage 3 addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); // @@ -199,7 +228,7 @@ public class TargetPriorityTest extends CardTestPlayerBaseAI { } @Test - public void test_targetAmount_PriorityKillByExtraPoints() { + public void test_TargetAmount_PriorityKillByExtraPoints() { addCard(Zone.HAND, playerA, "Flames of the Firebrand"); // damage 3 addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); // @@ -222,7 +251,7 @@ public class TargetPriorityTest extends CardTestPlayerBaseAI { } @Test - public void test_targetAmount_NormalCase() { + public void test_TargetAmount_NormalCase() { Ability ability = new SimpleActivatedAbility(Zone.ALL, new DamageMultiEffect(), new ManaCostsImpl<>("{R}")); ability.addTarget(new TargetCreaturePermanentAmount(3, 0, 3)); addCustomCardWithAbility("damage 3", playerA, ability); @@ -247,7 +276,7 @@ public class TargetPriorityTest extends CardTestPlayerBaseAI { } @Test - public void test_targetAmount_BadCase() { + public void test_TargetAmount_BadCase() { // choose targets as enters battlefield (e.g. can't be canceled) SpellAbility spell = new SpellAbility(new ManaCostsImpl<>("{R}"), "damage 3", Zone.HAND); Ability ability = new EntersBattlefieldTriggeredAbility(new DamageMultiEffect()); @@ -263,14 +292,12 @@ public class TargetPriorityTest extends CardTestPlayerBaseAI { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "damage 3"); - // must damage x3 Balduvian Bears by -1 to keep alive - checkDamage("pt after", 1, PhaseStep.BEGIN_COMBAT, playerA, "Balduvian Bears", 1); - // showBattlefield("after", 1, PhaseStep.BEGIN_COMBAT, playerA); + // up to target is optional, so AI must choose nothing due only bad targets setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); - assertPermanentCount(playerA, "damage 3", 1); - + assertLife(playerA, 20); + assertLife(playerB, 20); assertPermanentCount(playerA, "Memnite", 3); assertPermanentCount(playerA, "Balduvian Bears", 3); assertPermanentCount(playerA, "Ashcoat Bear", 3); @@ -280,7 +307,7 @@ public class TargetPriorityTest extends CardTestPlayerBaseAI { @Test @Ignore // do not enable it in production, only for devs - public void test_targetAmount_Performance() { + public void test_TargetAmount_Performance() { int cardsMultiplier = 3; Ability ability = new SimpleActivatedAbility(Zone.ALL, new DamageMultiEffect(), new ManaCostsImpl<>("{R}")); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/CyclingTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/CyclingTest.java index cbc4742c9a4..04696cceb3a 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/CyclingTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/CyclingTest.java @@ -61,6 +61,24 @@ public class CyclingTest extends CardTestPlayerBase { assertPowerToughness(playerB, "Pillarfield Ox", 0, 2); } + /** + * Tests that X value is correctly read by the resulting triggered ability + */ + @Test + public void cycleSharkTyphoon() { + addCard(Zone.HAND, playerA, "Shark Typhoon", 1); + addCard(Zone.BATTLEFIELD, playerA, "Island", 8); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cycling"); + setChoice(playerA, "X=6"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + assertGraveyardCount(playerA, "Shark Typhoon", 1); + assertPowerToughness(playerA, "Shark Token", 6, 6); + assertTappedCount("Island", true, 8); + } + /** * Cycle from graveyard or battlefield should not work. */ diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DayNightTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DayNightTest.java index 3ce078d3f4d..3a58e0dad27 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DayNightTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DayNightTest.java @@ -1,8 +1,10 @@ package org.mage.test.cards.abilities.keywords; +import mage.cards.Card; import mage.constants.PhaseStep; import mage.constants.Zone; import mage.game.permanent.Permanent; +import mage.util.CardUtil; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; @@ -59,6 +61,41 @@ public class DayNightTest extends CardTestPlayerBase { assertRuffianSmasher(true); } + @Test + public void testCopy() { + // possible bug: stack overflow on copy + addCard(Zone.HAND, playerA, ruffian); + + runCode("copy", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> { + Card card = currentGame.getCards().stream().filter(c -> c.getName().equals(ruffian)).findFirst().orElse(null); + Assert.assertNotNull(card); + Assert.assertNotNull(card.getSecondCardFace()); + + // original + Assert.assertNotNull(card.getSecondCardFace()); + // copy + Card copy = card.copy(); + Assert.assertNotNull(copy.getSecondCardFace()); + // deep copy + copy = CardUtil.deepCopyObject(card); + Assert.assertNotNull(copy.getSecondCardFace()); + + // copied + Card copied = game.copyCard(card, null, playerA.getId()); + Assert.assertNotNull(copied.getSecondCardFace()); + // copy + copy = copied.copy(); + Assert.assertNotNull(copy.getSecondCardFace()); + // deep copy + copy = CardUtil.deepCopyObject(copied); + Assert.assertNotNull(copy.getSecondCardFace()); + }); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + } + @Test public void testNightbound() { currentGame.setDaytime(false); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/WardTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/WardTest.java index 323d9b4cdd3..d34f5d2863c 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/WardTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/WardTest.java @@ -1,5 +1,6 @@ package org.mage.test.cards.abilities.keywords; +import mage.abilities.keyword.FlyingAbility; import mage.constants.PhaseStep; import mage.constants.Zone; import org.junit.Test; @@ -80,4 +81,115 @@ public class WardTest extends CardTestPlayerBase { assertPermanentCount(playerB, "Roaming Throne", 1); assertDamageReceived(playerB, "Roaming Throne", 0); } + + // Reported bug: #13523 - Ward not properly triggering when re-casting Aura + + private static final String creature = "Owlin Shieldmage"; // 3/3 Flying, Ward - Pay 3 life + private static final String aura = "Kenrith's Transformation"; // 1G enchanted creature loses all abilities and is 3/3 Elk (also draw card on ETB) + private static final String spell = "Beast Within"; // 2G destroy permanent, controller gets 3/3 Beast + private static final String regrowth = "Regrowth"; // 1G return target card from graveyard to hand + + @Test + public void wardRecastAuraNoPay() { + + addCard(Zone.BATTLEFIELD, playerB, creature); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 9); + addCard(Zone.HAND, playerA, aura); + addCard(Zone.HAND, playerA, spell); + addCard(Zone.HAND, playerA, regrowth); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, aura, creature); + setChoice(playerA, false); // don't pay for ward + + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, regrowth, aura); + + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, aura, creature); + setChoice(playerA, false); // don't pay for ward + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertLife(playerA, 20); + assertGraveyardCount(playerA, aura, 1); + assertGraveyardCount(playerA, regrowth, 1); + assertGraveyardCount(playerA, 2); + assertHandCount(playerA, spell, 1); + assertHandCount(playerA, 1); + assertAbility(playerB, creature, FlyingAbility.getInstance(), true); + + } + + @Test + public void wardRecastAuraPaySecond() { + + addCard(Zone.BATTLEFIELD, playerB, creature); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 9); + addCard(Zone.HAND, playerA, aura); + addCard(Zone.HAND, playerA, spell); + addCard(Zone.HAND, playerA, regrowth); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, aura, creature); + setChoice(playerA, false); // don't pay for ward + + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, regrowth, aura); + + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, aura, creature); + setChoice(playerA, true); // pay ward + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertLife(playerA, 17); + assertGraveyardCount(playerA, aura, 0); + assertGraveyardCount(playerA, regrowth, 1); + assertGraveyardCount(playerA, 1); + assertHandCount(playerA, spell, 1); + assertHandCount(playerA, 2); // one draw from aura entering + assertAttachedTo(playerB, aura, creature, true); + assertAbility(playerB, creature, FlyingAbility.getInstance(), false); + + } + + @Test + public void wardRecastAuraPayBoth() { + + addCard(Zone.BATTLEFIELD, playerB, creature); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 9); + addCard(Zone.HAND, playerA, aura); + addCard(Zone.HAND, playerA, spell); + addCard(Zone.HAND, playerA, regrowth); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, aura, creature); + setChoice(playerA, true); // pay for ward + + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, spell, aura); // destroy aura + + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, regrowth, aura); + + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, aura, creature); + setChoice(playerA, true); // pay ward + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertLife(playerA, 14); + assertGraveyardCount(playerA, spell, 1); + assertGraveyardCount(playerA, regrowth, 1); + assertGraveyardCount(playerA, 2); + assertHandCount(playerA, 2); // two draws from aura entering + assertAttachedTo(playerB, aura, creature, true); + assertAbility(playerB, creature, FlyingAbility.getInstance(), false); + + } + } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/exile/SearchNameExileTests.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/exile/SearchNameExileTests.java index 71e83ef6543..3a0019ed703 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/exile/SearchNameExileTests.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/exile/SearchNameExileTests.java @@ -125,9 +125,9 @@ public class SearchNameExileTests extends CardTestPlayerBase { addCard(Zone.HAND, playerA, "Test of Talents", 1); addCard(Zone.BATTLEFIELD, playerA, "Island", 2); - addCard(Zone.GRAVEYARD, playerB, "Ready // Willing", 1); + addCard(Zone.GRAVEYARD, playerB, "Ready // Willing", 2); addCard(Zone.HAND, playerB, "Ready // Willing", 2); - addCard(Zone.LIBRARY, playerB, "Ready // Willing", 1); + addCard(Zone.LIBRARY, playerB, "Ready // Willing", 2); addCard(Zone.BATTLEFIELD, playerB, "Plains", 2); addCard(Zone.BATTLEFIELD, playerB, "Forest", 2); addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2); @@ -137,7 +137,7 @@ public class SearchNameExileTests extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Test of Talents", "Ready // Willing", "Ready // Willing"); // TODO: a non strict cause a good AI choice test - make strict and duplicate as really AI test? - // in non strict mode AI must choose as much as possible in good "up to" target and half in bad target + // in non strict mode AI must choose as much as possible from grave/library due good exile effect/cost setStrictChooseMode(false); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); @@ -149,6 +149,6 @@ public class SearchNameExileTests extends CardTestPlayerBase { assertHandCount(playerB, "Ready // Willing", 0); assertHandCount(playerB, 1); //add 2, cast 1, last is exiled+redrawn - assertExileCount(playerB, "Ready // Willing", 4); + assertExileCount(playerB, "Ready // Willing", 6); } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopyPermanentSpellTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopyPermanentSpellTest.java index edda38ee472..7c5caeba8ef 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopyPermanentSpellTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopyPermanentSpellTest.java @@ -63,20 +63,23 @@ public class CopyPermanentSpellTest extends CardTestPlayerBase { public void testAuraTokenRedirect() { makeTester(); addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); - addCard(Zone.BATTLEFIELD, playerB, "Centaur Courser"); - addCard(Zone.BATTLEFIELD, playerB, "Hill Giant"); + addCard(Zone.BATTLEFIELD, playerB, "Centaur Courser"); // 3/3 + addCard(Zone.BATTLEFIELD, playerB, "Serra Angel"); // 4/4 addCard(Zone.HAND, playerA, "Dead Weight"); - setChoice(playerA, true); + setChoice(playerA, true); // use new target castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dead Weight", "Centaur Courser"); + // it's bad/unboost effect + // allow AI make a choice for new target of copied spell (it will be angel as a opponent's bigger creature for bad effect) + setStrictChooseMode(false); setStopAt(1, PhaseStep.END_TURN); execute(); assertPermanentCount(playerB, "Centaur Courser", 1); - assertPowerToughness(playerB, "Centaur Courser", 1, 1); - assertPermanentCount(playerB, "Hill Giant", 1); - assertPowerToughness(playerB, "Hill Giant", 1, 1); + assertPowerToughness(playerB, "Centaur Courser", 3 - 2, 3 - 2); + assertPermanentCount(playerB, "Serra Angel", 1); + assertPowerToughness(playerB, "Serra Angel", 4 - 2, 4 - 2); assertPermanentCount(playerA, "Dead Weight", 2); } @@ -152,23 +155,26 @@ public class CopyPermanentSpellTest extends CardTestPlayerBase { public void testBestowRedirect() { makeTester(); addCard(Zone.BATTLEFIELD, playerA, "Island", 5); - addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears"); - addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); + addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears"); // 2/2 + addCard(Zone.BATTLEFIELD, playerA, "Arbor Elf"); // 1/1 addCard(Zone.HAND, playerA, "Nimbus Naiad"); - setChoice(playerA, true); + setChoice(playerA, true); // change target castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Nimbus Naiad using bestow", "Grizzly Bears"); + // it's good/boost effect + // allow AI make a choice for new target of copied spell (it will be bear as a bigger creature for good effect) + setStrictChooseMode(false); setStopAt(1, PhaseStep.END_TURN); execute(); assertPermanentCount(playerA, "Grizzly Bears", 1); - assertPowerToughness(playerA, "Grizzly Bears", 4, 4); + assertPowerToughness(playerA, "Grizzly Bears", 2 + 2 + 2, 2 + 2 + 2); assertAbility(playerA, "Grizzly Bears", FlyingAbility.getInstance(), true); - assertPermanentCount(playerA, "Silvercoat Lion", 1); - assertPowerToughness(playerA, "Silvercoat Lion", 4, 4); - assertAbility(playerA, "Silvercoat Lion", FlyingAbility.getInstance(), true); + assertPermanentCount(playerA, "Arbor Elf", 1); + assertPowerToughness(playerA, "Arbor Elf", 1, 1); + assertAbility(playerA, "Arbor Elf", FlyingAbility.getInstance(), false); assertPermanentCount(playerA, "Nimbus Naiad", 2); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/planeswalker/JaceTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/planeswalker/JaceTest.java index 811f814d21c..2007c6082d4 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/planeswalker/JaceTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/planeswalker/JaceTest.java @@ -67,7 +67,7 @@ public class JaceTest extends CardTestPlayerBase { setStopAt(3, PhaseStep.BEGIN_COMBAT); execute(); - assertGraveyardCount(playerA, "Pillarfield Ox", 1); + assertGraveyardCount(playerA, "Pillarfield Ox", 1); // must discard a creature and keep land card assertExileCount("Jace, Vryn's Prodigy", 0); assertPermanentCount(playerA, "Jace, Telepath Unbound", 1); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/planeswalker/VivienTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/planeswalker/VivienTest.java index 3b6f1720316..4650755a7dc 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/planeswalker/VivienTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/planeswalker/VivienTest.java @@ -14,19 +14,22 @@ import org.mage.test.serverside.base.CardTestPlayerBase; public class VivienTest extends CardTestPlayerBase { @Test - public void testVivienArkbowRangerAbility1NoTargets() { - setStrictChooseMode(true); + public void test_Distribute_NoTargets() { // +1: Distribute two +1/+1 counters among up to two target creatures. They gain trample until end of turn. // −3: Target creature you control deals damage equal to its power to target creature or planeswalker. // −5: You may choose a creature card you own from outside the game, reveal it, and put it into your hand. addCard(Zone.HAND, playerA, "Vivien, Arkbow Ranger"); // Planeswalker {1}{G}{G}{G} - starts with 4 Loyality counters addCard(Zone.BATTLEFIELD, playerA, "Forest", 4); + // You can activate Vivien’s first ability without choosing any target creatures. The counters won’t be + // put on anything. This is a change from previous rules regarding distributing counters. + // (2019-07-12) + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Vivien, Arkbow Ranger", true); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+1: Distribute"); addTargetAmount(playerA, TestPlayer.TARGET_SKIP); // stop choosing (not targets) - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+1: Distribute"); - + setStrictChooseMode(true); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); @@ -36,8 +39,7 @@ public class VivienTest extends CardTestPlayerBase { } @Test - public void testVivienArkbowRangerAbilityOnePossibleTargetWithOne() { - setStrictChooseMode(true); + public void test_Distribute_OneTarget() { // +1: Distribute two +1/+1 counters among up to two target creatures. They gain trample until end of turn. // −3: Target creature you control deals damage equal to its power to target creature or planeswalker. // −5: You may choose a creature card you own from outside the game, reveal it, and put it into your hand. @@ -49,16 +51,16 @@ public class VivienTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Vivien, Arkbow Ranger", true); activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+1: Distribute"); - addTargetAmount(playerA, "Silvercoat Lion", 1); - addTargetAmount(playerA, TestPlayer.TARGET_SKIP); // stop choosing (one target) + addTargetAmount(playerA, "Silvercoat Lion", 2); + setStrictChooseMode(true); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); assertPermanentCount(playerA, "Vivien, Arkbow Ranger", 1); assertCounterCount("Vivien, Arkbow Ranger", CounterType.LOYALTY, 5); - assertPowerToughness(playerB, "Silvercoat Lion", 2 + 1, 2 + 1); + assertPowerToughness(playerB, "Silvercoat Lion", 2 + 2, 2 + 2); } @Test diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/blb/AlaniaDivergentStormTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/blb/AlaniaDivergentStormTest.java index eb1bb871feb..094831ef36e 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/blb/AlaniaDivergentStormTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/blb/AlaniaDivergentStormTest.java @@ -33,8 +33,8 @@ public class AlaniaDivergentStormTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, alania, true); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Coruscation Mage", true); setChoice(playerA, "No"); // Offspring? + addTarget(playerA, playerB); // Who draws? setChoice(playerA, "Yes"); // Copy spell? - setChoice(playerA, "PlayerB"); // Who draws? setStrictChooseMode(true); setStopAt(1, PhaseStep.BEGIN_COMBAT); @@ -61,8 +61,8 @@ public class AlaniaDivergentStormTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, alania, true); castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Stormcatch Mentor", true); + addTarget(playerA, playerB); // Who draws? setChoice(playerA, "Yes"); // Copy spell? - setChoice(playerA, "PlayerB"); // Who draws? castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Coruscation Mage", true); setChoice(playerA, "No"); // Offspring? @@ -93,16 +93,16 @@ public class AlaniaDivergentStormTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, alania, true); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Frolicking Familiar", true); + addTarget(playerA, playerB); // Who draws? setChoice(playerA, "Yes"); // Copy spell? - setChoice(playerA, "PlayerB"); // Who draws? castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Coruscation Mage", true); setChoice(playerA, "No"); // Offspring? castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Blow Off Steam", true); setChoice(playerA, "Whenever you cast an instant", 2); // Add Frolicking Familiar triggers first setChoice(playerA, "Whenever you cast a noncreature"); // Add Coruscation Mage trigger // Alania's trigger will add last + addTarget(playerA, playerB); // Who draws? setChoice(playerA, "Yes"); // Copy spell? - setChoice(playerA, "PlayerB"); // Who draws? addTarget(playerA, playerB); setChoice(playerA, "No"); // Change target? @@ -137,8 +137,8 @@ public class AlaniaDivergentStormTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, alania, true); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Acrobatic Leap", true); + addTarget(playerA, playerB); // Who draws? setChoice(playerA, "Yes"); // Copy spell? - setChoice(playerA, "PlayerB"); // Who draws? addTarget(playerA, alania); // Target creature setChoice(playerA, "No"); // Change target? castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Ancestral Recall", true); @@ -170,8 +170,8 @@ public class AlaniaDivergentStormTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, alania, true); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Gift of the Fae", true); + addTarget(playerA, playerB); // Who draws? setChoice(playerA, "Yes"); // Copy spell? - setChoice(playerA, "PlayerB"); // Who draws? addTarget(playerA, alania); // Target creature setChoice(playerA, "No"); // Change target? castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Maximize Velocity", true); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/dmc/TillerEngineTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/dmc/TillerEngineTest.java index c58c16977b6..e76708cdfa7 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/dmc/TillerEngineTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/dmc/TillerEngineTest.java @@ -25,7 +25,7 @@ public class TillerEngineTest extends CardTestPlayerBase { addCard(Zone.HAND, playerA, land); playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, land); - setChoice(playerA, "Whenever a land enters"); // order triggers + setChoice(playerA, "Whenever a land you control enters"); // order triggers setModeChoice(playerA, "1"); setStrictChooseMode(true); @@ -45,7 +45,7 @@ public class TillerEngineTest extends CardTestPlayerBase { addCard(Zone.HAND, playerA, land); playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, land); - setChoice(playerA, "Whenever a land enters"); // order triggers + setChoice(playerA, "Whenever a land you control enters"); // order triggers setModeChoice(playerA, "2"); addTarget(playerA, centaur); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/dsc/SoaringLightbringerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/dsc/SoaringLightbringerTest.java new file mode 100644 index 00000000000..e7639577d15 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/dsc/SoaringLightbringerTest.java @@ -0,0 +1,86 @@ +package org.mage.test.cards.single.dsc; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.counters.CounterType; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestCommander4Players; + +/** + * @author notgreat + */ +public class SoaringLightbringerTest extends CardTestCommander4Players { + + @Test + public void test_AttacksDoubled() { + addCard(Zone.BATTLEFIELD, playerA, "Soaring Lightbringer"); + addCard(Zone.BATTLEFIELD, playerA, "Memnite"); + + attack(1, playerA, "Soaring Lightbringer", playerB); + attack(1, playerA, "Memnite", playerB); + + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + + assertTappedCount("Glimmer Token", true, 1); + assertLife(playerB, 20 - 4 - 1 - 1); + } + + @Test + public void test_AttacksTwo() { + addCard(Zone.BATTLEFIELD, playerA, "Soaring Lightbringer"); + addCard(Zone.BATTLEFIELD, playerA, "Memnite"); + + attack(1, playerA, "Soaring Lightbringer", playerB); + attack(1, playerA, "Memnite", playerD); + + setChoice(playerA, "Whenever"); // Order triggers + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + + assertTappedCount("Glimmer Token", true, 2); + assertLife(playerB, 20 - 4 - 1); + assertLife(playerD, 20 - 1 - 1); + } + + @Test + public void test_AttacksPlaneswalker() { + addCard(Zone.BATTLEFIELD, playerD, "Soaring Lightbringer"); + addCard(Zone.BATTLEFIELD, playerD, "Memnite"); + addCard(Zone.HAND, playerA, "Nissa Revane"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 4); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Nissa Revane"); + attack(2, playerD, "Memnite", "Nissa Revane"); + + setStrictChooseMode(true); + setStopAt(2, PhaseStep.END_COMBAT); + execute(); + + assertPermanentCount(playerD, "Glimmer Token", 0); + assertCounterCount("Nissa Revane", CounterType.LOYALTY, 1); + } + + @Test + public void test_AttacksEnters() { + addCard(Zone.BATTLEFIELD, playerA, "Soaring Lightbringer"); + addCard(Zone.BATTLEFIELD, playerA, "Falconer Adept"); + + attack(1, playerA, "Falconer Adept", playerB); + setChoice(playerA, "Whenever"); // Order triggers + addTarget(playerA, playerC); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + + assertTappedCount("Glimmer Token", true, 1); + assertTappedCount("Bird Token", true, 1); + assertLife(playerB, 20 - 2 - 1); + assertLife(playerC, 20 - 1); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/grn/BeamsplitterMageTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/grn/BeamsplitterMageTest.java index 80cfef86fb3..32ad4d316e8 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/grn/BeamsplitterMageTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/grn/BeamsplitterMageTest.java @@ -9,11 +9,25 @@ import org.mage.test.serverside.base.CardTestPlayerBase; * @author TheElk801 */ public class BeamsplitterMageTest extends CardTestPlayerBase { + /** + * 2/2 + *

+ * Whenever you cast an instant or sorcery spell that targets only Beamsplitter Mage, + * if you control one or more creatures that spell could target, choose one of those + * creatures. Copy that spell. The copy targets the chosen creature. + */ private static final String bsm = "Beamsplitter Mage"; + + /** + * Target creature gets +1/+1 until end of turn. + * Target creature gets +1/+1 until end of turn. + * Target creature gets +1/+1 until end of turn. + */ + private static final String seeds = "Seeds of Strength"; + private static final String lion = "Silvercoat Lion"; private static final String duelist = "Deft Duelist"; private static final String bolt = "Lightning Bolt"; - private static final String seeds = "Seeds of Strength"; @Test public void testLightningBolt() { @@ -24,7 +38,9 @@ public class BeamsplitterMageTest extends CardTestPlayerBase { addCard(Zone.HAND, playerA, bolt); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bolt, bsm); + setChoice(playerA, lion); // target for copied bolt + setStrictChooseMode(true); setStopAt(1, PhaseStep.END_TURN); execute(); @@ -45,12 +61,18 @@ public class BeamsplitterMageTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerA, bsm); addCard(Zone.HAND, playerA, seeds); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, seeds, bsm); + // put x3 targets to bsm and copy it to lion + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, seeds); + addTarget(playerA, bsm); + addTarget(playerA, bsm); + addTarget(playerA, bsm); + setChoice(playerA, lion); + setStrictChooseMode(true); setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); execute(); - assertPowerToughness(playerA, bsm, 5, 5); - assertPowerToughness(playerA, lion, 5, 5); + assertPowerToughness(playerA, bsm, 2 + 3, 2 + 3); + assertPowerToughness(playerA, lion, 2 + 3, 2 + 3); } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/isd/HomicidalBruteTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/isd/HomicidalBruteTest.java index 165999433bb..0bfb2decd72 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/isd/HomicidalBruteTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/isd/HomicidalBruteTest.java @@ -84,4 +84,34 @@ public class HomicidalBruteTest extends CardTestPlayerBase { assertTapped("Homicidal Brute", true); } + @Test + public void testCardBlinkNotTransform() { + addCard(Zone.BATTLEFIELD, playerA, "Civilized Scholar"); + addCard(Zone.HAND, playerA, "Sejiri Merfolk"); + addCard(Zone.HAND, playerA, "Moonmist"); // transform all + addCard(Zone.HAND, playerA, "Cloudshift"); // blink + addCard(Zone.BATTLEFIELD, playerA, "Savannah", 3); + + activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Draw a card, then discard a card."); + setChoice(playerA, "Sejiri Merfolk"); // discard creature + + attack(3, playerA, "Homicidal Brute", playerB); + castSpell(3, PhaseStep.COMBAT_DAMAGE, playerA, "Cloudshift", "Homicidal Brute"); + castSpell(3, PhaseStep.END_COMBAT, playerA, "Moonmist"); + + checkPermanentTapped("after transform", 3, PhaseStep.POSTCOMBAT_MAIN, playerA, "Homicidal Brute", false, 1); + + setStrictChooseMode(true); + setStopAt(4, PhaseStep.UPKEEP); + execute(); + + assertGraveyardCount(playerA, "Cloudshift", 1); + assertGraveyardCount(playerA, "Moonmist", 1); + assertLife(playerA, 20); + assertLife(playerB, 15); + assertPermanentCount(playerA, "Civilized Scholar", 1); + assertPermanentCount(playerA, "Homicidal Brute", 0); + assertTapped("Civilized Scholar", true); + } + } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/lci/BarracksOfTheThousandTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/lci/BarracksOfTheThousandTest.java index e8f4545b1e4..c9838655cbe 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/lci/BarracksOfTheThousandTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/lci/BarracksOfTheThousandTest.java @@ -56,23 +56,29 @@ public class BarracksOfTheThousandTest extends CardTestPlayerBase { } @Test - public void trigger_onlyonce_doublemana() { + public void trigger_onceTwice_doublemana() { setStrictChooseMode(true); - addCard(Zone.BATTLEFIELD, playerB, "Heartbeat of Spring"); + addCard(Zone.BATTLEFIELD, playerA, "Mana Reflection"); addCard(Zone.HAND, playerA, "Armored Warhorse"); + addCard(Zone.HAND, playerA, "Savannah Lions", 2); initToTransform(); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Armored Warhorse"); + checkPermanentCount("One Gnome Soldier Token", 1, PhaseStep.BEGIN_COMBAT, playerA, "Gnome Soldier Token", 1); - setStopAt(1, PhaseStep.BEGIN_COMBAT); + castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Savannah Lions"); + waitStackResolved(3, PhaseStep.PRECOMBAT_MAIN); + castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Savannah Lions"); + + setStopAt(3, PhaseStep.BEGIN_COMBAT); execute(); - assertPermanentCount(playerA, "Gnome Soldier Token", 1); + assertPermanentCount(playerA, "Gnome Soldier Token", 3); assertPermanentCount(playerA, "Armored Warhorse", 1); + assertPermanentCount(playerA, "Savannah Lions", 2); } - @Test public void noTrigger_NotPaidWithBarrack() { setStrictChooseMode(true); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/lci/TheMyriadPoolsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/lci/TheMyriadPoolsTest.java new file mode 100644 index 00000000000..573ee3a2d44 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/lci/TheMyriadPoolsTest.java @@ -0,0 +1,27 @@ +package org.mage.test.cards.single.lci; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +public class TheMyriadPoolsTest extends CardTestPlayerBase { + + @Test + public void castCopiesCorrectly() { + addCard(Zone.BATTLEFIELD, playerA, "The Myriad Pools"); + addCard(Zone.BATTLEFIELD, playerA, "Memnite"); + addCard(Zone.HAND, playerA, "Flying Men"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Flying Men"); + addTarget(playerA, "Memnite"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + setStrictChooseMode(true); + execute(); + + assertPermanentCount(playerA, "The Myriad Pools", 1); + assertPermanentCount(playerA, "Memnite", 0); + assertPermanentCount(playerA, "Flying Men", 2); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/otc/BladegriffPrototypeTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/otc/BladegriffPrototypeTest.java new file mode 100644 index 00000000000..df140741b84 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/otc/BladegriffPrototypeTest.java @@ -0,0 +1,41 @@ +package org.mage.test.cards.single.otc; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +public class BladegriffPrototypeTest extends CardTestPlayerBase { + private static final String griff = "Bladegriff Prototype"; + + @Test + public void test_CanTargetOwn() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerB, "Squire"); + addCard(Zone.BATTLEFIELD, playerA, griff); + + attack(1, playerA, griff); + addTarget(playerB, "Squire"); + + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + + assertGraveyardCount(playerB, "Squire", 1); + } + + @Test(expected=AssertionError.class) + public void test_CantTargetYours() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerB, "Squire"); + addCard(Zone.BATTLEFIELD, playerA, griff); + + attack(1, playerA, griff); + addTarget(playerB, griff); + + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/unf/CometStellarPupTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/unf/CometStellarPupTest.java index 5cca732151f..faa662bf787 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/unf/CometStellarPupTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/unf/CometStellarPupTest.java @@ -27,11 +27,7 @@ public class CometStellarPupTest extends CardTestPlayerBase { */ private final static String comet = "Comet, Stellar Pup"; - private final static String cometAbility = "0: Roll a six-sided die." - + "
1 or 2 — [+2], then create two 1/1 green Squirrel creature tokens. They gain haste until end of turn." - + "
3 — [-1], then return a card with mana value 2 or less from your graveyard to your hand." - + "
4 or 5 — {this} deals damage equal to the number of loyalty counters on him to a creature or player, then [-2]." - + "
6 — [+1], and you may activate Comet, Stellar Pup's loyalty ability two more times this turn."; + private final static String cometAbility = "0: Roll a six-sided die."; @Test public void testRoll1() { diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/znr/YasharnImplacableEarthTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/znr/YasharnImplacableEarthTest.java index 5e3c2131f92..2daabf2511d 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/znr/YasharnImplacableEarthTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/znr/YasharnImplacableEarthTest.java @@ -1,23 +1,22 @@ package org.mage.test.cards.single.znr; -import mage.cards.decks.Deck; import mage.constants.PhaseStep; import mage.constants.Zone; -import org.assertj.core.api.Assertions; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; /** - * {@link mage.cards.y.YasharnImplacableEarth Yasharn, Implacable Earth} - * When Yasharn enters the battlefield, search your library for a basic Forest card and a basic Plains card, reveal those cards, put them into your hand, then shuffle. - * Players can’t pay life or sacrifice nonland permanents to cast spells or activate abilities. - * * @author Alex-Vasile */ public class YasharnImplacableEarthTest extends CardTestPlayerBase { + /** + * {@link mage.cards.y.YasharnImplacableEarth Yasharn, Implacable Earth} + * When Yasharn enters the battlefield, search your library for a basic Forest card and a basic Plains card, reveal those cards, put them into your hand, then shuffle. + * Players can’t pay life or sacrifice nonland permanents to cast spells or activate abilities. + */ private static final String yasharn = "Yasharn, Implacable Earth"; /** @@ -143,6 +142,8 @@ public class YasharnImplacableEarthTest extends CardTestPlayerBase { */ @Test public void canSacrificeLandToActivate() { + removeAllCardsFromLibrary(playerA); + addCard(Zone.BATTLEFIELD, playerA, yasharn); addCard(Zone.BATTLEFIELD, playerA, "Evolving Wilds"); addCard(Zone.LIBRARY, playerA, "Island"); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/EnterLeaveBattlefieldExileTargetTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/EnterLeaveBattlefieldExileTargetTest.java index f334f88dba2..2217cb4ee82 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/EnterLeaveBattlefieldExileTargetTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/EnterLeaveBattlefieldExileTargetTest.java @@ -77,7 +77,8 @@ public class EnterLeaveBattlefieldExileTargetTest extends CardTestPlayerBase { // test NPE error while AI targeting battlefield with tokens // Flying - // When Angel of Serenity enters the battlefield, you may exile up to three other target creatures from the battlefield and/or creature cards from graveyards. + // When Angel of Serenity enters the battlefield, you may exile up to three other target creatures + // from the battlefield and/or creature cards from graveyards. addCard(Zone.HAND, playerA, "Angel of Serenity"); addCard(Zone.BATTLEFIELD, playerA, "Plains", 7); // @@ -98,6 +99,7 @@ public class EnterLeaveBattlefieldExileTargetTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Angel of Serenity"); setChoice(playerA, true); //addTarget(playerA, "Silvercoat Lion^Balduvian Bears"); // AI must target + //addTarget(playerA, TestPlayer.TARGET_SKIP); setStrictChooseMode(false); // AI must target setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/ReturnToBattlefieldEffectsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/ReturnToBattlefieldEffectsTest.java index ba897e5a889..f0b2d87c89f 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/ReturnToBattlefieldEffectsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/ReturnToBattlefieldEffectsTest.java @@ -157,4 +157,62 @@ public class ReturnToBattlefieldEffectsTest extends CardTestPlayerBase { assertPermanentCount(playerB, "Reassembling Skeleton", 1); } + + // issue #12974 + private static final String rOrb = "Resurrection Orb"; + // Whenever equipped creature dies, return that card to the battlefield under its owner's control at the beginning of the next end step. + private static final String lMiss = "Lone Missionary"; // ETB gain 4 + private static final String cFeeder = "Carrion Feeder"; // sacrifice a creature: +1/+1 counter + + @Test + public void testReturnAttachedToBattlefield() { + addCard(Zone.BATTLEFIELD, playerA, rOrb); + addCard(Zone.BATTLEFIELD, playerA, lMiss); + addCard(Zone.BATTLEFIELD, playerA, cFeeder); + addCard(Zone.BATTLEFIELD, playerA, "Wastes", 4); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip", lMiss); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice"); + setChoice(playerA, lMiss); + + setStrictChooseMode(true); + setStopAt(2, PhaseStep.UPKEEP); + execute(); + + assertLife(playerA, 24); + assertPermanentCount(playerA, lMiss, 1); + assertPowerToughness(playerA, cFeeder, 2, 2); + + } + + @Test + public void testNotReturnAttachedToBattlefieldAfterZoneChange() { + addCard(Zone.BATTLEFIELD, playerA, rOrb); + addCard(Zone.BATTLEFIELD, playerA, lMiss); + addCard(Zone.BATTLEFIELD, playerA, cFeeder); + addCard(Zone.BATTLEFIELD, playerA, "Wastes", 4); + addCard(Zone.BATTLEFIELD, playerB, "Crypt Creeper"); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip", lMiss); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice"); + setChoice(playerA, lMiss); + + activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Sacrifice"); + addTarget(playerB, lMiss); + + setStrictChooseMode(true); + setStopAt(2, PhaseStep.UPKEEP); + execute(); + + assertLife(playerA, 20); + assertExileCount(playerA, lMiss, 1); + assertPowerToughness(playerA, cFeeder, 2, 2); + assertGraveyardCount(playerB, "Crypt Creeper", 1); + + } + } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/watchers/AureliasFuryTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/watchers/AureliasFuryTest.java new file mode 100644 index 00000000000..ad26ba67646 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/watchers/AureliasFuryTest.java @@ -0,0 +1,71 @@ +package org.mage.test.cards.watchers; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author xenohedron + */ +public class AureliasFuryTest extends CardTestPlayerBase { + + // see issue #13774 + + private static final String fury = "Aurelia's Fury"; // XRW + // Aurelia’s Fury deals X damage divided as you choose among any number of targets. + // Tap each creature dealt damage this way. Players dealt damage this way can’t cast noncreature spells this turn. + + private static final String elementalist = "Ardent Elementalist"; // 3R 2/1 + // When this creature enters, return target instant or sorcery card from your graveyard to your hand. + private static final String hatchling = "Kraken Hatchling"; // 0/4 + private static final String glimmerbell = "Glimmerbell"; // 1/3 flying; 1U: untap ~ + private static final String crab = "Fortress Crab"; // 1/6 + + + @Test + public void testAureliasFury() { + addCard(Zone.BATTLEFIELD, playerA, "Plateau", 5 + 4 + 4); + addCard(Zone.BATTLEFIELD, playerA, hatchling); + addCard(Zone.BATTLEFIELD, playerB, glimmerbell); + addCard(Zone.BATTLEFIELD, playerB, crab); + addCard(Zone.HAND, playerA, fury); + addCard(Zone.HAND, playerA, elementalist); + addCard(Zone.BATTLEFIELD, playerB, "Island", 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, fury); + setChoice(playerA, "X=3"); + addTargetAmount(playerA, hatchling, 2); + addTargetAmount(playerA, glimmerbell, 1); + + checkDamage("first cast", 1, PhaseStep.BEGIN_COMBAT, playerA, hatchling, 2); + checkDamage("first cast", 1, PhaseStep.BEGIN_COMBAT, playerB, glimmerbell, 1); + checkPermanentTapped("first cast", 1, PhaseStep.BEGIN_COMBAT, playerA, hatchling, true, 1); + checkPermanentTapped("first cast", 1, PhaseStep.BEGIN_COMBAT, playerB, glimmerbell, true, 1); + checkPermanentTapped("first cast", 1, PhaseStep.BEGIN_COMBAT, playerB, crab, false, 1); + + activateAbility(1, PhaseStep.END_COMBAT, playerB, "{1}{U}: Untap"); // untap glimmerbell + + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, elementalist); + addTarget(playerA, fury); // return to hand + waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN); + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, fury); + setChoice(playerA, "X=2"); + addTargetAmount(playerA, crab, 1); + addTargetAmount(playerA, playerB, 1); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertDamageReceived(playerA, hatchling, 2); + assertDamageReceived(playerB, glimmerbell, 1); + assertDamageReceived(playerB, crab, 1); + assertLife(playerA, 20); + assertLife(playerB, 19); + assertTapped(hatchling, true); + assertTapped(glimmerbell, false); + assertTapped(crab, true); + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/watchers/CathedralMembraneTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/watchers/CathedralMembraneTest.java new file mode 100644 index 00000000000..c1b47a2556d --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/watchers/CathedralMembraneTest.java @@ -0,0 +1,109 @@ +package org.mage.test.cards.watchers; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author xenohedron + */ +public class CathedralMembraneTest extends CardTestPlayerBase { + + // see issue #13774 + + private static final String cathedralMembrane = "Cathedral Membrane"; // 0/6 + // Defender + // When this creature dies during combat, it deals 6 damage to each creature it blocked this combat. + + private static final String wurm = "Autochthon Wurm"; // 9/14 convoke trample + private static final String gigantosaurus = "Gigantosaurus"; // 10/10 + + private static final String moraug = "Moraug, Fury of Akoum"; // 6/6 + // Each creature you control gets +1/+0 for each time it has attacked this turn. + // Landfall — Whenever a land you control enters, if it's your main phase, + // there's an additional combat phase after this phase. At the beginning of that combat, untap all creatures you control. + + private static final String recovery = "Miraculous Recovery"; // 4W instant + // Return target creature card from your graveyard to the battlefield. Put a +1/+1 counter on it. + + @Test + public void testMembraneTrigger() { + addCard(Zone.HAND, playerA, "Mountain"); + addCard(Zone.BATTLEFIELD, playerA, wurm); + addCard(Zone.BATTLEFIELD, playerA, gigantosaurus); + addCard(Zone.BATTLEFIELD, playerA, moraug); + addCard(Zone.HAND, playerB, cathedralMembrane); + addCard(Zone.HAND, playerB, recovery); + addCard(Zone.BATTLEFIELD, playerB, "Plains", 6); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, cathedralMembrane); + setChoice(playerB, true); // pay life + + attack(3, playerA, wurm, playerB); + + block(3, playerB, cathedralMembrane, wurm); + setChoiceAmount(playerA, 6); // assign trample damage + + setStrictChooseMode(true); + setStopAt(3, PhaseStep.END_TURN); + execute(); + + assertTapped(wurm, true); + assertTapped(gigantosaurus, false); + assertTapped(moraug, false); + assertGraveyardCount(playerB, cathedralMembrane, 1); + assertLife(playerA, 20); + assertLife(playerB, 20 - 2 - 4); + assertDamageReceived(playerA, wurm, 6); + assertDamageReceived(playerA, gigantosaurus, 0); + assertDamageReceived(playerA, moraug, 0); + + } + + @Test + public void testMembraneTriggerAgain() { + addCard(Zone.HAND, playerA, "Mountain"); + addCard(Zone.BATTLEFIELD, playerA, wurm); + addCard(Zone.BATTLEFIELD, playerA, gigantosaurus); + addCard(Zone.BATTLEFIELD, playerA, moraug); + addCard(Zone.HAND, playerB, cathedralMembrane); + addCard(Zone.HAND, playerB, recovery); + addCard(Zone.BATTLEFIELD, playerB, "Plains", 6); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, cathedralMembrane); + setChoice(playerB, true); // pay life + + attack(3, playerA, wurm, playerB); + + block(3, playerB, cathedralMembrane, wurm); + setChoiceAmount(playerA, 6); // assign trample damage + + setStrictChooseMode(true); + setStopAt(3, PhaseStep.END_COMBAT); + execute(); // separate execute needed to separate commands from second combat phase + + playLand(3, PhaseStep.POSTCOMBAT_MAIN, playerA, "Mountain"); + castSpell(3, PhaseStep.POSTCOMBAT_MAIN, playerB, recovery, cathedralMembrane); + + attack(3, playerA, wurm, playerB); + attack(3, playerA, gigantosaurus, playerB); + + block(3, playerB, cathedralMembrane, gigantosaurus); + + setStopAt(3, PhaseStep.END_TURN); + execute(); + + assertTapped(wurm, true); + assertTapped(gigantosaurus, true); + assertTapped(moraug, false); + assertGraveyardCount(playerB, cathedralMembrane, 1); + assertLife(playerA, 20); + assertLife(playerB, 20 - 2 - 4 - 11); + assertDamageReceived(playerA, wurm, 6); + assertDamageReceived(playerA, gigantosaurus, 1 + 6); + assertDamageReceived(playerA, moraug, 0); + + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/dialogs/TestableDialogsTest.java b/Mage.Tests/src/test/java/org/mage/test/dialogs/TestableDialogsTest.java new file mode 100644 index 00000000000..7a41de3d740 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/dialogs/TestableDialogsTest.java @@ -0,0 +1,328 @@ +package org.mage.test.dialogs; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.common.continuous.PlayAdditionalLandsAllEffect; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.utils.testers.TestableDialog; +import mage.utils.testers.TestableDialogsRunner; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; +import org.mage.test.player.TestPlayer; +import org.mage.test.serverside.base.CardTestPlayerBaseWithAIHelps; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Try to test all possible game dialogs by TestableDialogsRunner + *

+ * TODO: fill ai results for all generated dialogs + * + * @author JayDi85 + */ +public class TestableDialogsTest extends CardTestPlayerBaseWithAIHelps { + + TestableDialogsRunner runner = new TestableDialogsRunner(); + Ability fakeAbility = new SimpleStaticAbility(new InfoEffect("fake")); + + @Test + public void test_RunSingle_Manual() { + prepareCards(); + + runCode("run single", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> { + TestableDialog dialog = findDialog(runner, "target.choose(you, target)", "any 0-3"); + dialog.prepare(); + dialog.showDialog(playerA, fakeAbility, game, playerB); + }); + + // choice for 0-3 + setChoice(playerA, "Mountain"); + setChoice(playerA, "Mountain"); + setChoice(playerA, TestPlayer.CHOICE_SKIP); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + // it's ok to have wrong targets message cause manual testing selected x2, not AI's x3 + assertAndPrintRunnerResults(false, false); + } + + @Test + public void test_RunSingle_AI() { + prepareCards(); + + aiPlayStep(1, PhaseStep.PRECOMBAT_MAIN, PhaseStep.END_TURN, playerA); + aiPlayStep(1, PhaseStep.PRECOMBAT_MAIN, PhaseStep.END_TURN, playerB); + runCode("run single", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, (info, player, game) -> { + TestableDialog dialog = findDialog(runner, "target.choose(you, target)", "any 0-3"); + dialog.prepare(); + dialog.showDialog(playerA, fakeAbility, game, playerB); + }); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertAndPrintRunnerResults(false, true); + } + + @Test + public void test_RunAll_AI() { + // it's impossible to setup 700+ dialogs, so all choices made by AI + // current AI uses only simple choices in dialogs, not simulations + + prepareCards(); + + aiPlayStep(1, PhaseStep.PRECOMBAT_MAIN, PhaseStep.END_TURN, playerA); + aiPlayStep(1, PhaseStep.PRECOMBAT_MAIN, PhaseStep.END_TURN, playerB); + runCode("run all", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, (info, player, game) -> { + runner.getDialogs().forEach(dialog -> { + System.out.println(String.format("run testable dialog %d of %d (%s, %s - %s)", + dialog.getRegNumber(), + runner.getDialogs().size(), + dialog.getClass().getSimpleName(), + dialog.getGroup(), + dialog.getName() + )); + dialog.prepare(); + dialog.showDialog(playerA, fakeAbility, game, playerB); + }); + }); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertAndPrintRunnerResults(true, true); + } + + @Test + @Ignore // debug only - run single dialog by reg number + public void test_RunSingle_Debugging() { + int needRegNumber = 557; + + prepareCards(); + + aiPlayStep(1, PhaseStep.PRECOMBAT_MAIN, PhaseStep.END_TURN, playerA); + aiPlayStep(1, PhaseStep.PRECOMBAT_MAIN, PhaseStep.END_TURN, playerB); + runCode("run by number", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, (info, player, game) -> { + TestableDialog dialog = findDialog(runner, needRegNumber); + dialog.prepare(); + dialog.showDialog(playerA, fakeAbility, game, playerB); + }); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertAndPrintRunnerResults(false, true); + } + + private void prepareCards() { + // runner calls dialogs for both A and B, so players must have same cards + removeAllCardsFromLibrary(playerA); + removeAllCardsFromLibrary(playerB); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 6); + addCard(Zone.HAND, playerA, "Forest", 6); + addCard(Zone.BATTLEFIELD, playerB, "Mountain", 6); + addCard(Zone.HAND, playerB, "Forest", 6); + + runCode("restrict lands", 1, PhaseStep.UPKEEP, playerA, (info, player, game) -> { + // restrict any lands play, so AI will keep lands in hand + game.addEffect(new PlayAdditionalLandsAllEffect(-1), fakeAbility); + }); + } + + private TestableDialog findDialog(TestableDialogsRunner runner, String byGroup, String byName) { + List res = runner.getDialogs().stream() + .filter(dialog -> dialog.getGroup().equals(byGroup)) + .filter(dialog -> dialog.getName().equals(byName)) + .collect(Collectors.toList()); + Assert.assertEquals("must found only 1 dialog", 1, res.size()); + return res.get(0); + } + + private TestableDialog findDialog(TestableDialogsRunner runner, Integer byRegNumber) { + List res = runner.getDialogs().stream() + .filter(dialog -> dialog.getRegNumber().equals(byRegNumber)) + .collect(Collectors.toList()); + Assert.assertEquals("must found only 1 dialog", 1, res.size()); + return res.get(0); + } + + private void assertAndPrintRunnerResults(boolean showFullList, boolean failOnBadResults) { + // print table with full dialogs list and assert results + + // auto-size for columns + int maxNumberLength = "9999".length(); + int maxGroupLength = "Group".length(); + int maxNameLength = "Name".length(); + int maxResultLength = "Result".length(); + int needTotalsSize = 0; + for (TestableDialog dialog : runner.getDialogs()) { + if (!showFullList && !dialog.getResult().isFinished()) { + continue; + } + maxGroupLength = Math.max(maxGroupLength, dialog.getGroup().length()); + maxNameLength = Math.max(maxNameLength, dialog.getName().length()); + + // resize group to keep space for bigger total message like assert res + String resAssert = dialog.getResult().getResAssert(); + resAssert = resAssert == null ? "" : resAssert; + needTotalsSize = Math.max(needTotalsSize, dialog.getResult().getResDebugSource().length()); + needTotalsSize = Math.max(needTotalsSize, resAssert.length()); + int currentTotalsSize = maxNumberLength + maxGroupLength + maxNameLength + maxResultLength + 9; + if (currentTotalsSize < needTotalsSize) { + maxGroupLength = maxGroupLength + needTotalsSize - currentTotalsSize; + } + } + + String rowFormat = "| %-" + maxNumberLength + "s | %-" + maxGroupLength + "s | %-" + maxNameLength + "s | %-" + maxResultLength + "s |%n"; + String horizontalBorder = "+-" + + String.join("", Collections.nCopies(maxNumberLength, "-")) + "-+-" + + String.join("", Collections.nCopies(maxGroupLength, "-")) + "-+-" + + String.join("", Collections.nCopies(maxNameLength, "-")) + "-+-" + + String.join("", Collections.nCopies(maxResultLength, "-")) + "-+"; + String totalsLeftFormat = "| %-" + (maxNumberLength + maxGroupLength + maxNameLength + maxResultLength + 9) + "s |%n"; + String totalsRightFormat = "| %" + (maxNumberLength + maxGroupLength + maxNameLength + maxResultLength + 9) + "s |%n"; + + // print header row + System.out.println(horizontalBorder); + System.out.printf(rowFormat, "N", "Group", "Name", "Result"); + System.out.println(horizontalBorder); + + // print data rows + String prevGroup = ""; + int totalDialogs = 0; + int totalGood = 0; + int totalBad = 0; + int totalUnknown = 0; + TestableDialog firstBadDialog = null; + String firstBadAssert = ""; + String firstBadDebugSource = ""; + boolean usedHorizontalBorder = true; // mark that last print used horizontal border (fix duplicates) + Map coloredTexts = new HashMap<>(); // must colorize after string format to keep pretty table + for (TestableDialog dialog : runner.getDialogs()) { + if (!showFullList && !dialog.getResult().isFinished()) { + // print only required dialogs + continue; + } + totalDialogs++; + if (!prevGroup.isEmpty() && !prevGroup.equals(dialog.getGroup())) { + if (!usedHorizontalBorder) { + System.out.println(horizontalBorder); + usedHorizontalBorder = true; + } + } + prevGroup = dialog.getGroup(); + + // print dialog stats + String status; + coloredTexts.clear(); + String resAssert = dialog.getResult().getResAssert(); + String resDebugSource = dialog.getResult().getResDebugSource(); + String assertError = ""; + if (resAssert == null) { + totalUnknown++; + status = "?"; + coloredTexts.put("?", asYellow("?")); + } else if (resAssert.isEmpty()) { + totalGood++; + status = "OK"; + coloredTexts.put("OK", asGreen("OK")); + } else { + totalBad++; + status = "FAIL"; + coloredTexts.put("FAIL", asRed("FAIL")); + assertError = resAssert; + } + if (!assertError.isEmpty()) { + if (!usedHorizontalBorder) { + System.out.println(horizontalBorder); + usedHorizontalBorder = true; + } + } + System.out.print(getColoredRow(rowFormat, coloredTexts, dialog.getRegNumber(), dialog.getGroup(), dialog.getName(), status)); + usedHorizontalBorder = false; + + // print dialog error + if (!assertError.isEmpty()) { + coloredTexts.clear(); + coloredTexts.put(resAssert, asRed(resAssert)); + coloredTexts.put(resDebugSource, asRed(resDebugSource)); + String badAssert = getColoredRow(totalsRightFormat, coloredTexts, resAssert); + String badDebugSource = getColoredRow(totalsRightFormat, coloredTexts, resDebugSource); + if (firstBadDialog == null) { + firstBadDialog = dialog; + firstBadAssert = badAssert; + firstBadDebugSource = badDebugSource; + } + System.out.print(badAssert); + System.out.print(badDebugSource); + System.out.println(horizontalBorder); + usedHorizontalBorder = true; + } + } + if (!usedHorizontalBorder) { + System.out.println(horizontalBorder); + usedHorizontalBorder = true; + } + + // print totals + System.out.printf(totalsLeftFormat, "Total dialogs: " + totalDialogs); + usedHorizontalBorder = false; + String goodStats = String.format("%d good", totalGood); + String badStats = String.format("%d bad", totalBad); + String unknownStats = String.format("%d unknown", totalUnknown); + coloredTexts.clear(); + coloredTexts.put(goodStats, String.format("%s good", asGreen(String.valueOf(totalGood)))); + coloredTexts.put(badStats, String.format("%s bad", asRed(String.valueOf(totalBad)))); + coloredTexts.put(unknownStats, String.format("%s unknown", asYellow(String.valueOf(totalUnknown)))); + System.out.print(getColoredRow(totalsLeftFormat, coloredTexts, String.format("Total results: %s, %s, %s", + goodStats, badStats, unknownStats))); + // first error for fast access in big list + if (totalDialogs > 1 && firstBadDialog != null) { + System.out.println(horizontalBorder); + System.out.print(getColoredRow(totalsRightFormat, coloredTexts, "First bad dialog: " + firstBadDialog.getRegNumber())); + System.out.print(getColoredRow(totalsRightFormat, coloredTexts, firstBadDialog.getName() + " - " + firstBadDialog.getDescription())); + System.out.print(firstBadAssert); + System.out.print(firstBadDebugSource); + } + + // table end + System.out.println(horizontalBorder); + usedHorizontalBorder = true; + + if (failOnBadResults && totalBad > 0) { + Assert.fail(String.format("Testable dialogs has %d bad results, try to fix it", totalBad)); + } + } + + private String getColoredRow(String rowFormat, Map coloredTexts, Object... args) { + String line = String.format(rowFormat, args); + for (String coloredText : coloredTexts.keySet()) { + line = line.replace(coloredText, coloredTexts.get(coloredText)); + } + return line; + } + + private String asRed(String text) { + return "\u001B[31m" + text + "\u001B[0m"; + } + + private String asGreen(String text) { + return "\u001B[32m" + text + "\u001B[0m"; + } + + private String asYellow(String text) { + return "\u001B[33m" + text + "\u001B[0m"; + } +} \ No newline at end of file diff --git a/Mage.Tests/src/test/java/org/mage/test/load/LoadTest.java b/Mage.Tests/src/test/java/org/mage/test/load/LoadTest.java index 97b27a023ea..e9965808b0f 100644 --- a/Mage.Tests/src/test/java/org/mage/test/load/LoadTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/load/LoadTest.java @@ -918,12 +918,17 @@ public class LoadTest { public int getTotalEffectsCount() { return finalGameView == null ? 0 : this.finalGameView.getTotalEffectsCount(); } + + public int getGameCycle() { + return finalGameView == null ? 0 : this.finalGameView.getGameCycle(); + } } private static class LoadTestGameResultsList extends HashMap { - private static final String tableFormatHeader = "|%-10s|%-15s|%-20s|%-10s|%-10s|%-10s|%-10s|%-10s|%-15s|%-15s|%-10s|%n"; - private static final String tableFormatData = "|%-10s|%15s|%20s|%10s|%10s|%10s|%10s|%10s|%15s|%15s|%10s|%n"; + // index, name, random sid, game cycle, errors, effects, turn, life p1, life p2, creatures p1, creatures p2, =time, sec, ~time, sec + private static final String tableFormatHeader = "|%-10s|%-15s|%-20s|%-10s|%-10s|%-10s|%-10s|%-10s|%-10s|%-15s|%-15s|%-15s|%-15s|%n"; + private static final String tableFormatData = "|%-10s|%15s|%20s|%10s|%10s|%10s|%10s|%10s|%10s|%15s|%15s|%15s|%15s|%n"; public LoadTestGameResult createGame(int index, String name, long randomSeed) { if (this.containsKey(index)) { @@ -939,6 +944,7 @@ public class LoadTest { "index", "name", "random sid", + "game cycles", "errors", "effects", "turn", @@ -946,8 +952,8 @@ public class LoadTest { "life p2", "creatures p1", "creatures p2", - "time, sec", - "time per turn, sec" + "=time, sec", + "~time, sec" ); System.out.printf(tableFormatHeader, data.toArray()); } @@ -961,6 +967,7 @@ public class LoadTest { String.valueOf(gameResult.index), //"index", gameResult.name, //"name", String.valueOf(gameResult.randomSeed), // "random sid", + String.valueOf(gameResult.getGameCycle()), // "game cycles", String.valueOf(gameResult.getTotalErrorsCount()), // "errors", String.valueOf(gameResult.getTotalEffectsCount()), // "effects", gameResult.getTurnInfo(), //"turn", @@ -979,15 +986,16 @@ public class LoadTest { "TOTAL/AVG", //"index", String.valueOf(this.size()), //"name", "total, secs: " + String.format("%.3f", (float) this.getTotalDurationMs() / 1000), // "random sid", - String.valueOf(this.getTotalErrorsCount()), // errors - String.valueOf(this.getAvgEffectsCount()), // effects - String.valueOf(this.getAvgTurn()), // turn - String.valueOf(this.getAvgLife1()), // life p1 - String.valueOf(this.getAvgLife2()), // life p2 - String.valueOf(this.getAvgCreaturesCount1()), // creatures p1 - String.valueOf(this.getAvgCreaturesCount2()), // creatures p2 - String.valueOf(String.format("%.3f", (float) this.getAvgDurationMs() / 1000)), // time, sec - String.valueOf(String.format("%.3f", (float) this.getAvgDurationPerTurnMs() / 1000)) // time per turn, sec + "~" + this.getAvgGameCycle(), // game cycles + "=" + this.getTotalErrorsCount(), // errors + "~" + this.getAvgEffectsCount(), // effects + "~" + this.getAvgTurn(), // turn + "~" + this.getAvgLife1(), // life p1 + "~" + this.getAvgLife2(), // life p2 + "~" + this.getAvgCreaturesCount1(), // creatures p1 + "~" + this.getAvgCreaturesCount2(), // creatures p2 + "~" + String.format("%.3f", (float) this.getAvgDurationMs() / 1000), // time, sec + "~" + String.format("%.3f", (float) this.getAvgDurationPerTurnMs() / 1000) // time per turn, sec ); System.out.printf(tableFormatData, data.toArray()); } @@ -996,6 +1004,10 @@ public class LoadTest { return this.values().stream().mapToInt(LoadTestGameResult::getTotalErrorsCount).sum(); } + private int getAvgGameCycle() { + return this.size() == 0 ? 0 : this.values().stream().mapToInt(LoadTestGameResult::getGameCycle).sum() / this.size(); + } + private int getAvgEffectsCount() { return this.size() == 0 ? 0 : this.values().stream().mapToInt(LoadTestGameResult::getTotalEffectsCount).sum() / this.size(); } diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java index 80ce3115065..257266776f3 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java @@ -543,7 +543,7 @@ public class TestPlayer implements Player { if (currentTarget.getOriginalTarget() instanceof TargetCreaturePermanentAmount) { // supports only to set the complete amount to one target TargetCreaturePermanentAmount targetAmount = (TargetCreaturePermanentAmount) currentTarget.getOriginalTarget(); - targetAmount.setAmount(ability, game); + targetAmount.prepareAmount(ability, game); int amount = targetAmount.getAmountRemaining(); targetAmount.addTarget(id, amount, ability, game); targetsSet++; @@ -2101,10 +2101,7 @@ public class TestPlayer implements Player { if (target == null) { return "Target: null"; } - UUID abilityControllerId = getId(); - if (target.getTargetController() != null && target.getAbilityController() != null) { - abilityControllerId = target.getAbilityController(); - } + UUID abilityControllerId = target.getAffectedAbilityControllerId(this.getId()); Set possibleTargets = target.possibleTargets(abilityControllerId, source, game); return "Target: selected " + target.getSize() + ", possible " + possibleTargets.size() @@ -2267,20 +2264,19 @@ public class TestPlayer implements Player { @Override public boolean choose(Outcome outcome, Target target, Ability source, Game game, Map options) { - UUID abilityControllerId = this.getId(); - if (target.getTargetController() != null && target.getAbilityController() != null) { - abilityControllerId = target.getAbilityController(); + + // choose itself for starting player all the time + if (target.getMessage(game).equals("Select a starting player")) { + target.add(this.getId(), game); + return true; } + UUID abilityControllerId = target.getAffectedAbilityControllerId(this.getId()); + // TODO: warning, some cards call player.choose methods instead target.choose, see #8254 // most use cases - discard and other cost with choice like that method // must migrate all choices.remove(xxx) to choices.remove(0), takeMaxTargetsPerChoose can help to find it - // ignore player select - if (target.getMessage(game).equals("Select a starting player")) { - return computerPlayer.choose(outcome, target, source, game, options); - } - boolean isAddedSomething = false; // must return true on any changes in targets, so game can ask next choose dialog until finish assertAliasSupportInChoices(true); @@ -2328,7 +2324,7 @@ public class TestPlayer implements Player { continue; } if (hasObjectTargetNameOrAlias(permanent, targetName)) { - if (target.isNotTarget() || target.canTarget(abilityControllerId, permanent.getId(), source, game)) { + if (target.canTarget(abilityControllerId, permanent.getId(), source, game) && !target.contains(permanent.getId())) { if ((permanent.isCopy() && !originOnly) || (!permanent.isCopy() && !copyOnly)) { target.add(permanent.getId(), game); isAddedSomething = true; @@ -2336,7 +2332,7 @@ public class TestPlayer implements Player { } } } else if ((permanent.getName() + '-' + permanent.getExpansionSetCode()).equals(targetName)) { // TODO: remove search by exp code? - if (target.isNotTarget() || target.canTarget(abilityControllerId, permanent.getId(), source, game)) { + if (target.canTarget(abilityControllerId, permanent.getId(), source, game) && !target.contains(permanent.getId())) { if ((permanent.isCopy() && !originOnly) || (!permanent.isCopy() && !copyOnly)) { target.add(permanent.getId(), game); isAddedSomething = true; @@ -2371,7 +2367,7 @@ public class TestPlayer implements Player { isAddedSomething = false; for (Player player : game.getPlayers().values()) { if (player.getName().equals(choiceRecord)) { - if (target.canTarget(abilityControllerId, player.getId(), null, game) && !target.contains(player.getId())) { + if (target.canTarget(abilityControllerId, player.getId(), source, game) && !target.contains(player.getId())) { target.add(player.getId(), game); isAddedSomething = true; } @@ -2507,11 +2503,7 @@ public class TestPlayer implements Player { @Override public boolean chooseTarget(Outcome outcome, Target target, Ability source, Game game) { - UUID abilityControllerId = this.getId(); - if (target.getTargetController() != null && target.getAbilityController() != null) { - abilityControllerId = target.getAbilityController(); - } - UUID sourceId = source != null ? source.getSourceId() : null; + UUID abilityControllerId = target.getAffectedAbilityControllerId(this.getId()); assertAliasSupportInTargets(true); if (!targets.isEmpty()) { @@ -2538,7 +2530,8 @@ public class TestPlayer implements Player { String playerName = targetDefinition.substring(targetDefinition.indexOf("targetPlayer=") + 13); for (Player player : game.getPlayers().values()) { if (player.getName().equals(playerName) - && target.canTarget(abilityControllerId, player.getId(), source, game)) { + && target.canTarget(abilityControllerId, player.getId(), source, game) + && !target.contains(player.getId())) { target.addTarget(player.getId(), source, game); targets.remove(targetDefinition); return true; @@ -2814,10 +2807,7 @@ public class TestPlayer implements Player { @Override public boolean chooseTarget(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game) { - UUID abilityControllerId = this.getId(); - if (target.getTargetController() != null && target.getAbilityController() != null) { - abilityControllerId = target.getAbilityController(); - } + UUID abilityControllerId = target.getAffectedAbilityControllerId(this.getId()); assertAliasSupportInTargets(false); if (!targets.isEmpty()) { @@ -2887,7 +2877,7 @@ public class TestPlayer implements Player { @Override public boolean chooseUse(Outcome outcome, String message, String secondMessage, String trueText, String falseText, Ability source, Game game) { - if (message.equals("Scry 1?")) { + if (message != null && message.equals("Scry 1?")) { return false; } assertAliasSupportInChoices(false); @@ -4326,10 +4316,20 @@ public class TestPlayer implements Player { // chooseTargetAmount calls for EACH target cycle (e.g. one target per click, see TargetAmount) // if use want to stop choosing then chooseTargetAmount must return false (example: up to xxx) - Assert.assertNotEquals("chooseTargetAmount needs non zero amount remaining", 0, target.getAmountRemaining()); + // nothing to choose + target.prepareAmount(source, game); + if (target.getAmountRemaining() <= 0) { + return false; + } + if (target.getMaxNumberOfTargets() == 0 && target.getMinNumberOfTargets() == 0) { + return false; + } + + UUID abilityControllerId = target.getAffectedAbilityControllerId(this.getId()); assertAliasSupportInTargets(true); - if (!targets.isEmpty()) { + + while (!targets.isEmpty()) { // skip targets if (targets.get(0).equals(TARGET_SKIP)) { @@ -4381,7 +4381,11 @@ public class TestPlayer implements Player { // can select target.addTarget(possibleTarget, targetAmount, source, game); targets.remove(0); - return true; // one target per choose call + // allow test player to choose as much as possible until skip command + if (target.getAmountRemaining() <= 0) { + return true; + } + break; // try next target } } } diff --git a/Mage.Tests/src/test/java/org/mage/test/utils/DebugUtilTest.java b/Mage.Tests/src/test/java/org/mage/test/utils/DebugUtilTest.java index 45ff3069e33..65b89f753a3 100644 --- a/Mage.Tests/src/test/java/org/mage/test/utils/DebugUtilTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/utils/DebugUtilTest.java @@ -15,9 +15,9 @@ public class DebugUtilTest extends CardTestPlayerBase { } private void secondMethod() { - String resCurrent = DebugUtil.getMethodNameWithSource(0); - String resPrev = DebugUtil.getMethodNameWithSource(1); - String resPrevPrev = DebugUtil.getMethodNameWithSource(2); + String resCurrent = DebugUtil.getMethodNameWithSource(0, "method"); + String resPrev = DebugUtil.getMethodNameWithSource(1, "method"); + String resPrevPrev = DebugUtil.getMethodNameWithSource(2, "method"); Assert.assertTrue("must find secondMethod, but get " + resCurrent, resCurrent.startsWith("secondMethod")); Assert.assertTrue("must find firstMethod, but get " + resPrev, resPrev.startsWith("firstMethod")); Assert.assertTrue("must find test_StackTraceWithSourceName, but get " + resPrevPrev, resPrevPrev.startsWith("test_StackTraceWithSourceName")); diff --git a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java index 9c9afcfc5bd..c58738dac2f 100644 --- a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java +++ b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java @@ -16,6 +16,7 @@ import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.ExileUntilSourceLeavesEffect; import mage.abilities.effects.common.FightTargetsEffect; +import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.counter.ProliferateEffect; import mage.abilities.effects.keyword.ScryEffect; import mage.abilities.hint.common.CitysBlessingHint; @@ -36,6 +37,7 @@ import mage.constants.*; import mage.filter.Filter; import mage.filter.predicate.Predicate; import mage.filter.predicate.Predicates; +import mage.game.FakeGame; import mage.game.Game; import mage.game.command.Dungeon; import mage.game.command.Plane; @@ -83,10 +85,22 @@ public class VerifyCardDataTest { private static final Logger logger = Logger.getLogger(VerifyCardDataTest.class); - private static final String FULL_ABILITIES_CHECK_SET_CODES = "BLC"; // check ability text due mtgjson, can use multiple sets like MAT;CMD or * for all - private static final boolean CHECK_ONLY_ABILITIES_TEXT = false; // use when checking text locally, suppresses unnecessary checks and output messages + private static String FULL_ABILITIES_CHECK_SET_CODES = ""; // check ability text due mtgjson, can use multiple sets like MAT;CMD or * for all + private static boolean CHECK_ONLY_ABILITIES_TEXT = false; // use when checking text locally, suppresses unnecessary checks and output messages private static final boolean CHECK_COPYABLE_FIELDS = true; // disable for better verify test performance + // for automated local testing support + static { + String val = System.getProperty("xmage.tests.verifyCheckSetCodes"); + if (val != null) { + FULL_ABILITIES_CHECK_SET_CODES = val; + } + val = System.getProperty("xmage.tests.verifyCheckOnlyText"); + if (val != null) { + CHECK_ONLY_ABILITIES_TEXT = Boolean.parseBoolean(val); + } + } + private static final boolean AUTO_FIX_SAMPLE_DECKS = false; // debug only: auto-fix sample decks by test_checkSampleDecks test run private static final Set checkedNames = new HashSet<>(); // skip already checked cards @@ -1683,6 +1697,61 @@ public class VerifyCardDataTest { } } + @Test + @Ignore + // experimental test to find potentially fail conditions with NPE see https://github.com/magefree/mage/issues/13752 + public void test_checkBadConditions() { + // all conditions in AsThoughEffect must be compatible with empty source param (e.g. must be able to use inside ConditionalAsThoughEffect) + // see AsThoughEffectType.needAffectedAbility ? + // 370+ failed conditions + Collection errorsList = new ArrayList<>(); + Game fakeGame = new FakeGame(); + Ability fakeAbility = new SimpleStaticAbility(new InfoEffect("fake")); + + // TODO: add classes support (see example with tokens and default constructor)? + Reflections reflections = new Reflections("mage."); + Set> conditionEnums = reflections.getSubTypesOf(Condition.class) + .stream() + .filter(Class::isEnum) + .sorted(Comparator.comparing(Class::toString)) + .collect(Collectors.toCollection(LinkedHashSet::new)); + for (Class enumClass : conditionEnums) { + for (Object enumItem : enumClass.getEnumConstants()) { + // miss watcher will fail in both use cases, but miss ability only one + String errorOnAbility = ""; + try { + ((Condition) enumItem).apply(fakeGame, fakeAbility); + } catch (Exception e) { + errorOnAbility = Arrays.stream(e.getStackTrace()) + .map(StackTraceElement::toString) + .limit(5) + .collect(Collectors.joining("\n")); + } + + String errorOnEmptyAbility = ""; + try { + ((Condition) enumItem).apply(fakeGame, null); + } catch (Exception e) { + errorOnEmptyAbility = Arrays.stream(e.getStackTrace()) + .map(StackTraceElement::toString) + .limit(5) + .collect(Collectors.joining("\n")); + } + + if (errorOnAbility.isEmpty() && !errorOnEmptyAbility.isEmpty()) { + System.out.println(); + System.out.println("bad condition " + enumClass.getName() + "\n" + errorOnEmptyAbility); + errorsList.add("Error: condition must support empty and non-empty source params: " + enumClass.getName()); + } + } + } + + printMessages(errorsList); + if (!errorsList.isEmpty()) { + Assert.fail("Found conditions errors: " + errorsList.size()); + } + } + private void check(Card card, int cardIndex) { MtgJsonCard ref = MtgJsonService.cardFromSet(card.getExpansionSetCode(), card.getName(), card.getCardNumber()); if (ref != null) { @@ -3338,4 +3407,4 @@ public class VerifyCardDataTest { System.out.println(String.format("ALL DONE, found and write %d combos", allCombos.size())); } -} \ No newline at end of file +} diff --git a/Mage/src/main/java/mage/abilities/Ability.java b/Mage/src/main/java/mage/abilities/Ability.java index 31dee95d241..a834cf8be68 100644 --- a/Mage/src/main/java/mage/abilities/Ability.java +++ b/Mage/src/main/java/mage/abilities/Ability.java @@ -516,6 +516,10 @@ public interface Ability extends Controllable, Serializable { */ void initSourceObjectZoneChangeCounter(Game game, boolean force); + // TODO: it's activating time of ability, not current object's zcc, see #13737, + // in most use cases you must use game.getState().getZoneChangeCounter or input.getObject().getZoneChangeCounter(game) + // only ability related logic can use it (example: delayed triggers) + @Deprecated int getSourceObjectZoneChangeCounter(); /** diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java index ad735b98e74..6366a6a4209 100644 --- a/Mage/src/main/java/mage/abilities/AbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java @@ -1226,10 +1226,7 @@ public abstract class AbilityImpl implements Ability { for (Mode mode : modes.values()) { boolean validTargets = true; for (Target target : mode.getTargets()) { - UUID abilityControllerId = controllerId; - if (target.getTargetController() != null) { - abilityControllerId = target.getTargetController(); - } + UUID abilityControllerId = target.getAffectedAbilityControllerId(controllerId); if (!target.canChoose(abilityControllerId, ability, game)) { validTargets = false; break; diff --git a/Mage/src/main/java/mage/abilities/ActivatedAbility.java b/Mage/src/main/java/mage/abilities/ActivatedAbility.java index 02205c61626..33399fbb77a 100644 --- a/Mage/src/main/java/mage/abilities/ActivatedAbility.java +++ b/Mage/src/main/java/mage/abilities/ActivatedAbility.java @@ -75,7 +75,7 @@ public interface ActivatedAbility extends Ability { * * @param mayActivate */ - void setMayActivate(TargetController mayActivate); + ActivatedAbility setMayActivate(TargetController mayActivate); /** * Returns the minimal possible cost for what the ability can be activated diff --git a/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java b/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java index 0290cb0b6e1..08ec1313fc2 100644 --- a/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java @@ -182,8 +182,9 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa } @Override - public void setMayActivate(TargetController mayActivate) { + public ActivatedAbilityImpl setMayActivate(TargetController mayActivate) { this.mayActivate = mayActivate; + return this; } public UUID getActivatorId() { diff --git a/Mage/src/main/java/mage/abilities/DelayedTriggeredAbility.java b/Mage/src/main/java/mage/abilities/DelayedTriggeredAbility.java index 15d9a52a61c..4f8afbc5d97 100644 --- a/Mage/src/main/java/mage/abilities/DelayedTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/DelayedTriggeredAbility.java @@ -10,7 +10,7 @@ import mage.game.Game; */ public abstract class DelayedTriggeredAbility extends TriggeredAbilityImpl { - private final Duration duration; + private Duration duration; protected boolean triggerOnlyOnce; protected DelayedTriggeredAbility(Effect effect) { @@ -44,6 +44,10 @@ public abstract class DelayedTriggeredAbility extends TriggeredAbilityImpl { return duration; } + public void setDuration(Duration duration) { + this.duration = duration; + } + public boolean getTriggerOnlyOnce() { return triggerOnlyOnce; } diff --git a/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java b/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java index 93100ce08c3..b3e20a2d92b 100644 --- a/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java @@ -218,6 +218,7 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge @Override public TriggeredAbility withInterveningIf(Condition interveningIfCondition) { this.interveningIfCondition = interveningIfCondition; + this.replaceRuleText = false; return this; } @@ -301,6 +302,9 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge if (!conditionText.isEmpty()) { // e.g. CaseSolveAbility if (replaceRuleText && triggerPhrase != null && triggerPhrase.contains("{this}")) { conditionText = conditionText.replace("{this}", "it"); + if (conditionText.startsWith("it is ")) { + conditionText = conditionText.replace("it is ", "it's "); + } } if (!conditionText.startsWith("if ")) { sb.append("if "); @@ -329,7 +333,7 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge } } if (replaceRuleText && triggerPhrase != null) { - superRule = superRule.replaceFirst("^((?:you may )?sacrifice |(put|remove) [^ ]+ [^ ]+ counters? (on|from) |return |transform |untap |regenerate )?\\{this\\}", "$1it"); + superRule = superRule.replaceFirst("^((?:you may )?sacrifice |(put|remove) [^ ]+ [^ ]+ counters? (on|from) |return |transform |untap |regenerate |attach )?\\{this\\}", "$1it"); } sb.append(superRule); if (triggerLimitEachTurn != Integer.MAX_VALUE) { diff --git a/Mage/src/main/java/mage/abilities/common/ActivateIfConditionActivatedAbility.java b/Mage/src/main/java/mage/abilities/common/ActivateIfConditionActivatedAbility.java index 8d9804f7504..06906571472 100644 --- a/Mage/src/main/java/mage/abilities/common/ActivateIfConditionActivatedAbility.java +++ b/Mage/src/main/java/mage/abilities/common/ActivateIfConditionActivatedAbility.java @@ -5,55 +5,81 @@ import mage.abilities.condition.Condition; import mage.abilities.condition.InvertCondition; import mage.abilities.costs.Cost; import mage.abilities.effects.Effect; +import mage.abilities.effects.Effects; +import mage.constants.EffectType; import mage.constants.TimingRule; import mage.constants.Zone; +import mage.game.Game; +import mage.util.CardUtil; /** * @author LevelX2 */ public class ActivateIfConditionActivatedAbility extends ActivatedAbilityImpl { + private static final Effects emptyEffects = new Effects(); + + private String conditionText = null; + public ActivateIfConditionActivatedAbility(Effect effect, Cost cost, Condition condition) { - this(Zone.BATTLEFIELD, effect, cost, condition, TimingRule.INSTANT); + this(Zone.BATTLEFIELD, effect, cost, condition); } public ActivateIfConditionActivatedAbility(Zone zone, Effect effect, Cost cost, Condition condition) { - this(zone, effect, cost, condition, TimingRule.INSTANT); - } - - public ActivateIfConditionActivatedAbility(Zone zone, Effect effect, Cost cost, Condition condition, TimingRule timing) { super(zone, effect, cost); this.condition = condition; - this.timing = timing; } protected ActivateIfConditionActivatedAbility(final ActivateIfConditionActivatedAbility ability) { super(ability); + this.conditionText = ability.conditionText; + } + + @Override + public Effects getEffects(Game game, EffectType effectType) { + if (!condition.apply(game, this)) { + return emptyEffects; + } + return super.getEffects(game, effectType); + } + + public ActivateIfConditionActivatedAbility hideCondition() { + return withConditionText(""); + } + + public ActivateIfConditionActivatedAbility withConditionText(String conditionText) { + this.conditionText = conditionText; + return this; } @Override public String getRule() { - StringBuilder sb = new StringBuilder(super.getRule()); - if (condition.toString().startsWith("You may also")) { - sb.append(' ').append(condition.toString()).append('.'); - return sb.toString(); + if (conditionText != null) { + if (conditionText.isEmpty()) { + return super.getRule(); + } + return super.getRule() + ' ' + CardUtil.getTextWithFirstCharUpperCase(conditionText) + '.'; } + String conditionText = condition.toString(); + if (conditionText.startsWith("You may also")) { + return super.getRule() + ' ' + conditionText + '.'; + } + StringBuilder sb = new StringBuilder(super.getRule()); if (condition instanceof InvertCondition) { sb.append(" You can't activate this ability "); } else { sb.append(" Activate only "); } - if (!condition.toString().startsWith("during") - && !condition.toString().startsWith("before") - && !condition.toString().startsWith("if")) { + if (!conditionText.startsWith("during") + && !conditionText.startsWith("before") + && !conditionText.startsWith("if")) { sb.append("if "); } - sb.append(condition.toString()); + sb.append(conditionText); if (timing == TimingRule.SORCERY) { sb.append(" and only as a sorcery"); } sb.append('.'); - return sb.toString(); } @@ -61,5 +87,4 @@ public class ActivateIfConditionActivatedAbility extends ActivatedAbilityImpl { public ActivateIfConditionActivatedAbility copy() { return new ActivateIfConditionActivatedAbility(this); } - } diff --git a/Mage/src/main/java/mage/abilities/common/AnimateDeadTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/AnimateDeadTriggeredAbility.java index daaf7e7359d..f81d85be913 100644 --- a/Mage/src/main/java/mage/abilities/common/AnimateDeadTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/AnimateDeadTriggeredAbility.java @@ -16,16 +16,12 @@ import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; import mage.players.Player; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import mage.target.targetpointer.FixedTarget; import mage.util.CardUtil; import mage.watchers.Watcher; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.UUID; +import java.util.*; /** * @author LevelX2, awjackson @@ -66,13 +62,13 @@ class AnimateDeadReplaceAbilityEffect extends ContinuousEffectImpl { private final boolean becomesAura; private Ability newAbility; - private TargetCreaturePermanent newTarget; + private TargetPermanent newTarget; public AnimateDeadReplaceAbilityEffect(boolean becomesAura) { super(Duration.Custom, Outcome.AddAbility); this.becomesAura = becomesAura; staticText = (becomesAura ? "it becomes an Aura with" : - "it loses \"enchant creature card in a graveyard\" and gains" + "it loses \"enchant creature card in a graveyard\" and gains" ) + " \"enchant creature put onto the battlefield with {this}.\""; if (becomesAura) { dependencyTypes.add(DependencyType.AuraAddingRemoving); @@ -98,7 +94,7 @@ class AnimateDeadReplaceAbilityEffect extends ContinuousEffectImpl { FilterCreaturePermanent filter = new FilterCreaturePermanent("creature put onto the battlefield with {this}"); filter.add(new AnimateDeadPredicate(source.getSourceId())); - newTarget = new TargetCreaturePermanent(filter); + newTarget = new TargetPermanent(filter); newAbility = new EnchantAbility(newTarget); } diff --git a/Mage/src/main/java/mage/abilities/common/AttacksPlayerWithCreaturesTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/AttacksPlayerWithCreaturesTriggeredAbility.java new file mode 100644 index 00000000000..1264c40f4cd --- /dev/null +++ b/Mage/src/main/java/mage/abilities/common/AttacksPlayerWithCreaturesTriggeredAbility.java @@ -0,0 +1,107 @@ +package mage.abilities.common; + +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.constants.SetTargetPointer; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.events.DefenderAttackedEvent; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; +import mage.target.targetpointer.FixedTargets; +import mage.util.CardUtil; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * based heavily on AttacksWithCreaturesTriggeredAbility + * @author notgreat + */ +public class AttacksPlayerWithCreaturesTriggeredAbility extends TriggeredAbilityImpl { + private final FilterPermanent filter; + private final int minAttackers; + private final boolean onlyOpponents; + private final SetTargetPointer setTargetPointer; + + public AttacksPlayerWithCreaturesTriggeredAbility(Effect effect, SetTargetPointer setTargetPointer) { + this(effect, StaticFilters.FILTER_PERMANENT_CREATURE_CONTROLLED, setTargetPointer); + } + + public AttacksPlayerWithCreaturesTriggeredAbility(Effect effect, FilterPermanent filter, SetTargetPointer setTargetPointer) { + this(effect, 1, filter, setTargetPointer, false); + } + + public AttacksPlayerWithCreaturesTriggeredAbility(Effect effect, int minAttackers, FilterPermanent filter, SetTargetPointer setTargetPointer, boolean onlyOpponents) { + this(Zone.BATTLEFIELD, effect, minAttackers, filter, setTargetPointer, onlyOpponents, false); + } + + public AttacksPlayerWithCreaturesTriggeredAbility(Zone zone, Effect effect, int minAttackers, FilterPermanent filter, SetTargetPointer setTargetPointer, boolean onlyOpponents, boolean optional) { + super(zone, effect, optional); + this.filter = filter; + this.minAttackers = minAttackers; + this.onlyOpponents = onlyOpponents; + this.setTargetPointer = setTargetPointer; + if (minAttackers == 1 && StaticFilters.FILTER_PERMANENT_CREATURE_CONTROLLED.equals(filter) && !onlyOpponents) { + setTriggerPhrase("Whenever you attack a player, "); + } else { + setTriggerPhrase("Whenever " + CardUtil.numberToText(minAttackers) + " or more " + filter.getMessage() + + " attack " + (onlyOpponents ? "an opponent" : "a player") + ", "); + } + } + + protected AttacksPlayerWithCreaturesTriggeredAbility(final AttacksPlayerWithCreaturesTriggeredAbility ability) { + super(ability); + this.filter = ability.filter; + this.minAttackers = ability.minAttackers; + this.onlyOpponents = ability.onlyOpponents; + this.setTargetPointer = ability.setTargetPointer; + } + + @Override + public AttacksPlayerWithCreaturesTriggeredAbility copy() { + return new AttacksPlayerWithCreaturesTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DEFENDER_ATTACKED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Player player = game.getPlayer(getControllerId()); + UUID attackedId = event.getTargetId(); + if (player == null || game.getPlayer(attackedId) == null) { + return false; + } + DefenderAttackedEvent attackedEvent = (DefenderAttackedEvent) event; + List attackers = attackedEvent.getAttackers(game).stream() + .filter(permanent -> filter.match(permanent, controllerId, this, game)) + .collect(Collectors.toList()); + if (attackers.size() < minAttackers || (onlyOpponents && !game.isOpponent(player, attackedId))) { + return false; + } + switch (setTargetPointer){ + case NONE: + break; + case PLAYER: + getEffects().setTargetPointer(new FixedTarget(attackedId)); + break; + case PERMANENT: + getEffects().setTargetPointer(new FixedTargets(new ArrayList<>(attackers), game)); + break; + default: + throw new UnsupportedOperationException("Unexpected setTargetPointer in AttacksPlayerWithCreaturesTriggeredAbility: " + setTargetPointer); + + } + this.getEffects().setValue("playerAttacked",attackedId); + return true; + } +} diff --git a/Mage/src/main/java/mage/abilities/common/BecomesAuraAttachToManifestSourceEffect.java b/Mage/src/main/java/mage/abilities/common/BecomesAuraAttachToManifestSourceEffect.java index ccf51904b2b..f0f9a747137 100644 --- a/Mage/src/main/java/mage/abilities/common/BecomesAuraAttachToManifestSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/common/BecomesAuraAttachToManifestSourceEffect.java @@ -12,6 +12,7 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.util.CardUtil; @@ -47,7 +48,7 @@ public class BecomesAuraAttachToManifestSourceEffect extends OneShotEffect { if (enchantedCreature != null) { enchantedCreature.addAttachment(enchantment.getId(), source, game); FilterCreaturePermanent filter = new FilterCreaturePermanent(); - Target target = new TargetCreaturePermanent(filter); + Target target = new TargetPermanent(filter); target.addTarget(enchantedCreature.getId(), source, game); game.addEffect(new BecomesAuraSourceEffect(target), source); } diff --git a/Mage/src/main/java/mage/abilities/common/BecomesTargetAnyTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BecomesTargetAnyTriggeredAbility.java index 01816dc7446..bcd65966258 100644 --- a/Mage/src/main/java/mage/abilities/common/BecomesTargetAnyTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/BecomesTargetAnyTriggeredAbility.java @@ -12,7 +12,6 @@ import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.stack.StackObject; import mage.target.targetpointer.FixedTarget; -import mage.util.CardUtil; /** * @author xenohedron @@ -70,7 +69,7 @@ public class BecomesTargetAnyTriggeredAbility extends TriggeredAbilityImpl { if (permanent == null || !filterTarget.match(permanent, getControllerId(), this, game)) { return false; } - StackObject targetingObject = CardUtil.findTargetingStackObject(this.getId().toString(), event, game); + StackObject targetingObject = game.findTargetingStackObject(this.getId().toString(), event); if (targetingObject == null || !filterStack.match(targetingObject, getControllerId(), this, game)) { return false; } diff --git a/Mage/src/main/java/mage/abilities/common/BecomesTargetAttachedTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BecomesTargetAttachedTriggeredAbility.java index 54481419723..93501b89c17 100644 --- a/Mage/src/main/java/mage/abilities/common/BecomesTargetAttachedTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/BecomesTargetAttachedTriggeredAbility.java @@ -8,10 +8,9 @@ import mage.filter.FilterStackObject; import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.stack.StackObject; import mage.game.permanent.Permanent; +import mage.game.stack.StackObject; import mage.target.targetpointer.FixedTarget; -import mage.util.CardUtil; /** * @author LoneFox @@ -54,7 +53,7 @@ public class BecomesTargetAttachedTriggeredAbility extends TriggeredAbilityImpl if (enchantment == null || enchantment.getAttachedTo() == null || !event.getTargetId().equals(enchantment.getAttachedTo())) { return false; } - StackObject targetingObject = CardUtil.findTargetingStackObject(this.getId().toString(), event, game); + StackObject targetingObject = game.findTargetingStackObject(this.getId().toString(), event); if (targetingObject == null || !filter.match(targetingObject, getControllerId(), this, game)) { return false; } diff --git a/Mage/src/main/java/mage/abilities/common/BecomesTargetControllerTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BecomesTargetControllerTriggeredAbility.java index c6948f53828..83006241427 100644 --- a/Mage/src/main/java/mage/abilities/common/BecomesTargetControllerTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/BecomesTargetControllerTriggeredAbility.java @@ -3,15 +3,14 @@ package mage.abilities.common; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; import mage.constants.SetTargetPointer; +import mage.constants.Zone; import mage.filter.FilterPermanent; import mage.filter.FilterStackObject; -import mage.game.events.GameEvent; -import mage.constants.Zone; import mage.game.Game; +import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.stack.StackObject; import mage.target.targetpointer.FixedTarget; -import mage.util.CardUtil; /** * @author xenohedron @@ -63,7 +62,7 @@ public class BecomesTargetControllerTriggeredAbility extends TriggeredAbilityImp return false; } } - StackObject targetingObject = CardUtil.findTargetingStackObject(this.getId().toString(), event, game); + StackObject targetingObject = game.findTargetingStackObject(this.getId().toString(), event); if (targetingObject == null || !filterStack.match(targetingObject, getControllerId(), this, game)) { return false; } diff --git a/Mage/src/main/java/mage/abilities/common/BecomesTargetSourceTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BecomesTargetSourceTriggeredAbility.java index 0f61e332e7d..df3cd8ca8af 100644 --- a/Mage/src/main/java/mage/abilities/common/BecomesTargetSourceTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/BecomesTargetSourceTriggeredAbility.java @@ -10,7 +10,6 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.stack.StackObject; import mage.target.targetpointer.FixedTarget; -import mage.util.CardUtil; /** * @author North @@ -57,7 +56,7 @@ public class BecomesTargetSourceTriggeredAbility extends TriggeredAbilityImpl { if (!event.getTargetId().equals(getSourceId())) { return false; } - StackObject targetingObject = CardUtil.findTargetingStackObject(this.getId().toString(), event, game); + StackObject targetingObject = game.findTargetingStackObject(this.getId().toString(), event); if (targetingObject == null || !filter.match(targetingObject, getControllerId(), this, game)) { return false; } diff --git a/Mage/src/main/java/mage/abilities/common/CaseAbility.java b/Mage/src/main/java/mage/abilities/common/CaseAbility.java index 21e95e09bd5..9b736f1a3b9 100644 --- a/Mage/src/main/java/mage/abilities/common/CaseAbility.java +++ b/Mage/src/main/java/mage/abilities/common/CaseAbility.java @@ -5,7 +5,6 @@ import mage.abilities.TriggeredAbility; import mage.abilities.condition.CompoundCondition; import mage.abilities.condition.Condition; import mage.abilities.condition.common.SolvedSourceCondition; -import mage.abilities.decorator.ConditionalActivatedAbility; import mage.abilities.decorator.ConditionalAsThoughEffect; import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.decorator.ConditionalReplacementEffect; @@ -62,7 +61,7 @@ public class CaseAbility extends SimpleStaticAbility { * * The "Solved" ability must be one of the following: *

    - *
  • {@link ConditionalActivatedAbility} using the condition {@link SolvedSourceCondition}.SOLVED
  • + *
  • {@link ActivateIfConditionActivatedAbility} using the condition {@link SolvedSourceCondition}.SOLVED
  • *
  • {@link TriggeredAbility} using the condition {@link SolvedSourceCondition}.SOLVED
  • *
  • {@link SimpleStaticAbility} with only {@link ConditionalAsThoughEffect} or {@link ConditionalContinuousEffect} effects
  • *
@@ -81,7 +80,7 @@ public class CaseAbility extends SimpleStaticAbility { addSubAbility(new CaseSolveAbility(toSolveCondition)); - if (!(solvedAbility instanceof ConditionalActivatedAbility)) { + if (!(solvedAbility instanceof ActivateIfConditionActivatedAbility)) { if (solvedAbility instanceof TriggeredAbility) { if (!(((TriggeredAbility) solvedAbility).getTriggerCondition() instanceof SolvedSourceCondition)) { throw new IllegalArgumentException("Wrong code usage: if solvedAbility is a TriggeredAbility it must have SolvedSourceCondition as its trigger condition"); @@ -92,17 +91,17 @@ public class CaseAbility extends SimpleStaticAbility { if (!(effect instanceof ConditionalContinuousEffect || effect instanceof ConditionalAsThoughEffect || effect instanceof ConditionalReplacementEffect)) { - throw new IllegalArgumentException("Wrong code usage: solvedAbility must be one of ConditionalActivatedAbility, " + + throw new IllegalArgumentException("Wrong code usage: solvedAbility must be one of ActivateIfConditionActivatedAbility, " + "TriggeredAbility, or StaticAbility with conditional effects."); } } } else { - throw new IllegalArgumentException("Wrong code usage: solvedAbility must be one of ConditionalActivatedAbility, " + + throw new IllegalArgumentException("Wrong code usage: solvedAbility must be one of ActivateIfConditionActivatedAbility, " + "TriggeredAbility, or StaticAbility with conditional effects."); } } } else { - ((ConditionalActivatedAbility) solvedAbility).hideCondition(); + ((ActivateIfConditionActivatedAbility) solvedAbility).hideCondition(); } addSubAbility(solvedAbility.withFlavorWord("Solved")); // TODO: Technically this shouldn't be italicized } diff --git a/Mage/src/main/java/mage/abilities/common/CastSpellPaidBySourceTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/CastSpellPaidBySourceTriggeredAbility.java index 501f68e9c74..058440e135e 100644 --- a/Mage/src/main/java/mage/abilities/common/CastSpellPaidBySourceTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/CastSpellPaidBySourceTriggeredAbility.java @@ -71,7 +71,8 @@ public class CastSpellPaidBySourceTriggeredAbility extends TriggeredAbilityImpl if (setTargetPointer) { this.getAllEffects().setTargetPointer(new FixedTarget(spell.getId(), game)); } + this.getEffects().setValue("spellCast", spell); return true; } -} \ No newline at end of file +} diff --git a/Mage/src/main/java/mage/abilities/common/CycleTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/CycleTriggeredAbility.java index 0e08ea66c72..606b36db71c 100644 --- a/Mage/src/main/java/mage/abilities/common/CycleTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/CycleTriggeredAbility.java @@ -6,6 +6,7 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.stack.StackObject; +import mage.util.CardUtil; /** * @author Plopman @@ -40,6 +41,7 @@ public class CycleTriggeredAbility extends ZoneChangeTriggeredAbility { return false; } this.getEffects().setValue("cycleCosts", object.getStackAbility().getCosts()); + this.getEffects().setValue("cycleXValue", CardUtil.getSourceCostsTag(game, object.getStackAbility(), "X", 0)); return true; } diff --git a/Mage/src/main/java/mage/abilities/common/DiesCreatureTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DiesCreatureTriggeredAbility.java index 7df6846dc67..30e3b9c6e58 100644 --- a/Mage/src/main/java/mage/abilities/common/DiesCreatureTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/DiesCreatureTriggeredAbility.java @@ -12,6 +12,7 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.target.targetpointer.FixedTarget; +import mage.util.CardUtil; /** * @author North @@ -52,12 +53,13 @@ public class DiesCreatureTriggeredAbility extends TriggeredAbilityImpl { public DiesCreatureTriggeredAbility(Zone zone, Effect effect, boolean optional, FilterPermanent filter, boolean setTargetPointer) { this(zone, effect, optional, filter, (setTargetPointer ? SetTargetPointer.PERMANENT : SetTargetPointer.NONE)); } + public DiesCreatureTriggeredAbility(Zone zone, Effect effect, boolean optional, FilterPermanent filter, SetTargetPointer setTargetPointer) { super(zone, effect, optional); this.filter = filter; this.setTargetPointer = setTargetPointer; setLeavesTheBattlefieldTrigger(true); - setTriggerPhrase("Whenever " + filter.getMessage() + (filter.getMessage().startsWith("one or more") ? " die, " : " dies, ")); + setTriggerPhrase("Whenever " + CardUtil.addArticle(filter.getMessage()) + (filter.getMessage().startsWith("one or more") ? " die, " : " dies, ")); } protected DiesCreatureTriggeredAbility(final DiesCreatureTriggeredAbility ability) { diff --git a/Mage/src/main/java/mage/abilities/common/DiscardedByOpponentTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DiscardedByOpponentTriggeredAbility.java index 0d86a1058c2..dbbd43d354e 100644 --- a/Mage/src/main/java/mage/abilities/common/DiscardedByOpponentTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/DiscardedByOpponentTriggeredAbility.java @@ -14,7 +14,7 @@ public class DiscardedByOpponentTriggeredAbility extends TriggeredAbilityImpl { public DiscardedByOpponentTriggeredAbility(Effect effect) { super(Zone.GRAVEYARD, effect, false); - setTriggerPhrase("When a spell or ability an opponent controls causes you to discard this card"); + setTriggerPhrase("When a spell or ability an opponent controls causes you to discard this card, "); } protected DiscardedByOpponentTriggeredAbility(final DiscardedByOpponentTriggeredAbility ability) { diff --git a/Mage/src/main/java/mage/abilities/common/EndOfCombatTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/EndOfCombatTriggeredAbility.java index a6d36c6fa6a..b09494c8ef7 100644 --- a/Mage/src/main/java/mage/abilities/common/EndOfCombatTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/EndOfCombatTriggeredAbility.java @@ -40,7 +40,7 @@ public class EndOfCombatTriggeredAbility extends AtStepTriggeredAbility { case ANY: return "At end of combat, "; case YOU: - return "At the end of combat on your turn, "; + return "At end of combat on your turn, "; default: throw new UnsupportedOperationException("Unsupported TargetController in EndOfCombatTriggeredAbility: " + targetController); } diff --git a/Mage/src/main/java/mage/abilities/common/EntersBattlefieldAllTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/EntersBattlefieldAllTriggeredAbility.java index b01369d0766..8f7b39b603a 100644 --- a/Mage/src/main/java/mage/abilities/common/EntersBattlefieldAllTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/EntersBattlefieldAllTriggeredAbility.java @@ -76,8 +76,9 @@ public class EntersBattlefieldAllTriggeredAbility extends TriggeredAbilityImpl { String filterMessage = filter.getMessage(); if (filterMessage.startsWith("one or more")) { setTriggerPhrase(getWhen() + filterMessage + " enter, "); + } else { + setTriggerPhrase(getWhen() + CardUtil.addArticle(filterMessage) + " enters, "); } - setTriggerPhrase(getWhen() + CardUtil.addArticle(filterMessage) + " enters, "); } @Override diff --git a/Mage/src/main/java/mage/abilities/common/EntersBattlefieldAttachToTarget.java b/Mage/src/main/java/mage/abilities/common/EntersBattlefieldAttachToTarget.java index d2f45004c13..3c3195d00d8 100644 --- a/Mage/src/main/java/mage/abilities/common/EntersBattlefieldAttachToTarget.java +++ b/Mage/src/main/java/mage/abilities/common/EntersBattlefieldAttachToTarget.java @@ -16,7 +16,8 @@ public class EntersBattlefieldAttachToTarget extends EntersBattlefieldTriggeredA } public EntersBattlefieldAttachToTarget(FilterPermanent filter) { - super(new AttachEffect(Outcome.BoostCreature, "attach it to target " + filter.getMessage())); + super(new AttachEffect(Outcome.BoostCreature, "attach {this} to target " + filter.getMessage())); + this.withRuleTextReplacement(true); // default "it" but a few exceptions this.addTarget(new TargetPermanent(filter)); } diff --git a/Mage/src/main/java/mage/abilities/common/OnEventTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/OnEventTriggeredAbility.java deleted file mode 100644 index a0f648c5643..00000000000 --- a/Mage/src/main/java/mage/abilities/common/OnEventTriggeredAbility.java +++ /dev/null @@ -1,62 +0,0 @@ - -package mage.abilities.common; - -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.Effect; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; - -/** - * @author BetaSteward_at_googlemail.com - */ -public class OnEventTriggeredAbility extends TriggeredAbilityImpl { - - private final EventType eventType; - private final String eventName; - private final boolean allPlayers; - - public OnEventTriggeredAbility(EventType eventType, String eventName, Effect effect) { - this(eventType, eventName, effect, false); - } - - public OnEventTriggeredAbility(EventType eventType, String eventName, Effect effect, boolean optional) { - this(eventType, eventName, false, effect, optional); - } - - public OnEventTriggeredAbility(EventType eventType, String eventName, boolean allPlayers, Effect effect) { - this(eventType, eventName, allPlayers, effect, false); - } - - public OnEventTriggeredAbility(EventType eventType, String eventName, boolean allPlayers, Effect effect, boolean optional) { - super(Zone.BATTLEFIELD, effect, optional); - this.eventType = eventType; - this.eventName = eventName; - this.allPlayers = allPlayers; - setTriggerPhrase("At the " + eventName + ", "); - } - - protected OnEventTriggeredAbility(final OnEventTriggeredAbility ability) { - super(ability); - this.eventType = ability.eventType; - this.eventName = ability.eventName; - this.allPlayers = ability.allPlayers; - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == eventType; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return allPlayers || event.getPlayerId().equals(this.controllerId); - } - - @Override - public OnEventTriggeredAbility copy() { - return new OnEventTriggeredAbility(this); - } - -} diff --git a/Mage/src/main/java/mage/abilities/common/OpponentPlaysLandTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/OpponentPlaysLandTriggeredAbility.java index bbd90879091..9f702612c74 100644 --- a/Mage/src/main/java/mage/abilities/common/OpponentPlaysLandTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/OpponentPlaysLandTriggeredAbility.java @@ -12,7 +12,11 @@ import mage.game.permanent.Permanent; */ public class OpponentPlaysLandTriggeredAbility extends TriggeredAbilityImpl { - public OpponentPlaysLandTriggeredAbility(Zone zone, Effect effect, Boolean optional) { + public OpponentPlaysLandTriggeredAbility(Effect effect, boolean optional) { + this(Zone.BATTLEFIELD, effect, optional); + } + + public OpponentPlaysLandTriggeredAbility(Zone zone, Effect effect, boolean optional) { super(zone, effect, optional); setTriggerPhrase("Whenever an opponent plays a land, "); } diff --git a/Mage/src/main/java/mage/abilities/common/PutIntoGraveFromBattlefieldAllTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/PutIntoGraveFromBattlefieldAllTriggeredAbility.java index e798718f028..a0d5ac75c7a 100644 --- a/Mage/src/main/java/mage/abilities/common/PutIntoGraveFromBattlefieldAllTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/PutIntoGraveFromBattlefieldAllTriggeredAbility.java @@ -10,6 +10,7 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.target.targetpointer.FixedTarget; +import mage.util.CardUtil; /** * @author LevelX2 @@ -30,7 +31,7 @@ public class PutIntoGraveFromBattlefieldAllTriggeredAbility extends TriggeredAbi this.filter = filter; this.onlyToControllerGraveyard = onlyToControllerGraveyard; this.setTargetPointer = setTargetPointer; - setTriggerPhrase("Whenever " + filter.getMessage() + " is put into " + + setTriggerPhrase("Whenever " + CardUtil.addArticle(filter.getMessage()) + " is put into " + (onlyToControllerGraveyard ? "your" : "a") + " graveyard, "); } diff --git a/Mage/src/main/java/mage/abilities/common/SanctuaryInterveningIfTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/SanctuaryTriggeredAbility.java similarity index 53% rename from Mage/src/main/java/mage/abilities/common/SanctuaryInterveningIfTriggeredAbility.java rename to Mage/src/main/java/mage/abilities/common/SanctuaryTriggeredAbility.java index 450811e56c1..f91dd75d01c 100644 --- a/Mage/src/main/java/mage/abilities/common/SanctuaryInterveningIfTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/SanctuaryTriggeredAbility.java @@ -1,14 +1,10 @@ - package mage.abilities.common; import mage.ObjectColor; -import mage.abilities.TriggeredAbility; import mage.abilities.condition.CompoundCondition; import mage.abilities.condition.Condition; -import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.decorator.ConditionalOneShotEffect; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.filter.FilterPermanent; @@ -18,10 +14,10 @@ import mage.filter.predicate.mageobject.ColorPredicate; /** * @author TheElk801 */ -public class SanctuaryInterveningIfTriggeredAbility extends ConditionalInterveningIfTriggeredAbility { +public class SanctuaryTriggeredAbility extends BeginningOfUpkeepTriggeredAbility { private static Condition makeOrCondition(ObjectColor color1, ObjectColor color2) { - FilterPermanent filter = new FilterPermanent(); + FilterPermanent filter = new FilterPermanent("you control a " + color1.getDescription() + " or " + color2.getDescription() + " permanent"); filter.add(Predicates.or( new ColorPredicate(color1), new ColorPredicate(color2) @@ -39,24 +35,17 @@ public class SanctuaryInterveningIfTriggeredAbility extends ConditionalInterveni return new CompoundCondition(condition1, condition2); } - private static TriggeredAbility makeTrigger(OneShotEffect effect1, OneShotEffect effect2, ObjectColor color1, ObjectColor color2) { - TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility( - new ConditionalOneShotEffect(effect1, new InvertCondition(makeAndCondition(color1, color2))) - ); - ability.addEffect(new ConditionalOneShotEffect(effect2, makeAndCondition(color1, color2))); - return ability; + public SanctuaryTriggeredAbility(OneShotEffect effect1, OneShotEffect effect2, ObjectColor color1, ObjectColor color2, String text) { + super(new ConditionalOneShotEffect(effect2, effect1, makeAndCondition(color1, color2), text)); + this.withInterveningIf(makeOrCondition(color1, color2)); } - public SanctuaryInterveningIfTriggeredAbility(OneShotEffect effect1, OneShotEffect effect2, ObjectColor color1, ObjectColor color2, String text) { - super(makeTrigger(effect1, effect2, color1, color2), makeOrCondition(color1, color2), text); - } - - protected SanctuaryInterveningIfTriggeredAbility(final SanctuaryInterveningIfTriggeredAbility ability) { + protected SanctuaryTriggeredAbility(final SanctuaryTriggeredAbility ability) { super(ability); } @Override - public SanctuaryInterveningIfTriggeredAbility copy() { - return new SanctuaryInterveningIfTriggeredAbility(this); + public SanctuaryTriggeredAbility copy() { + return new SanctuaryTriggeredAbility(this); } } diff --git a/Mage/src/main/java/mage/abilities/common/SourceDealsNoncombatDamageToOpponentTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/SourceDealsNoncombatDamageToOpponentTriggeredAbility.java new file mode 100644 index 00000000000..198412dccff --- /dev/null +++ b/Mage/src/main/java/mage/abilities/common/SourceDealsNoncombatDamageToOpponentTriggeredAbility.java @@ -0,0 +1,66 @@ +package mage.abilities.common; + +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.constants.SetTargetPointer; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; + +/** + * @author notgreat + */ +public class SourceDealsNoncombatDamageToOpponentTriggeredAbility extends TriggeredAbilityImpl { + SetTargetPointer setTargetPointer; + + public SourceDealsNoncombatDamageToOpponentTriggeredAbility(Effect effect) { + this(effect, SetTargetPointer.NONE); + } + public SourceDealsNoncombatDamageToOpponentTriggeredAbility(Effect effect, SetTargetPointer setTargetPointer) { + this(effect, false, setTargetPointer); + } + + public SourceDealsNoncombatDamageToOpponentTriggeredAbility(Effect effect, boolean optional, SetTargetPointer setTargetPointer) { + super(Zone.BATTLEFIELD, effect, optional); + this.setTargetPointer = setTargetPointer; + setTriggerPhrase("Whenever a source you control deals noncombat damage to an opponent, "); + } + + protected SourceDealsNoncombatDamageToOpponentTriggeredAbility(final SourceDealsNoncombatDamageToOpponentTriggeredAbility ability) { + super(ability); + setTargetPointer = ability.setTargetPointer; + } + + @Override + public SourceDealsNoncombatDamageToOpponentTriggeredAbility copy() { + return new SourceDealsNoncombatDamageToOpponentTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Player opponent = game.getPlayer(event.getTargetId()); + DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event; + if (opponent == null || !game.isOpponent(opponent, getControllerId()) + || !isControlledBy(game.getControllerId(event.getSourceId())) + || damageEvent.isCombatDamage()) { + return false; + } + int damageAmount = event.getAmount(); + if (damageAmount < 1) { + return false; + } + this.getEffects().setValue("damage", damageAmount); + if (setTargetPointer == SetTargetPointer.PLAYER) { + getEffects().setTargetPointer(new FixedTarget(event.getSourceId())); + } + return true; + } +} diff --git a/Mage/src/main/java/mage/abilities/condition/common/AddendumCondition.java b/Mage/src/main/java/mage/abilities/condition/common/AddendumCondition.java index 81324372212..b5c3c8d0131 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/AddendumCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/AddendumCondition.java @@ -27,4 +27,9 @@ public enum AddendumCondition implements Condition { Spell spell = game.getSpell(source.getSourceId()); return spell != null && !spell.isCopy(); // copies are not casted } + + @Override + public String toString() { + return "you cast it during your main phase"; + } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/AttackedPlayersPoisonedCondition.java b/Mage/src/main/java/mage/abilities/condition/common/AttackedPlayersPoisonedCondition.java deleted file mode 100644 index aa6cf7b4315..00000000000 --- a/Mage/src/main/java/mage/abilities/condition/common/AttackedPlayersPoisonedCondition.java +++ /dev/null @@ -1,37 +0,0 @@ -package mage.abilities.condition.common; - -import mage.abilities.Ability; -import mage.abilities.condition.Condition; -import mage.counters.CounterType; -import mage.game.Game; -import mage.game.combat.CombatGroup; - -import java.util.Objects; - -/** - * A condition which checks whether any players being attacked are poisoned - * (have one or more poison counters on them) - * - * @author alexander-novo - */ -public enum AttackedPlayersPoisonedCondition implements Condition { - instance; - - @Override - public boolean apply(Game game, Ability source) { - return game.getCombat() - .getGroups() - .stream() - .map(CombatGroup::getDefenderId) - .filter(Objects::nonNull) - .distinct() - .map(game::getPlayer) - .filter(Objects::nonNull) - .anyMatch(player -> player.getCountersCount(CounterType.POISON) > 0); - } - - @Override - public String toString() { - return "one or more players being attacked are poisoned"; - } -} diff --git a/Mage/src/main/java/mage/abilities/condition/common/CollectedEvidenceCondition.java b/Mage/src/main/java/mage/abilities/condition/common/CollectedEvidenceCondition.java index 377e456eeaf..21e1aa9e1e4 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/CollectedEvidenceCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/CollectedEvidenceCondition.java @@ -21,7 +21,6 @@ public enum CollectedEvidenceCondition implements Condition { @Override public String toString() { - // must use "used" instead "collected" because it can be visible as card hint on stack before real collect - return "Evidence was used"; + return "evidence was collected"; } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/DrewTwoOrMoreCardsCondition.java b/Mage/src/main/java/mage/abilities/condition/common/DrewTwoOrMoreCardsCondition.java index fb5fd5ceef3..f457ff9dc4a 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/DrewTwoOrMoreCardsCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/DrewTwoOrMoreCardsCondition.java @@ -19,6 +19,6 @@ public enum DrewTwoOrMoreCardsCondition implements Condition { @Override public String toString() { - return "you've drawn two or more cards this turn"; + return "you've drawn more than one card this turn"; } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/EnchantedSourceCondition.java b/Mage/src/main/java/mage/abilities/condition/common/EnchantedSourceCondition.java index 28e4fb3db24..4921b46aa38 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/EnchantedSourceCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/EnchantedSourceCondition.java @@ -7,6 +7,7 @@ import mage.constants.ComparisonType; import mage.constants.SubType; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.util.CardUtil; import java.util.UUID; @@ -50,6 +51,6 @@ public class EnchantedSourceCondition implements Condition { @Override public String toString() { - return "{this} is enchanted"; + return "{this} is enchanted" + (numberOfEnchantments > 1 ? " by " + CardUtil.numberToText(numberOfEnchantments) + " or more Auras" : ""); } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/HaveInitiativeCondition.java b/Mage/src/main/java/mage/abilities/condition/common/HaveInitiativeCondition.java index 1110482c5a9..0a813233b2f 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/HaveInitiativeCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/HaveInitiativeCondition.java @@ -17,6 +17,6 @@ public enum HaveInitiativeCondition implements Condition { @Override public String toString() { - return "if you have the initiative"; + return "you have the initiative"; } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/IsStepCondition.java b/Mage/src/main/java/mage/abilities/condition/common/IsStepCondition.java index ad4387727fd..e347ed79e1a 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/IsStepCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/IsStepCondition.java @@ -7,13 +7,17 @@ import mage.constants.PhaseStep; import mage.game.Game; /** - * * @author LevelX2 */ public class IsStepCondition implements Condition { protected PhaseStep phaseStep; protected boolean onlyDuringYourSteps; + private static final IsStepCondition myUpkeep = new IsStepCondition(PhaseStep.UPKEEP, true); + + public static IsStepCondition getMyUpkeep() { + return myUpkeep; + } public IsStepCondition(PhaseStep phaseStep) { this(phaseStep, true); diff --git a/Mage/src/main/java/mage/abilities/condition/common/LandfallCondition.java b/Mage/src/main/java/mage/abilities/condition/common/LandfallCondition.java index 2b6d991c540..a91b10c6d09 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/LandfallCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/LandfallCondition.java @@ -16,4 +16,9 @@ public enum LandfallCondition implements Condition { LandfallWatcher watcher = game.getState().getWatcher(LandfallWatcher.class); return watcher != null && watcher.landPlayed(source.getControllerId()); } + + @Override + public String toString() { + return "you had a land enter the battlefield under your control this turn"; + } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/LifeCompareCondition.java b/Mage/src/main/java/mage/abilities/condition/common/LifeCompareCondition.java index 76be7c9ad27..66b7158a4e7 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/LifeCompareCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/LifeCompareCondition.java @@ -8,6 +8,7 @@ import mage.game.Game; import mage.players.Player; import java.util.Objects; +import java.util.Optional; /** * @author xenohedron @@ -20,9 +21,10 @@ public class LifeCompareCondition implements Condition { /** * "As long as [player] has [number] or [more/less] life" + * * @param targetController YOU, OPPONENT, ANY, EACH_PLAYER - * @param comparisonType comparison operator - * @param amount life threshold + * @param comparisonType comparison operator + * @param amount life threshold */ public LifeCompareCondition(TargetController targetController, ComparisonType comparisonType, int amount) { this.targetController = targetController; @@ -40,7 +42,8 @@ public class LifeCompareCondition implements Condition { case YOU: return ComparisonType.compare(controller.getLife(), comparisonType, amount); case OPPONENT: - return game.getOpponents(controller.getId()) + return game + .getOpponents(controller.getId()) .stream() .map(game::getPlayer) .filter(Objects::nonNull) @@ -48,7 +51,9 @@ public class LifeCompareCondition implements Condition { .map(Player::getLife) .anyMatch(l -> ComparisonType.compare(l, comparisonType, amount)); case ANY: - return game.getState().getPlayersInRange(controller.getId(), game) + return game + .getState() + .getPlayersInRange(controller.getId(), game) .stream() .map(game::getPlayer) .filter(Objects::nonNull) @@ -56,13 +61,23 @@ public class LifeCompareCondition implements Condition { .map(Player::getLife) .anyMatch(l -> ComparisonType.compare(l, comparisonType, amount)); case EACH_PLAYER: - return game.getState().getPlayersInRange(controller.getId(), game) + return game + .getState() + .getPlayersInRange(controller.getId(), game) .stream() .map(game::getPlayer) .filter(Objects::nonNull) .filter(Player::isInGame) .map(Player::getLife) .allMatch(l -> ComparisonType.compare(l, comparisonType, amount)); + case ACTIVE: + return Optional + .ofNullable(game) + .map(Game::getActivePlayerId) + .map(game::getPlayer) + .map(Player::getLife) + .filter(l -> ComparisonType.compare(l, comparisonType, amount)) + .isPresent(); default: throw new IllegalArgumentException("Unsupported TargetController in LifeCompareCondition: " + targetController); } @@ -84,27 +99,30 @@ public class LifeCompareCondition implements Condition { case EACH_PLAYER: sb.append("each player has "); break; + case ACTIVE: + sb.append("that player has "); + break; default: throw new IllegalArgumentException("Unsupported TargetController in LifeCompareCondition: " + targetController); } switch (comparisonType) { - case MORE_THAN: - sb.append("more than ").append(amount); - break; - case FEWER_THAN: - sb.append("less than ").append(amount); - break; - case EQUAL_TO: - sb.append("exactly ").append(amount); - break; - case OR_GREATER: - sb.append(amount).append(" or more"); - break; - case OR_LESS: - sb.append(amount).append(" or less"); - break; - default: - throw new IllegalArgumentException("Unsupported ComparisonType in LifeCompareCondition: " + comparisonType); + case MORE_THAN: + sb.append("more than ").append(amount); + break; + case FEWER_THAN: + sb.append("less than ").append(amount); + break; + case EQUAL_TO: + sb.append("exactly ").append(amount); + break; + case OR_GREATER: + sb.append(amount).append(" or more"); + break; + case OR_LESS: + sb.append(amount).append(" or less"); + break; + default: + throw new IllegalArgumentException("Unsupported ComparisonType in LifeCompareCondition: " + comparisonType); } sb.append(" life"); return sb.toString(); diff --git a/Mage/src/main/java/mage/abilities/condition/common/LiveLostLastTurnCondition.java b/Mage/src/main/java/mage/abilities/condition/common/LiveLostLastTurnCondition.java index fc625230ab8..fde812b4aab 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/LiveLostLastTurnCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/LiveLostLastTurnCondition.java @@ -1,28 +1,24 @@ - package mage.abilities.condition.common; import mage.abilities.Ability; import mage.abilities.condition.Condition; import mage.game.Game; -import mage.watchers.WatcherUtils; import mage.watchers.common.PlayerLostLifeWatcher; /** - * * @author LevelX */ public enum LiveLostLastTurnCondition implements Condition { - instance; @Override public boolean apply(Game game, Ability source) { PlayerLostLifeWatcher watcher = game.getState().getWatcher(PlayerLostLifeWatcher.class); - if (watcher != null) { - return watcher.getLifeLostLastTurn(source.getControllerId()) > 0; - } else { - WatcherUtils.logMissingWatcher(game, source, PlayerLostLifeWatcher.class, this.getClass()); - } - return false; + return watcher != null && watcher.getLifeLostLastTurn(source.getControllerId()) > 0; + } + + @Override + public String toString() { + return "you lost life last turn"; } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/MonarchIsNotSetCondition.java b/Mage/src/main/java/mage/abilities/condition/common/MonarchIsNotSetCondition.java index f489ddfa2e9..e46e06afac8 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/MonarchIsNotSetCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/MonarchIsNotSetCondition.java @@ -1,4 +1,3 @@ - package mage.abilities.condition.common; import mage.abilities.Ability; @@ -19,6 +18,6 @@ public enum MonarchIsNotSetCondition implements Condition { @Override public String toString() { - return "if there is no monarch"; + return "there is no monarch"; } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/MonstrousCondition.java b/Mage/src/main/java/mage/abilities/condition/common/MonstrousCondition.java index d52277a8171..5723bee4556 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/MonstrousCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/MonstrousCondition.java @@ -1,5 +1,3 @@ - - package mage.abilities.condition.common; import mage.abilities.Ability; @@ -7,21 +5,22 @@ import mage.abilities.condition.Condition; import mage.game.Game; import mage.game.permanent.Permanent; - /** * Checks if a Permanent is monstrous * * @author LevelX2 */ public enum MonstrousCondition implements Condition { - instance; + @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - return permanent.isMonstrous(); - } - return false; + return permanent != null && permanent.isMonstrous(); + } + + @Override + public String toString() { + return "{this} is monstrous"; } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/OpponentHasMoreLifeCondition.java b/Mage/src/main/java/mage/abilities/condition/common/OpponentHasMoreLifeCondition.java index 5ea4d9a6131..d4db69c9a0e 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/OpponentHasMoreLifeCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/OpponentHasMoreLifeCondition.java @@ -1,5 +1,3 @@ - - package mage.abilities.condition.common; import mage.abilities.Ability; @@ -10,25 +8,23 @@ import mage.players.Player; import java.util.UUID; /** - * * @author fireshoes */ public enum OpponentHasMoreLifeCondition implements Condition { instance; - + @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - for (UUID uuid : game.getOpponents(controller.getId())) { - Player opponent = game.getPlayer(uuid); - if (opponent != null) { - if (opponent.getLife() > controller.getLife()) { - return true; - } - } + if (controller == null) { + return false; + } + for (UUID uuid : game.getOpponents(controller.getId())) { + Player opponent = game.getPlayer(uuid); + if (opponent != null && opponent.getLife() > controller.getLife()) { + return true; } } return false; diff --git a/Mage/src/main/java/mage/abilities/condition/common/RenownedSourceCondition.java b/Mage/src/main/java/mage/abilities/condition/common/RenownedSourceCondition.java index 3b49012cfef..03af32c71d4 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/RenownedSourceCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/RenownedSourceCondition.java @@ -6,27 +6,32 @@ import mage.game.Game; import mage.game.permanent.Permanent; /** - * Checks if a Permanent is renown + * Checks if a Permanent is renowned * * @author LevelX2 */ public enum RenownedSourceCondition implements Condition { - instance; + THIS("{this} is"), + ITS("it's"); + private final String name; + + RenownedSourceCondition(String name) { + this.name = name; + } + @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { - return permanent.isRenowned(); + return permanent.isRenowned(); } return false; } @Override public String toString() { - return "it's renowned"; + return name + " renowned"; } - - -} \ No newline at end of file +} diff --git a/Mage/src/main/java/mage/abilities/condition/common/RevealedOrControlledDragonCondition.java b/Mage/src/main/java/mage/abilities/condition/common/RevealedOrControlledDragonCondition.java index 8658e5897bf..c13f4a2f6fc 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/RevealedOrControlledDragonCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/RevealedOrControlledDragonCondition.java @@ -27,4 +27,9 @@ public enum RevealedOrControlledDragonCondition implements Condition { = game.getState().getWatcher(DragonOnTheBattlefieldWhileSpellWasCastWatcher.class); return watcher != null && watcher.checkCondition(source, game); } + + @Override + public String toString() { + return "you revealed a Dragon card or controlled a Dragon as you cast this spell"; + } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/SourceAttackingPlayerWithMostLifeCondition.java b/Mage/src/main/java/mage/abilities/condition/common/SourceAttackingPlayerWithMostLifeCondition.java index 7d066f2e29b..d2e2639c92d 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/SourceAttackingPlayerWithMostLifeCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/SourceAttackingPlayerWithMostLifeCondition.java @@ -31,6 +31,6 @@ public enum SourceAttackingPlayerWithMostLifeCondition implements Condition { @Override public String toString() { - return "{this} is attacking the player with the most life or tied for most life"; + return "it's attacking the player with the most life or tied for most life"; } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/SourceEnteredThisTurnCondition.java b/Mage/src/main/java/mage/abilities/condition/common/SourceEnteredThisTurnCondition.java index 2ff18a230b8..8007d430b84 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/SourceEnteredThisTurnCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/SourceEnteredThisTurnCondition.java @@ -25,6 +25,6 @@ public enum SourceEnteredThisTurnCondition implements Condition { @Override public String toString() { - return "{this} " + (flag ? "entered" : "didn't enter") + " the battlefield this turn"; + return "{this} " + (flag ? "entered" : "didn't enter the battlefield") + " this turn"; } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/SourceInExileCondition.java b/Mage/src/main/java/mage/abilities/condition/common/SourceInExileCondition.java index 0625f697a11..7570560e115 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/SourceInExileCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/SourceInExileCondition.java @@ -10,7 +10,6 @@ import mage.game.Game; * * @author Susucr */ - public enum SourceInExileCondition implements Condition { instance; @@ -18,4 +17,9 @@ public enum SourceInExileCondition implements Condition { public boolean apply(Game game, Ability source) { return game.getState().getZone(source.getSourceId()) == Zone.EXILED; } + + @Override + public String toString() { + return "this card is exiled"; + } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/SourceIsEnchantmentCondition.java b/Mage/src/main/java/mage/abilities/condition/common/SourceIsEnchantmentCondition.java new file mode 100644 index 00000000000..246308b6e59 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/condition/common/SourceIsEnchantmentCondition.java @@ -0,0 +1,27 @@ +package mage.abilities.condition.common; + +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.game.Game; + +import java.util.Optional; + +/** + * @author TheElk801 + */ +public enum SourceIsEnchantmentCondition implements Condition { + instance; + + @Override + public boolean apply(Game game, Ability source) { + return Optional + .ofNullable(source.getSourcePermanentOrLKI(game)) + .filter(permanent -> permanent.isEnchantment(game)) + .isPresent(); + } + + @Override + public String toString() { + return "this permanent is an enchantment"; + } +} diff --git a/Mage/src/main/java/mage/abilities/condition/common/SourceOnBattlefieldCondition.java b/Mage/src/main/java/mage/abilities/condition/common/SourceOnBattlefieldCondition.java index d5b042add5b..81d0170a292 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/SourceOnBattlefieldCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/SourceOnBattlefieldCondition.java @@ -20,6 +20,6 @@ public enum SourceOnBattlefieldCondition implements Condition { @Override public String toString() { - return "if {this} is on the battlefield"; + return "{this} is on the battlefield"; } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/SpectacleCondition.java b/Mage/src/main/java/mage/abilities/condition/common/SpectacleCondition.java index 5a9370e416b..d97499b4024 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/SpectacleCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/SpectacleCondition.java @@ -1,4 +1,3 @@ - package mage.abilities.condition.common; import mage.abilities.Ability; @@ -11,11 +10,15 @@ import mage.util.CardUtil; * @author TheElk801 */ public enum SpectacleCondition implements Condition { - instance; @Override public boolean apply(Game game, Ability source) { return CardUtil.checkSourceCostsTagExists(game, source, SpectacleAbility.SPECTACLE_ACTIVATION_VALUE_KEY); } + + @Override + public String toString() { + return "its spectacle cost was paid"; + } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/SurgedCondition.java b/Mage/src/main/java/mage/abilities/condition/common/SurgedCondition.java index 8b65ebdc690..6ded9090265 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/SurgedCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/SurgedCondition.java @@ -1,4 +1,3 @@ - package mage.abilities.condition.common; import mage.abilities.Ability; @@ -8,15 +7,18 @@ import mage.game.Game; import mage.util.CardUtil; /** - * * @author LevelX2 */ public enum SurgedCondition implements Condition { - instance; @Override public boolean apply(Game game, Ability source) { return CardUtil.checkSourceCostsTagExists(game, source, SurgeAbility.SURGE_ACTIVATION_VALUE_KEY); } + + @Override + public String toString() { + return "its surge cost was paid"; + } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/SuspendedCondition.java b/Mage/src/main/java/mage/abilities/condition/common/SuspendedCondition.java index 83dcaad3e73..06bb40c33ce 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/SuspendedCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/SuspendedCondition.java @@ -43,7 +43,6 @@ public enum SuspendedCondition implements Condition { @Override public String toString() { - return "{this} is suspended"; + return "this card is suspended"; } - } diff --git a/Mage/src/main/java/mage/abilities/condition/common/TreasureSpentToCastCondition.java b/Mage/src/main/java/mage/abilities/condition/common/TreasureSpentToCastCondition.java index 11035124bda..f598aef57d2 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/TreasureSpentToCastCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/TreasureSpentToCastCondition.java @@ -19,4 +19,9 @@ public enum TreasureSpentToCastCondition implements Condition { } return ManaPaidSourceWatcher.getTreasurePaid(source.getSourceId(), game) > 0; } + + @Override + public String toString() { + return "mana from a Treasure was spent to cast it"; + } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/TributeNotPaidCondition.java b/Mage/src/main/java/mage/abilities/condition/common/TributeNotPaidCondition.java index b6da7a564fd..1c972e33416 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/TributeNotPaidCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/TributeNotPaidCondition.java @@ -1,4 +1,3 @@ - package mage.abilities.condition.common; import mage.abilities.Ability; @@ -11,8 +10,7 @@ import mage.game.Game; * @author LevelX2 */ public enum TributeNotPaidCondition implements Condition { - - instance; + instance; @Override public boolean apply(Game game, Ability source) { @@ -22,4 +20,9 @@ public enum TributeNotPaidCondition implements Condition { } return false; } + + @Override + public String toString() { + return "tribute wasn't paid"; + } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/YouControlTwoOrMoreGatesCondition.java b/Mage/src/main/java/mage/abilities/condition/common/YouControlTwoOrMoreGatesCondition.java new file mode 100644 index 00000000000..73b5f2517d8 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/condition/common/YouControlTwoOrMoreGatesCondition.java @@ -0,0 +1,26 @@ +package mage.abilities.condition.common; + +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.game.Game; + +/** + * @author TheElk801 + */ +public enum YouControlTwoOrMoreGatesCondition implements Condition { + instance; + private static final FilterPermanent filter = new FilterControlledPermanent(SubType.GATE); + + @Override + public boolean apply(Game game, Ability source) { + return game.getBattlefield().count(filter, source.getControllerId(), source, game) >= 2; + } + + @Override + public String toString() { + return "you control two or more Gates"; + } +} diff --git a/Mage/src/main/java/mage/abilities/costs/common/TapTargetCost.java b/Mage/src/main/java/mage/abilities/costs/common/TapTargetCost.java index 0d8a5b77059..ea468535e43 100644 --- a/Mage/src/main/java/mage/abilities/costs/common/TapTargetCost.java +++ b/Mage/src/main/java/mage/abilities/costs/common/TapTargetCost.java @@ -4,6 +4,7 @@ import mage.abilities.Ability; import mage.abilities.costs.Cost; import mage.abilities.costs.CostImpl; import mage.constants.Outcome; +import mage.filter.common.FilterControlledPermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetControlledPermanent; @@ -20,6 +21,18 @@ public class TapTargetCost extends CostImpl { TargetControlledPermanent target; + public TapTargetCost(FilterControlledPermanent filter) { + this(1, filter); + } + + public TapTargetCost(int amount, FilterControlledPermanent filter) { + this(amount, amount, filter); + } + + public TapTargetCost(int minAmount, int maxAmount, FilterControlledPermanent filter) { + this(new TargetControlledPermanent(minAmount, maxAmount, filter, true)); + } + public TapTargetCost(TargetControlledPermanent target) { this.target = target; this.target.withNotTarget(true); // costs are never targeted diff --git a/Mage/src/main/java/mage/abilities/decorator/ConditionalActivatedAbility.java b/Mage/src/main/java/mage/abilities/decorator/ConditionalActivatedAbility.java deleted file mode 100644 index 6f7d8681e50..00000000000 --- a/Mage/src/main/java/mage/abilities/decorator/ConditionalActivatedAbility.java +++ /dev/null @@ -1,81 +0,0 @@ -package mage.abilities.decorator; - -import mage.abilities.ActivatedAbilityImpl; -import mage.abilities.condition.Condition; -import mage.abilities.costs.Cost; -import mage.abilities.effects.Effect; -import mage.abilities.effects.Effects; -import mage.constants.EffectType; -import mage.constants.TimingRule; -import mage.constants.Zone; -import mage.game.Game; - -/** - * @author LevelX - */ -public class ConditionalActivatedAbility extends ActivatedAbilityImpl { - - private static final Effects emptyEffects = new Effects(); - - private String ruleText = null; - private boolean showCondition = true; - - public ConditionalActivatedAbility(Effect effect, Cost cost, Condition condition) { - this(Zone.BATTLEFIELD, effect, cost, condition); - } - - public ConditionalActivatedAbility(Zone zone, Effect effect, Cost cost, Condition condition) { - super(zone, effect, cost); - this.condition = condition; - } - - public ConditionalActivatedAbility(Zone zone, Effect effect, Cost cost, Condition condition, String rule) { - this(zone, effect, cost, condition); - this.ruleText = rule; - } - - protected ConditionalActivatedAbility(final ConditionalActivatedAbility ability) { - super(ability); - this.ruleText = ability.ruleText; - this.showCondition = ability.showCondition; - } - - @Override - public Effects getEffects(Game game, EffectType effectType) { - if (!condition.apply(game, this)) { - return emptyEffects; - } - return super.getEffects(game, effectType); - } - - @Override - public ConditionalActivatedAbility copy() { - return new ConditionalActivatedAbility(this); - } - - public ConditionalActivatedAbility hideCondition() { - this.showCondition = false; - return this; - } - - @Override - public String getRule() { - if (ruleText != null && !ruleText.isEmpty()) { - return ruleText; - } - StringBuilder sb = new StringBuilder(super.getRule()); - if (showCondition) { - sb.append(" Activate only "); - if (timing == TimingRule.SORCERY) { - sb.append("as a sorcery and only "); - } - String conditionText = condition.toString(); - if (!conditionText.startsWith("during") && !conditionText.startsWith("before") && !conditionText.startsWith("if")) { - sb.append("if "); - } - sb.append(conditionText); - sb.append('.'); - } - return sb.toString(); - } -} diff --git a/Mage/src/main/java/mage/abilities/decorator/ConditionalInterveningIfTriggeredAbility.java b/Mage/src/main/java/mage/abilities/decorator/ConditionalInterveningIfTriggeredAbility.java deleted file mode 100644 index f975727ef27..00000000000 --- a/Mage/src/main/java/mage/abilities/decorator/ConditionalInterveningIfTriggeredAbility.java +++ /dev/null @@ -1,158 +0,0 @@ -package mage.abilities.decorator; - -import mage.MageObject; -import mage.abilities.Modes; -import mage.abilities.TriggeredAbility; -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.condition.Condition; -import mage.abilities.effects.Effect; -import mage.abilities.effects.Effects; -import mage.abilities.hint.Hint; -import mage.constants.EffectType; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.watchers.Watcher; - -import java.util.ArrayList; -import java.util.List; - -/** - * Adds condition to {@link mage.abilities.effects.ContinuousEffect}. Acts as - * decorator. - * - * @author nantuko - */ -public class ConditionalInterveningIfTriggeredAbility extends TriggeredAbilityImpl { - - protected TriggeredAbility ability; - protected Condition condition; - protected String abilityText; - - /** - * Triggered ability with a condition. Set the optionality for the trigger - * ability itself. - * - * @param ability - * @param condition - * @param text explicit rule text for the ability, if null or empty, the - * rule text generated by the triggered ability itself is used. - */ - public ConditionalInterveningIfTriggeredAbility(TriggeredAbility ability, Condition condition, String text) { - super(ability.getZone(), null); - if (ability.isLeavesTheBattlefieldTrigger()) { - setLeavesTheBattlefieldTrigger(true); - } - this.ability = ability; - this.condition = condition; - this.abilityText = text; - } - - protected ConditionalInterveningIfTriggeredAbility(final ConditionalInterveningIfTriggeredAbility triggered) { - super(triggered); - this.ability = triggered.ability.copy(); - this.condition = triggered.condition; - this.abilityText = triggered.abilityText; - } - - @Override - public boolean checkInterveningIfClause(Game game) { - return condition.apply(game, this); - } - - @Override - public ConditionalInterveningIfTriggeredAbility copy() { - return new ConditionalInterveningIfTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return ability.checkEventType(event, game); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - ability.setSourceId(this.getSourceId()); - ability.setControllerId(this.getControllerId()); - return ability.checkTrigger(event, game); - } - - @Override - public String getRule() { - if (abilityText == null || abilityText.isEmpty()) { - return ability.getRule(); - } - return addRulePrefix(abilityText + (abilityText.endsWith(".") || abilityText.endsWith("\"") || abilityText.endsWith(">") ? "" : ".")); - } - - @Override - public Effects getEffects() { - return ability.getEffects(); - } - - @Override - public void addEffect(Effect effect) { - ability.addEffect(effect); - } - - @Override - public Modes getModes() { - return ability.getModes(); - } - - @Override - public List getWatchers() { - return ability.getWatchers(); - } - - @Override - public void addWatcher(Watcher watcher) { - ability.addWatcher(watcher); - } - - @Override - public List getHints() { - List res = new ArrayList<>(super.getHints()); - res.addAll(ability.getHints()); - return res; - } - - @Override - public Effects getEffects(Game game, EffectType effectType) { - return ability.getEffects(game, effectType); - } - - @Override - public boolean isOptional() { - return ability.isOptional(); - } - - @Override - public void setSourceObjectZoneChangeCounter(int sourceObjectZoneChangeCounter) { - ability.setSourceObjectZoneChangeCounter(sourceObjectZoneChangeCounter); - } - - @Override - public void initSourceObjectZoneChangeCounter(Game game, boolean force) { - ability.initSourceObjectZoneChangeCounter(game, force); - } - - @Override - public int getSourceObjectZoneChangeCounter() { - return ability.getSourceObjectZoneChangeCounter(); - } - - @Override - public boolean caresAboutManaColor() { - return condition.caresAboutManaColor(); - } - - @Override - public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) { - if (isLeavesTheBattlefieldTrigger()) { - // TODO: leaves battlefield and die are not same! Is it possible make a diff logic? - return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game); - } else { - return super.isInUseableZone(game, sourceObject, event); - } - } -} diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/EffectKeyValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/EffectKeyValue.java index b3cbe5cb55d..e3671c7aafb 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/EffectKeyValue.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/EffectKeyValue.java @@ -10,36 +10,36 @@ import mage.game.Game; * @author stravant */ public class EffectKeyValue implements DynamicValue { - private String key; - private String description; + + private final String key; + private final String description; public EffectKeyValue(String key) { - this.key = key; - this.description = key; + this(key, key); } public EffectKeyValue(String key, String description) { - this(key); + this.key = key; this.description = description; } @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - return (Integer)effect.getValue(key); + return (Integer) effect.getValue(key); } @Override - public EffectKeyValue copy(){ + public EffectKeyValue copy() { return new EffectKeyValue(this.key, this.description); } @Override public String toString() { - return "equal to"; + return description; } @Override public String getMessage() { - return description; + return ""; } -} \ No newline at end of file +} diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestAmongPermanentsValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestAmongPermanentsValue.java index c800465d79c..5fa525f2808 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestAmongPermanentsValue.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestAmongPermanentsValue.java @@ -7,6 +7,7 @@ import mage.abilities.hint.Hint; import mage.abilities.hint.ValueHint; import mage.filter.FilterPermanent; import mage.filter.StaticFilters; +import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; @@ -25,6 +26,8 @@ public class GreatestAmongPermanentsValue implements DynamicValue { = new GreatestAmongPermanentsValue(Quality.Power, StaticFilters.FILTER_CONTROLLED_CREATURES); public static final GreatestAmongPermanentsValue POWER_OTHER_CONTROLLED_CREATURES = new GreatestAmongPermanentsValue(Quality.Power, StaticFilters.FILTER_OTHER_CONTROLLED_CREATURES); + public static final GreatestAmongPermanentsValue POWER_ALL_CREATURES + = new GreatestAmongPermanentsValue(Quality.Power, new FilterCreaturePermanent("creatures on the battlefield")); public static final GreatestAmongPermanentsValue TOUGHNESS_CONTROLLED_CREATURES = new GreatestAmongPermanentsValue(Quality.Toughness, StaticFilters.FILTER_CONTROLLED_CREATURES); public static final GreatestAmongPermanentsValue TOUGHNESS_OTHER_CONTROLLED_CREATURES @@ -114,4 +117,4 @@ public class GreatestAmongPermanentsValue implements DynamicValue { public Hint getHint() { return new ValueHint("Greatest " + quality.text + " among " + filter.getMessage(), this); } -} \ No newline at end of file +} diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/SavedDamageValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/SavedDamageValue.java index ac6e0cd6b8c..1753578e2a7 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/SavedDamageValue.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/SavedDamageValue.java @@ -10,7 +10,8 @@ import mage.game.Game; */ public enum SavedDamageValue implements DynamicValue { MANY("many"), - MUCH("much"); + MUCH("much"), + AMOUNT("amount of"); private final String message; diff --git a/Mage/src/main/java/mage/abilities/effects/CreateTokenCopySourceEffect.java b/Mage/src/main/java/mage/abilities/effects/CreateTokenCopySourceEffect.java index 2e8b722c0fa..deebf3897d7 100644 --- a/Mage/src/main/java/mage/abilities/effects/CreateTokenCopySourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/CreateTokenCopySourceEffect.java @@ -6,6 +6,7 @@ import mage.constants.Outcome; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.targetpointer.FixedTarget; +import mage.util.CardUtil; /** * Created by glerman on 20/6/15. @@ -27,8 +28,8 @@ public class CreateTokenCopySourceEffect extends OneShotEffect { super(Outcome.PutCreatureInPlay); this.number = copies; this.tapped = tapped; - staticText = "create " + (copies > 1 ? copies : "a") + " " + (tapped ? "tapped " : "") - + (copies > 1 ? "tokens that are" : "token that's") + " a copy of {this}"; + staticText = "create " + CardUtil.numberToText(copies, "a") + " " + (tapped ? "tapped " : "") + + (copies > 1 ? "tokens that are copies of " : "token that's a copy of ") + "{this}"; } protected CreateTokenCopySourceEffect(final CreateTokenCopySourceEffect effect) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenAttachSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenAttachSourceEffect.java index 11d45ac59f1..91eab7dae25 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenAttachSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenAttachSourceEffect.java @@ -2,11 +2,17 @@ package mage.abilities.effects.common; import mage.abilities.Ability; import mage.constants.Outcome; +import mage.filter.FilterPermanent; +import mage.filter.predicate.permanent.PermanentReferenceInCollectionPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.Token; +import mage.players.Player; +import mage.target.TargetPermanent; -import java.util.Optional; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; /** * @author weirddan455 @@ -42,22 +48,42 @@ public class CreateTokenAttachSourceEffect extends CreateTokenEffect { @Override public boolean apply(Game game, Ability source) { super.apply(game, source); - Permanent token = this - .getLastAddedTokenIds() - .stream() - .findFirst() - .map(game::getPermanent) - .orElse(null); - if (token == null || optional - && !Optional - .ofNullable(game.getPlayer(source.getControllerId())) - .map(player -> player.chooseUse( - Outcome.BoostCreature, "Attach the equipment to the token?", source, game - )) - .orElse(false)) { + Player player = game.getPlayer(source.getControllerId()); + Permanent equipment = source.getSourcePermanentIfItStillExists(game); + if (player == null + || equipment == null + || optional + && !player.chooseUse( + Outcome.BoostCreature, "Attach " + + equipment.getLogName() + " to the token?", source, game + )) { return false; } - token.addAttachment(source.getSourceId(), source, game); + List permanents = this + .getLastAddedTokenIds() + .stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + Permanent token; + switch (permanents.size()) { + case 0: + return false; + case 1: + token = permanents.get(0); + break; + default: + FilterPermanent filter = new FilterPermanent("token"); + filter.add(new PermanentReferenceInCollectionPredicate(permanents, game)); + TargetPermanent target = new TargetPermanent(filter); + target.withNotTarget(true); + target.withChooseHint("to attach to"); + player.choose(outcome, target, source, game); + token = game.getPermanent(target.getFirstTarget()); + } + if (token != null) { + token.addAttachment(source.getSourceId(), source, game); + } return true; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/GainLifeAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/GainLifeAllEffect.java new file mode 100644 index 00000000000..6f164dee867 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/GainLifeAllEffect.java @@ -0,0 +1,83 @@ +package mage.abilities.effects.common; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.game.Game; + +import java.util.Collection; +import java.util.Optional; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public class GainLifeAllEffect extends OneShotEffect { + + private final int amount; + private final TargetController targetController; + + public GainLifeAllEffect(int amount) { + this(amount, TargetController.EACH_PLAYER); + } + + public GainLifeAllEffect(int amount, TargetController targetController) { + super(Outcome.Benefit); + this.amount = amount; + this.targetController = targetController; + staticText = makeRule(amount, targetController); + } + + private GainLifeAllEffect(final GainLifeAllEffect effect) { + super(effect); + this.amount = effect.amount; + this.targetController = effect.targetController; + } + + @Override + public GainLifeAllEffect copy() { + return new GainLifeAllEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (UUID playerId : getPlayers(targetController, game, source)) { + Optional.ofNullable(playerId) + .map(game::getPlayer) + .ifPresent(player -> player.gainLife(amount, game, source)); + } + return true; + } + + private static Collection getPlayers(TargetController targetController, Game game, Ability source) { + switch (targetController) { + case ANY: + case EACH_PLAYER: + return game.getState().getPlayersInRange(source.getControllerId(), game); + case OPPONENT: + return game.getOpponents(source.getControllerId()); + default: + throw new IllegalArgumentException("TargetController " + targetController + " not supported"); + } + } + + private static String makeRule(int amount, TargetController targetController) { + StringBuilder sb = new StringBuilder("each "); + switch (targetController) { + case ANY: + case EACH_PLAYER: + sb.append("player"); + break; + case OPPONENT: + sb.append("opponent"); + break; + default: + throw new IllegalArgumentException("TargetController " + targetController + " not supported"); + } + sb.append(" gains "); + sb.append(amount); + sb.append(" life"); + return sb.toString(); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/LearnEffect.java b/Mage/src/main/java/mage/abilities/effects/common/LearnEffect.java index 907eb42bc7e..88e6399b2f9 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/LearnEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/LearnEffect.java @@ -20,12 +20,11 @@ public class LearnEffect extends OneShotEffect { filter.add(SubType.LESSON.getPredicate()); } - private static final String defaultText = "learn. (You may reveal a Lesson card you own from outside the game " + - "and put it into your hand, or discard a card to draw a card.)"; public LearnEffect() { super(Outcome.Neutral); - staticText = defaultText; + staticText = "learn. (You may reveal a Lesson card you own " + + "from outside the game and put it into your hand, or discard a card to draw a card.)"; } private LearnEffect(final LearnEffect effect) { @@ -50,8 +49,4 @@ public class LearnEffect extends OneShotEffect { public LearnEffect copy() { return new LearnEffect(this); } - - public static String getDefaultText() { - return defaultText; - } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/MeldEffect.java b/Mage/src/main/java/mage/abilities/effects/common/MeldEffect.java index 60e54932be2..0d85288b5dd 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/MeldEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/MeldEffect.java @@ -41,6 +41,7 @@ public class MeldEffect extends OneShotEffect { this.meldWithName = meldWithName; this.meldIntoName = meldIntoName; this.attacking = attacking; + this.staticText = "exile them, then meld them into " + meldIntoName; } protected MeldEffect(final MeldEffect effect) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/ReturnToBattlefieldUnderOwnerControlAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ReturnToBattlefieldUnderOwnerControlAttachedEffect.java index 163470b756d..15767c750a0 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ReturnToBattlefieldUnderOwnerControlAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ReturnToBattlefieldUnderOwnerControlAttachedEffect.java @@ -45,16 +45,14 @@ public class ReturnToBattlefieldUnderOwnerControlAttachedEffect extends OneShotE if (controller == null) { return false; } - Object object = getValue("attachedTo"); - if (object instanceof Permanent) { - Card card = game.getCard(((Permanent) object).getId()); - if (card != null) { - if (controller.moveCards(card, Zone.BATTLEFIELD, source, game, this.tapped, false, true, null)) { - return true; - } + Object attached = getValue("attachedTo"); + Object zcc = getValue("zcc"); + if (attached instanceof Permanent && zcc instanceof Integer) { + Card card = game.getCard(((Permanent) attached).getId()); + if (card != null && (int) zcc == card.getZoneChangeCounter(game)) { + return controller.moveCards(card, Zone.BATTLEFIELD, source, game, this.tapped, false, true, null); } } - return false; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/GoadTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/GoadTargetEffect.java index 4fe12b5667b..9c2619323cc 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/GoadTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/GoadTargetEffect.java @@ -25,6 +25,7 @@ public class GoadTargetEffect extends ContinuousEffectImpl { * turn of the controller of that spell or ability, that creature attacks * each combat if able and attacks a player other than that player if able. */ + public static String goadReminderText = "(Until your next turn, that creature attacks each combat if able and attacks a player other than you if able.)"; public GoadTargetEffect() { this(Duration.UntilYourNextTurn); } @@ -74,6 +75,6 @@ public class GoadTargetEffect extends ContinuousEffectImpl { return staticText; } return "goad " + getTargetPointer().describeTargets(mode.getTargets(), "that creature") - + ". (Until your next turn, that creature attacks each combat if able and attacks a player other than you if able.)"; + + ". "+goadReminderText; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAllTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAllTargetEffect.java index fd41ecea46e..2a227ac59ab 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAllTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/MustBeBlockedByAllTargetEffect.java @@ -19,7 +19,7 @@ public class MustBeBlockedByAllTargetEffect extends RequirementEffect { public MustBeBlockedByAllTargetEffect(Duration duration) { super(duration); - staticText = "All creatures able to block target creature " + + staticText = "all creatures able to block target creature " + (this.getDuration() == Duration.EndOfTurn ? "this turn " : "") + "do so"; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityControllerEffect.java index 07a75f3c492..50784744666 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityControllerEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainAbilityControllerEffect.java @@ -2,12 +2,12 @@ package mage.abilities.effects.common.continuous; +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.Duration; import mage.constants.Layer; import mage.constants.Outcome; import mage.constants.SubLayer; -import mage.abilities.Ability; -import mage.abilities.effects.ContinuousEffectImpl; import mage.game.Game; import mage.players.Player; @@ -34,7 +34,7 @@ public class GainAbilityControllerEffect extends ContinuousEffectImpl { public GainAbilityControllerEffect(Ability ability, Duration duration) { super(duration, Layer.PlayerEffects, SubLayer.NA, Outcome.AddAbility); this.ability = ability; - staticText = "You have " + ability.getRule(); + staticText = "you " + (duration == Duration.WhileOnBattlefield ? "have" : "gain") + ' ' + ability.getRule(); if (!duration.toString().isEmpty()) { staticText += ' ' + duration.toString(); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/cost/CastFromHandForFreeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/cost/CastFromHandForFreeEffect.java index 75b5b17d635..f71c5c2796d 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/cost/CastFromHandForFreeEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/cost/CastFromHandForFreeEffect.java @@ -24,7 +24,7 @@ public class CastFromHandForFreeEffect extends OneShotEffect { public CastFromHandForFreeEffect(FilterCard filter) { super(Outcome.PlayForFree); this.filter = filter; - this.staticText = "you may cast " + filter.getMessage() + " from your hand without paying its mana cost"; + this.staticText = "you may cast " + filter.getMessage() + (filter.getMessage().contains("your hand") ? "" : " from your hand") + " without paying its mana cost"; } protected CastFromHandForFreeEffect(final CastFromHandForFreeEffect effect) { @@ -35,10 +35,9 @@ public class CastFromHandForFreeEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller == null) { - return false; - } - return CardUtil.castSpellWithAttributesForFree(controller, source, game, new CardsImpl(controller.getHand()), filter); + return controller != null && CardUtil.castSpellWithAttributesForFree( + controller, source, game, new CardsImpl(controller.getHand()), filter + ); } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/common/replacement/AdditionalTriggerControlledETBReplacementEffect.java b/Mage/src/main/java/mage/abilities/effects/common/replacement/AdditionalTriggerControlledETBReplacementEffect.java index c4b4b464a24..ffa3c03b2bb 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/replacement/AdditionalTriggerControlledETBReplacementEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/replacement/AdditionalTriggerControlledETBReplacementEffect.java @@ -17,7 +17,7 @@ public class AdditionalTriggerControlledETBReplacementEffect extends Replacement public AdditionalTriggerControlledETBReplacementEffect() { super(Duration.WhileOnBattlefield, Outcome.Benefit); - staticText = "If a permanent entering the battlefield causes a triggered ability " + + staticText = "If a permanent entering causes a triggered ability " + "of a permanent you control to trigger, that ability triggers an additional time"; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/DontCauseTriggerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/DontCauseTriggerEffect.java index 55139f9daba..1cbdf35d610 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/DontCauseTriggerEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/DontCauseTriggerEffect.java @@ -41,7 +41,7 @@ public class DontCauseTriggerEffect extends ContinuousRuleModifyingEffectImpl { this.filterEntering = filterEntering; this.orDying = orDying; this.filterTriggering = filterTriggering; - staticText = filterEntering.getMessage() + " entering the battlefield" + staticText = filterEntering.getMessage() + " entering" + (orDying ? " or dying" : "") + " don't cause abilities" + (filterTriggering == null ? "" : " of " + filterTriggering.getMessage()) + " to trigger"; diff --git a/Mage/src/main/java/mage/abilities/effects/keyword/SupportEffect.java b/Mage/src/main/java/mage/abilities/effects/keyword/SupportEffect.java index 1edcde3b5b1..5d44fbe1263 100644 --- a/Mage/src/main/java/mage/abilities/effects/keyword/SupportEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/keyword/SupportEffect.java @@ -6,7 +6,6 @@ import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.cards.Card; import mage.counters.CounterType; -import mage.filter.common.FilterCreaturePermanent; import mage.target.common.TargetCreaturePermanent; import mage.util.CardUtil; @@ -23,7 +22,7 @@ public class SupportEffect extends AddCountersTargetEffect { this.amountSupportTargets = StaticValue.get(amount); this.otherPermanent = otherPermanent; if (card.isInstantOrSorcery()) { - card.getSpellAbility().addTarget(new TargetCreaturePermanent(0, amount, new FilterCreaturePermanent("target creatures"), false)); + card.getSpellAbility().addTarget(new TargetCreaturePermanent(0, amount)); } staticText = setText(); } diff --git a/Mage/src/main/java/mage/abilities/effects/mana/AddManaInAnyCombinationEffect.java b/Mage/src/main/java/mage/abilities/effects/mana/AddManaInAnyCombinationEffect.java index e81528cfa43..f65cdd8e12d 100644 --- a/Mage/src/main/java/mage/abilities/effects/mana/AddManaInAnyCombinationEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/mana/AddManaInAnyCombinationEffect.java @@ -150,7 +150,7 @@ public class AddManaInAnyCombinationEffect extends ManaEffect { } private String setText() { - StringBuilder sb = new StringBuilder("Add "); + StringBuilder sb = new StringBuilder("add "); String amountString = CardUtil.numberToText(amount.toString()); sb.append(amountString); sb.append(" mana in any combination of "); diff --git a/Mage/src/main/java/mage/abilities/hint/common/EvidenceHint.java b/Mage/src/main/java/mage/abilities/hint/common/EvidenceHint.java index 046f54d737f..e52a025871c 100644 --- a/Mage/src/main/java/mage/abilities/hint/common/EvidenceHint.java +++ b/Mage/src/main/java/mage/abilities/hint/common/EvidenceHint.java @@ -14,7 +14,7 @@ public class EvidenceHint extends ConditionHint { private final int needAmount; public EvidenceHint(int needAmount) { - super(CollectedEvidenceCondition.instance); + super(CollectedEvidenceCondition.instance, "Evidence was used"); this.needAmount = needAmount; } diff --git a/Mage/src/main/java/mage/abilities/hint/common/RenownedHint.java b/Mage/src/main/java/mage/abilities/hint/common/RenownedHint.java index 97e63519f07..5ddd3e5a8f6 100644 --- a/Mage/src/main/java/mage/abilities/hint/common/RenownedHint.java +++ b/Mage/src/main/java/mage/abilities/hint/common/RenownedHint.java @@ -8,7 +8,7 @@ import mage.game.Game; public enum RenownedHint implements Hint { instance; - private static final ConditionHint hint = new ConditionHint(RenownedSourceCondition.instance, + private static final ConditionHint hint = new ConditionHint(RenownedSourceCondition.THIS, "{this} is renowned", null, "{this} isn't renowned", null, true); diff --git a/Mage/src/main/java/mage/abilities/keyword/ConvokeAbility.java b/Mage/src/main/java/mage/abilities/keyword/ConvokeAbility.java index 134adc1f246..de792ae59e5 100644 --- a/Mage/src/main/java/mage/abilities/keyword/ConvokeAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/ConvokeAbility.java @@ -29,7 +29,7 @@ import mage.game.stack.Spell; import mage.players.ManaPool; import mage.players.Player; import mage.target.Target; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import mage.util.CardUtil; import java.util.*; @@ -131,7 +131,7 @@ public class ConvokeAbility extends SimpleStaticAbility implements AlternateMana } filter.add(Predicates.or(colorPredicates)); } - Target target = new TargetControlledCreaturePermanent(1, 1, filter, true); + Target target = new TargetPermanent(1, 1, filter, true); target.withTargetName("creature to tap for convoke"); specialAction.addTarget(target); if (specialAction.canActivate(source.getControllerId(), game).canActivate()) { diff --git a/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java b/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java index eff1c18aa26..627f2f2756c 100644 --- a/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java @@ -22,7 +22,7 @@ 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.TargetPermanent; import mage.util.CardUtil; import java.awt.*; @@ -146,7 +146,7 @@ class CrewCost extends CostImpl { paid = true; return true; } - Target target = new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, filter, true) { + Target target = new TargetPermanent(0, Integer.MAX_VALUE, filter, true) { @Override public String getMessage(Game game) { // shows selected power diff --git a/Mage/src/main/java/mage/abilities/keyword/ForecastAbility.java b/Mage/src/main/java/mage/abilities/keyword/ForecastAbility.java index 00e28429ab3..e4eb9ddb428 100644 --- a/Mage/src/main/java/mage/abilities/keyword/ForecastAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/ForecastAbility.java @@ -2,12 +2,10 @@ package mage.abilities.keyword; import mage.abilities.ActivatedAbilityImpl; -import mage.abilities.condition.Condition; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.Cost; import mage.abilities.costs.common.RevealSourceFromYourHandCost; import mage.abilities.effects.Effect; -import mage.constants.PhaseStep; import mage.constants.Zone; /** @@ -26,12 +24,10 @@ import mage.constants.Zone; */ public class ForecastAbility extends ActivatedAbilityImpl { - private static final Condition upkeepCondition = new IsStepCondition(PhaseStep.UPKEEP, true); - public ForecastAbility(Effect effect, Cost cost) { super(Zone.HAND, effect, cost); this.maxActivationsPerTurn = 1; - this.condition = upkeepCondition; + this.condition = IsStepCondition.getMyUpkeep(); this.addCost(new RevealSourceFromYourHandCost()); } diff --git a/Mage/src/main/java/mage/abilities/keyword/MadnessAbility.java b/Mage/src/main/java/mage/abilities/keyword/MadnessAbility.java index b1c532974e2..7297698bac1 100644 --- a/Mage/src/main/java/mage/abilities/keyword/MadnessAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/MadnessAbility.java @@ -291,4 +291,9 @@ enum MadnessCondition implements Condition { return ((Spell) madnessSpell).getSpellAbility().getSpellAbilityCastMode() == SpellAbilityCastMode.MADNESS; } + + @Override + public String toString() { + return "its madness cost was paid"; + } } diff --git a/Mage/src/main/java/mage/abilities/keyword/MentorAbility.java b/Mage/src/main/java/mage/abilities/keyword/MentorAbility.java index 7938ccdc3d7..efb24b269e3 100644 --- a/Mage/src/main/java/mage/abilities/keyword/MentorAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/MentorAbility.java @@ -13,6 +13,7 @@ import mage.filter.predicate.permanent.AttackingPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -29,7 +30,7 @@ public class MentorAbility extends AttacksTriggeredAbility { public MentorAbility() { super(new MentorEffect(), false); - this.addTarget(new TargetCreaturePermanent(filter)); + this.addTarget(new TargetPermanent(filter)); } protected MentorAbility(final MentorAbility ability) { diff --git a/Mage/src/main/java/mage/abilities/keyword/ProvokeAbility.java b/Mage/src/main/java/mage/abilities/keyword/ProvokeAbility.java index 4d7bd7f0dd6..7c068c514b4 100644 --- a/Mage/src/main/java/mage/abilities/keyword/ProvokeAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/ProvokeAbility.java @@ -1,8 +1,6 @@ package mage.abilities.keyword; -import java.util.UUID; - import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.effects.RequirementEffect; @@ -13,7 +11,9 @@ import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; + +import java.util.UUID; /** * 702.38. Provoke 702.38a Provoke is a triggered ability. “Provoke” means @@ -46,8 +46,7 @@ public class ProvokeAbility extends AttacksTriggeredAbility { UUID defendingPlayerId = game.getCombat().getDefendingPlayerId(sourceId, game); filter.add(new ControllerIdPredicate(defendingPlayerId)); this.getTargets().clear(); - TargetCreaturePermanent target = new TargetCreaturePermanent(filter); - this.addTarget(target); + this.addTarget(new TargetPermanent(filter)); return true; } return false; diff --git a/Mage/src/main/java/mage/abilities/keyword/RenownAbility.java b/Mage/src/main/java/mage/abilities/keyword/RenownAbility.java index df811a37cfa..0b93bc9172e 100644 --- a/Mage/src/main/java/mage/abilities/keyword/RenownAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/RenownAbility.java @@ -15,7 +15,6 @@ import mage.game.permanent.Permanent; import mage.util.CardUtil; /** - * * @author LevelX2 */ public class RenownAbility extends TriggeredAbilityImpl { diff --git a/Mage/src/main/java/mage/abilities/keyword/SaddleAbility.java b/Mage/src/main/java/mage/abilities/keyword/SaddleAbility.java index a9b2d74730f..c187c930330 100644 --- a/Mage/src/main/java/mage/abilities/keyword/SaddleAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/SaddleAbility.java @@ -20,7 +20,7 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.target.Target; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import mage.watchers.common.SaddledMountWatcher; import java.awt.*; @@ -128,7 +128,7 @@ class SaddleCost extends CostImpl { @Override public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) { - Target target = new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, filter, true) { + Target target = new TargetPermanent(0, Integer.MAX_VALUE, filter, true) { @Override public String getMessage(Game game) { // shows selected power diff --git a/Mage/src/main/java/mage/abilities/keyword/SupportAbility.java b/Mage/src/main/java/mage/abilities/keyword/SupportAbility.java index 79b84114d31..295c8477c83 100644 --- a/Mage/src/main/java/mage/abilities/keyword/SupportAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/SupportAbility.java @@ -1,12 +1,13 @@ - package mage.abilities.keyword; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.keyword.SupportEffect; import mage.cards.Card; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.AnotherPredicate; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; /** * 701.32. Support @@ -19,19 +20,25 @@ import mage.target.common.TargetCreaturePermanent; */ public class SupportAbility extends EntersBattlefieldTriggeredAbility { + private static final FilterPermanent filter = new FilterCreaturePermanent("other target creatures"); + + static { + filter.add(AnotherPredicate.instance); + } + /* * For enchantments, the text should not include the word "other". * The otherPermanent choice removes the word "other" from rule text creation. */ public SupportAbility(Card card, int amount, boolean otherPermanent) { super(new SupportEffect(card, amount, otherPermanent)); - if (!card.isInstantOrSorcery()) { - FilterCreaturePermanent filter = new FilterCreaturePermanent("creatures"); - if (card.isCreature()) { - filter.add(AnotherPredicate.instance); - filter.setMessage("other target creatures"); - } - addTarget(new TargetCreaturePermanent(0, amount, filter, false)); + if (card.isInstantOrSorcery()) { + return; + } + if (!card.isCreature()) { + addTarget(new TargetPermanent(0, amount, StaticFilters.FILTER_PERMANENT_CREATURES)); + } else { + addTarget(new TargetPermanent(0, amount, filter)); } } diff --git a/Mage/src/main/java/mage/abilities/keyword/SuspendAbility.java b/Mage/src/main/java/mage/abilities/keyword/SuspendAbility.java index 86b584fddf3..f69518cf516 100644 --- a/Mage/src/main/java/mage/abilities/keyword/SuspendAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/SuspendAbility.java @@ -10,7 +10,6 @@ import mage.abilities.costs.VariableCostType; import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.VariableManaCost; -import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.OneShotEffect; @@ -147,7 +146,7 @@ public class SuspendAbility extends SpecialAction { if (card.getManaCost().isEmpty()) { setRuleAtTheTop(true); } - addSubAbility(new SuspendBeginningOfUpkeepInterveningIfTriggeredAbility()); + addSubAbility(new SuspendUpkeepAbility()); addSubAbility(new SuspendPlayCardAbility()); } else { ruleText = "Suspend"; @@ -188,8 +187,7 @@ public class SuspendAbility extends SpecialAction { ability.setControllerId(card.getOwnerId()); game.getState().addOtherAbility(card, ability); - SuspendBeginningOfUpkeepInterveningIfTriggeredAbility ability1 - = new SuspendBeginningOfUpkeepInterveningIfTriggeredAbility(); + SuspendUpkeepAbility ability1 = new SuspendUpkeepAbility(); ability1.setSourceId(card.getId()); ability1.setControllerId(card.getOwnerId()); game.getState().addOtherAbility(card, ability1); @@ -434,23 +432,20 @@ class GainHasteEffect extends ContinuousEffectImpl { } -class SuspendBeginningOfUpkeepInterveningIfTriggeredAbility extends ConditionalInterveningIfTriggeredAbility { +class SuspendUpkeepAbility extends BeginningOfUpkeepTriggeredAbility { - SuspendBeginningOfUpkeepInterveningIfTriggeredAbility() { - super(new BeginningOfUpkeepTriggeredAbility(Zone.EXILED, TargetController.YOU, new RemoveCounterSourceEffect(CounterType.TIME.createInstance()), - false), - SuspendedCondition.instance, - "At the beginning of your upkeep, if {this} is suspended, remove a time counter from it."); + SuspendUpkeepAbility() { + super(Zone.EXILED, TargetController.YOU, new RemoveCounterSourceEffect(CounterType.TIME.createInstance()).setText("remove a time counter from it"), false); + this.withInterveningIf(SuspendedCondition.instance); this.setRuleVisible(false); - } - private SuspendBeginningOfUpkeepInterveningIfTriggeredAbility(final SuspendBeginningOfUpkeepInterveningIfTriggeredAbility effect) { + private SuspendUpkeepAbility(final SuspendUpkeepAbility effect) { super(effect); } @Override - public SuspendBeginningOfUpkeepInterveningIfTriggeredAbility copy() { - return new SuspendBeginningOfUpkeepInterveningIfTriggeredAbility(this); + public SuspendUpkeepAbility copy() { + return new SuspendUpkeepAbility(this); } } diff --git a/Mage/src/main/java/mage/abilities/keyword/WardAbility.java b/Mage/src/main/java/mage/abilities/keyword/WardAbility.java index 01db3372ce5..1a064c0a65c 100644 --- a/Mage/src/main/java/mage/abilities/keyword/WardAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/WardAbility.java @@ -77,7 +77,7 @@ public class WardAbility extends TriggeredAbilityImpl { if (!getSourceId().equals(event.getTargetId())) { return false; } - StackObject targetingObject = CardUtil.findTargetingStackObject(this.getId().toString(), event, game); + StackObject targetingObject = game.findTargetingStackObject(this.getId().toString(), event); if (targetingObject == null || !game.getOpponents(getControllerId()).contains(targetingObject.getControllerId())) { return false; } diff --git a/Mage/src/main/java/mage/cards/CardWithSpellOption.java b/Mage/src/main/java/mage/cards/CardWithSpellOption.java index b1470f7dedc..ed177daa1ec 100644 --- a/Mage/src/main/java/mage/cards/CardWithSpellOption.java +++ b/Mage/src/main/java/mage/cards/CardWithSpellOption.java @@ -26,6 +26,7 @@ public abstract class CardWithSpellOption extends CardImpl { public CardWithSpellOption(CardWithSpellOption card) { super(card); + // make sure all parts created and parent ref added this.spellCard = card.getSpellCard().copy(); this.spellCard.setParentCard(this); } diff --git a/Mage/src/main/java/mage/cards/ModalDoubleFacedCard.java b/Mage/src/main/java/mage/cards/ModalDoubleFacedCard.java index eb8f3fcd19f..eccfab302f2 100644 --- a/Mage/src/main/java/mage/cards/ModalDoubleFacedCard.java +++ b/Mage/src/main/java/mage/cards/ModalDoubleFacedCard.java @@ -62,6 +62,7 @@ public abstract class ModalDoubleFacedCard extends CardImpl implements CardWithH public ModalDoubleFacedCard(ModalDoubleFacedCard card) { super(card); + // make sure all parts created and parent ref added this.leftHalfCard = card.getLeftHalfCard().copy(); ((ModalDoubleFacedCardHalf) leftHalfCard).setParentCard(this); this.rightHalfCard = card.rightHalfCard.copy(); diff --git a/Mage/src/main/java/mage/cards/SplitCard.java b/Mage/src/main/java/mage/cards/SplitCard.java index aafccf957b2..7595febd85b 100644 --- a/Mage/src/main/java/mage/cards/SplitCard.java +++ b/Mage/src/main/java/mage/cards/SplitCard.java @@ -38,6 +38,7 @@ public abstract class SplitCard extends CardImpl implements CardWithHalves { protected SplitCard(SplitCard card) { super(card); + // make sure all parts created and parent ref added this.leftHalfCard = card.getLeftHalfCard().copy(); ((SplitCardHalf) leftHalfCard).setParentCard(this); this.rightHalfCard = card.rightHalfCard.copy(); diff --git a/Mage/src/main/java/mage/cards/repository/TokenRepository.java b/Mage/src/main/java/mage/cards/repository/TokenRepository.java index a3a86c78c9e..75ff94d16bf 100644 --- a/Mage/src/main/java/mage/cards/repository/TokenRepository.java +++ b/Mage/src/main/java/mage/cards/repository/TokenRepository.java @@ -264,10 +264,19 @@ public enum TokenRepository { res.add(createXmageToken(XMAGE_IMAGE_NAME_COPY, 4, "https://api.scryfall.com/cards/tznr/12/en?format=image")); res.add(createXmageToken(XMAGE_IMAGE_NAME_COPY, 5, "https://api.scryfall.com/cards/twho/1/en?format=image")); res.add(createXmageToken(XMAGE_IMAGE_NAME_COPY, 6, "https://api.scryfall.com/cards/tlci/1/en?format=image")); + res.add(createXmageToken(XMAGE_IMAGE_NAME_COPY, 7, "https://api.scryfall.com/cards/tfin/1/en?format=image")); + res.add(createXmageToken(XMAGE_IMAGE_NAME_COPY, 8, "https://api.scryfall.com/cards/ttdm/1/en?format=image")); + res.add(createXmageToken(XMAGE_IMAGE_NAME_COPY, 9, "https://api.scryfall.com/cards/totj/1/en?format=image")); + res.add(createXmageToken(XMAGE_IMAGE_NAME_COPY, 10, "https://api.scryfall.com/cards/tdsk/1/en?format=image")); + res.add(createXmageToken(XMAGE_IMAGE_NAME_COPY, 11, "https://api.scryfall.com/cards/tacr/1/en?format=image")); + res.add(createXmageToken(XMAGE_IMAGE_NAME_COPY, 12, "https://api.scryfall.com/cards/tpip/1/en?format=image")); // City's Blessing // https://scryfall.com/search?q=type%3Atoken+include%3Aextras+unique%3Aprints+City%27s+Blessing+&unique=cards&as=grid&order=name + // https://scryfall.com/search?as=grid&order=released&q=oracleid%3A73d60ab9-1c38-4592-a5b5-ab84788bcc84+include%3Aextras&unique=prints res.add(createXmageToken(XMAGE_IMAGE_NAME_CITY_BLESSING, 1, "https://api.scryfall.com/cards/f18/2/en?format=image")); + res.add(createXmageToken(XMAGE_IMAGE_NAME_CITY_BLESSING, 2, "https://api.scryfall.com/cards/tlcc/17/en?format=image")); + res.add(createXmageToken(XMAGE_IMAGE_NAME_CITY_BLESSING, 3, "https://api.scryfall.com/cards/tmkc/28/en?format=image")); // Day // Night // https://scryfall.com/search?q=include%3Aextras+unique%3Aprints+%22Day+%2F%2F+Night%22&unique=cards&as=grid&order=name @@ -280,6 +289,7 @@ public enum TokenRepository { res.add(createXmageToken(XMAGE_IMAGE_NAME_FACE_DOWN_MANIFEST, 2, "https://api.scryfall.com/cards/tc18/1/en?format=image")); res.add(createXmageToken(XMAGE_IMAGE_NAME_FACE_DOWN_MANIFEST, 3, "https://api.scryfall.com/cards/tfrf/4/en?format=image")); res.add(createXmageToken(XMAGE_IMAGE_NAME_FACE_DOWN_MANIFEST, 4, "https://api.scryfall.com/cards/tncc/3/en?format=image")); + res.add(createXmageToken(XMAGE_IMAGE_NAME_FACE_DOWN_MANIFEST, 5, "https://api.scryfall.com/cards/tdsk/18/en?format=image")); // Morph and Megamorph // https://scryfall.com/search?q=Morph+unique%3Aprints+otag%3Aassistant-cards&unique=cards&as=grid&order=name @@ -298,12 +308,14 @@ public enum TokenRepository { // Foretell // https://scryfall.com/search?q=Foretell+unique%3Aprints+otag%3Aassistant-cards&unique=cards&as=grid&order=name res.add(createXmageToken(XMAGE_IMAGE_NAME_FACE_DOWN_FORETELL, 1, "https://api.scryfall.com/cards/tkhm/23/en?format=image")); + res.add(createXmageToken(XMAGE_IMAGE_NAME_FACE_DOWN_FORETELL, 2, "https://api.scryfall.com/cards/tfic/10/en?format=image")); // The Monarch // https://scryfall.com/search?q=Monarch+unique%3Aprints+otag%3Aassistant-cards&unique=cards&as=grid&order=name res.add(createXmageToken(XMAGE_IMAGE_NAME_THE_MONARCH, 1, "https://api.scryfall.com/cards/tonc/22/en?format=image")); res.add(createXmageToken(XMAGE_IMAGE_NAME_THE_MONARCH, 2, "https://api.scryfall.com/cards/tcn2/1/en?format=image")); res.add(createXmageToken(XMAGE_IMAGE_NAME_THE_MONARCH, 3, "https://api.scryfall.com/cards/tltc/15/en?format=image")); + res.add(createXmageToken(XMAGE_IMAGE_NAME_THE_MONARCH, 4, "https://api.scryfall.com/cards/tfic/11/en?format=image")); // Radiation (for trigger) res.add(createXmageToken(XMAGE_IMAGE_NAME_RADIATION, 1, "https://api.scryfall.com/cards/tpip/22/en?format=image")); diff --git a/Mage/src/main/java/mage/choices/Choice.java b/Mage/src/main/java/mage/choices/Choice.java index c99d11df9e6..e4538b198e6 100644 --- a/Mage/src/main/java/mage/choices/Choice.java +++ b/Mage/src/main/java/mage/choices/Choice.java @@ -44,6 +44,9 @@ public interface Choice extends Serializable, Copyable { ChoiceHintType getHintType(); + /** + * For AI, mana auto-payment from choose color dialogs + */ boolean isManaColorChoice(); Choice setManaColorChoice(boolean manaColorChoice); diff --git a/Mage/src/main/java/mage/constants/Outcome.java b/Mage/src/main/java/mage/constants/Outcome.java index 1f4e4681214..1e976f9ad7b 100644 --- a/Mage/src/main/java/mage/constants/Outcome.java +++ b/Mage/src/main/java/mage/constants/Outcome.java @@ -47,23 +47,23 @@ public enum Outcome { private final boolean good; // no different between own or opponent targets (example: copy must choose from all permanents) - private boolean canTargetAll; + private boolean anyTargetHasSameValue; Outcome(boolean good) { this.good = good; } - Outcome(boolean good, boolean canTargetAll) { + Outcome(boolean good, boolean anyTargetHasSameValue) { this.good = good; - this.canTargetAll = canTargetAll; + this.anyTargetHasSameValue = anyTargetHasSameValue; } public boolean isGood() { return good; } - public boolean isCanTargetAll() { - return canTargetAll; + public boolean anyTargetHasSameValue() { + return anyTargetHasSameValue; } public static Outcome inverse(Outcome outcome) { diff --git a/Mage/src/main/java/mage/constants/SubType.java b/Mage/src/main/java/mage/constants/SubType.java index b8a14045d1d..78d376b1d53 100644 --- a/Mage/src/main/java/mage/constants/SubType.java +++ b/Mage/src/main/java/mage/constants/SubType.java @@ -163,6 +163,7 @@ public enum SubType { DRYAD("Dryad", SubTypeSet.CreatureType), DWARF("Dwarf", SubTypeSet.CreatureType), // E + ECHIDNA("Echidna", SubTypeSet.CreatureType), EFREET("Efreet", SubTypeSet.CreatureType), EGG("Egg", SubTypeSet.CreatureType), ELDER("Elder", SubTypeSet.CreatureType), @@ -210,6 +211,7 @@ public enum SubType { HALFLING("Halfling", SubTypeSet.CreatureType), HAMSTER("Hamster", SubTypeSet.CreatureType), HARPY("Harpy", SubTypeSet.CreatureType), + HEDGEHOG("Hedgehog", SubTypeSet.CreatureType), HELLION("Hellion", SubTypeSet.CreatureType), HERO("Hero", SubTypeSet.CreatureType), HIPPO("Hippo", SubTypeSet.CreatureType), diff --git a/Mage/src/main/java/mage/filter/StaticFilters.java b/Mage/src/main/java/mage/filter/StaticFilters.java index 201c60fc726..6680018c2fb 100644 --- a/Mage/src/main/java/mage/filter/StaticFilters.java +++ b/Mage/src/main/java/mage/filter/StaticFilters.java @@ -232,6 +232,12 @@ public final class StaticFilters { FILTER_CARD_INSTANT_AND_SORCERY.setLockedFilter(true); } + public static final FilterInstantOrSorceryCard FILTER_CARDS_INSTANT_AND_SORCERY = new FilterInstantOrSorceryCard("instant and sorcery cards"); + + static { + FILTER_CARDS_INSTANT_AND_SORCERY.setLockedFilter(true); + } + public static final FilterPermanentCard FILTER_CARD_PERMANENT = new FilterPermanentCard("permanent card"); static { diff --git a/Mage/src/main/java/mage/filter/common/FilterAnyTarget.java b/Mage/src/main/java/mage/filter/common/FilterAnyTarget.java index 0958607c370..45e16a5c591 100644 --- a/Mage/src/main/java/mage/filter/common/FilterAnyTarget.java +++ b/Mage/src/main/java/mage/filter/common/FilterAnyTarget.java @@ -4,6 +4,8 @@ import mage.constants.CardType; import mage.filter.predicate.Predicates; /** + * Warning, it's a filter for damage effects only (ignore lands, artifacts and other non-damageable objects) + * * @author TheElk801 */ public class FilterAnyTarget extends FilterPermanentOrPlayer { diff --git a/Mage/src/main/java/mage/filter/common/FilterPlaneswalkerPermanent.java b/Mage/src/main/java/mage/filter/common/FilterPlaneswalkerPermanent.java index eedc09a699b..638bf60a323 100644 --- a/Mage/src/main/java/mage/filter/common/FilterPlaneswalkerPermanent.java +++ b/Mage/src/main/java/mage/filter/common/FilterPlaneswalkerPermanent.java @@ -1,5 +1,3 @@ - - package mage.filter.common; import mage.constants.CardType; @@ -16,7 +14,11 @@ public class FilterPlaneswalkerPermanent extends FilterPermanent { } public FilterPlaneswalkerPermanent(SubType subType) { - this(subType.getDescription() + " planeswalker"); + this(subType, subType.getDescription() + " planeswalker"); + } + + public FilterPlaneswalkerPermanent(SubType subType, String name) { + this(name); this.add(subType.getPredicate()); } diff --git a/Mage/src/main/java/mage/filter/predicate/mageobject/AnotherPredicate.java b/Mage/src/main/java/mage/filter/predicate/mageobject/AnotherPredicate.java index cca9260b1e7..6df56973dd5 100644 --- a/Mage/src/main/java/mage/filter/predicate/mageobject/AnotherPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/mageobject/AnotherPredicate.java @@ -16,8 +16,7 @@ public enum AnotherPredicate implements ObjectSourcePlayerPredicate if (!input.getObject().getId().equals(input.getSourceId())) { return true; } - int zcc = input.getSource().getSourceObjectZoneChangeCounter(); - return zcc != 0 && zcc != input.getObject().getZoneChangeCounter(game); + return false; } @Override diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/PermanentIdPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/PermanentIdPredicate.java index c387ee3bcf3..9acd64939d1 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/PermanentIdPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/PermanentIdPredicate.java @@ -1,13 +1,12 @@ - package mage.filter.predicate.permanent; -import java.util.UUID; import mage.filter.predicate.Predicate; import mage.game.Game; import mage.game.permanent.Permanent; +import java.util.UUID; + /** - * * @author LevelX2 */ public class PermanentIdPredicate implements Predicate { @@ -27,4 +26,5 @@ public class PermanentIdPredicate implements Predicate { public String toString() { return "PermanentId(" + permanentId + ')'; } + } diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/SaddledSourceThisTurnPredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/SaddledSourceThisTurnPredicate.java index ed6593a8d91..f150d8244ea 100644 --- a/Mage/src/main/java/mage/filter/predicate/permanent/SaddledSourceThisTurnPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/permanent/SaddledSourceThisTurnPredicate.java @@ -17,9 +17,9 @@ public enum SaddledSourceThisTurnPredicate implements ObjectSourcePlayerPredicat @Override public boolean apply(ObjectSourcePlayer input, Game game) { - return SaddledMountWatcher.checkIfSaddledThisTurn( - input.getObject(), new MageObjectReference(input.getSourceId(), input.getSource().getSourceObjectZoneChangeCounter(), game), game - ); + // for delayed triggers must use starting zcc (when delayed trigger created) + MageObjectReference startingMor = new MageObjectReference(input.getSourceId(), input.getSource().getSourceObjectZoneChangeCounter(), game); + return SaddledMountWatcher.checkIfSaddledThisTurn(input.getObject(), startingMor, game); } @Override diff --git a/Mage/src/main/java/mage/game/Game.java b/Mage/src/main/java/mage/game/Game.java index 2df39b9016d..13846b795b8 100644 --- a/Mage/src/main/java/mage/game/Game.java +++ b/Mage/src/main/java/mage/game/Game.java @@ -30,6 +30,7 @@ import mage.game.permanent.Battlefield; import mage.game.permanent.Permanent; import mage.game.stack.Spell; import mage.game.stack.SpellStack; +import mage.game.stack.StackObject; import mage.game.turn.Phase; import mage.game.turn.Step; import mage.game.turn.Turn; @@ -310,6 +311,19 @@ public interface Game extends MageItem, Serializable, Copyable { void resetShortLivingLKI(); + /** + * For finding the spell or ability on the stack for "becomes the target" triggers. + * Also ensures that spells/abilities that target the same object twice only trigger each "becomes the target" ability once. + * If this is the first attempt at triggering for a given ability targeting a given object, + * this method temporarily records that in the game state for later checks by this same method, + * to not return the same object again (until short living LKI is cleared) + * + * @param checkingReference must be unique for each usage (this.getId().toString() of the TriggeredAbility, or this.getKey() of the watcher) + * @param event the GameEvent.EventType.TARGETED from checkTrigger() or watch() + * @return the StackObject which targeted the source, or null if already used or not found + */ + StackObject findTargetingStackObject(String checkingReference, GameEvent event); + void setLosingPlayer(Player player); Player getLosingPlayer(); diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 06932787520..e48ef287395 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -121,6 +121,8 @@ public abstract class GameImpl implements Game { protected Map> lkiExtended = new HashMap<>(); // Used to check if an object was moved by the current effect in resolution (so Wrath like effect can be handled correctly) protected Map> lkiShortLiving = new EnumMap<>(Zone.class); + // For checking "becomes the target" triggers accurately. Cleared on short living LKI reset + protected Map>> targetedMap = new HashMap<>(); // Permanents entering the Battlefield while handling replacement effects before they are added to the battlefield protected Map permanentsEntering = new HashMap<>(); @@ -202,6 +204,7 @@ public abstract class GameImpl implements Game { this.lkiCardState = CardUtil.deepCopyObject(game.lkiCardState); this.lkiExtended = CardUtil.deepCopyObject(game.lkiExtended); this.lkiShortLiving = CardUtil.deepCopyObject(game.lkiShortLiving); + this.targetedMap = CardUtil.deepCopyObject(game.targetedMap); this.permanentsEntering = CardUtil.deepCopyObject(game.permanentsEntering); this.enterWithCounters = CardUtil.deepCopyObject(game.enterWithCounters); @@ -1412,21 +1415,21 @@ public abstract class GameImpl implements Game { public void initGameDefaultWatchers() { List newWatchers = new ArrayList<>(); - newWatchers.add(new CastSpellLastTurnWatcher()); - newWatchers.add(new PlayerLostLifeWatcher()); + newWatchers.add(new CastSpellLastTurnWatcher()); // SPELL_CAST + newWatchers.add(new PlayerLostLifeWatcher()); // LOST_LIFE newWatchers.add(new FirstStrikeWatcher()); // required for combat code - newWatchers.add(new BlockedAttackerWatcher()); + newWatchers.add(new BlockedAttackerWatcher()); // BLOCKER_DECLARED newWatchers.add(new PlanarRollWatcher()); // needed for RollDiceTest (planechase code needs improves) - newWatchers.add(new AttackedThisTurnWatcher()); - newWatchers.add(new CardsDrawnThisTurnWatcher()); - newWatchers.add(new ManaSpentToCastWatcher()); - newWatchers.add(new ManaPaidSourceWatcher()); - newWatchers.add(new BlockingOrBlockedWatcher()); - newWatchers.add(new EndStepCountWatcher()); + newWatchers.add(new AttackedThisTurnWatcher()); // ATTACKER_DECLARED + newWatchers.add(new CardsDrawnThisTurnWatcher()); // DREW_CARD + newWatchers.add(new ManaSpentToCastWatcher()); // SPELL_CAST + newWatchers.add(new ManaPaidSourceWatcher()); // MANA_PAID + newWatchers.add(new BlockingOrBlockedWatcher()); // BLOCKER_DECLARED, END_COMBAT_STEP_POST, REMOVED_FROM_COMBAT + newWatchers.add(new EndStepCountWatcher()); // for continuous effects newWatchers.add(new CommanderPlaysCountWatcher()); // commander plays count uses in non commander games by some cards - newWatchers.add(new CreaturesDiedWatcher()); - newWatchers.add(new TemptedByTheRingWatcher()); - newWatchers.add(new SpellsCastWatcher()); + newWatchers.add(new CreaturesDiedWatcher()); // ZONE_CHANGE + newWatchers.add(new TemptedByTheRingWatcher()); // TEMPTED_BY_RING + newWatchers.add(new SpellsCastWatcher()); // SPELL_CAST newWatchers.add(new AttackedOrBlockedThisCombatWatcher()); // required for tests // runtime check - allows only GAME scope (one watcher per game) @@ -3687,6 +3690,39 @@ public abstract class GameImpl implements Game { @Override public void resetShortLivingLKI() { lkiShortLiving.clear(); + targetedMap.clear(); + } + + @Override + public StackObject findTargetingStackObject(String checkingReference, GameEvent event) { + // In case of multiple simultaneous triggered abilities from the same source, + // need to get the actual one that targeted, see #8026, #8378, rulings for Battle Mammoth + // In case of copied triggered abilities, need to trigger on each independently, see #13498 + // Also avoids triggering on cancelled selections, see #8802 + Map> targetMap = targetedMap.getOrDefault(checkingReference, null); + // targetMap: key - targetId; value - Set of stackObject Ids + if (targetMap == null) { + targetMap = new HashMap<>(); + } else { + targetMap = new HashMap<>(targetMap); // must have new object reference if saved back + } + Set targetingObjects = targetMap.computeIfAbsent(event.getTargetId(), k -> new HashSet<>()); + for (StackObject stackObject : getStack()) { + Ability stackAbility = stackObject.getStackAbility(); + if (stackAbility == null || !stackAbility.getSourceId().equals(event.getSourceId())) { + continue; + } + if (CardUtil.getAllSelectedTargets(stackAbility, this).contains(event.getTargetId())) { + if (!targetingObjects.add(stackObject.getId())) { + continue; // The trigger/watcher already recorded that target of the stack object, check for another + } + // Otherwise, store this combination of trigger/watcher + target + stack object + targetMap.put(event.getTargetId(), targetingObjects); + targetedMap.put(checkingReference, targetMap); + return stackObject; + } + } + return null; } @Override diff --git a/Mage/src/main/java/mage/game/ZonesHandler.java b/Mage/src/main/java/mage/game/ZonesHandler.java index 65d336cdf1a..809fc545a32 100644 --- a/Mage/src/main/java/mage/game/ZonesHandler.java +++ b/Mage/src/main/java/mage/game/ZonesHandler.java @@ -16,6 +16,7 @@ import mage.game.permanent.PermanentToken; import mage.game.stack.Spell; import mage.players.Player; import mage.target.TargetCard; +import mage.util.FuzzyTestsUtil; import java.util.*; @@ -416,6 +417,9 @@ public final class ZonesHandler { && card.removeFromZone(game, fromZone, source)) { success = true; event.setTarget(permanent); + + // tests only: inject fuzzy data with random phased out permanents + FuzzyTestsUtil.addRandomPhasedOutPermanent(permanent, source, game); } else { // revert controller to owner if permanent does not enter game.getContinuousEffects().setController(permanent.getId(), permanent.getOwnerId()); diff --git a/Mage/src/main/java/mage/game/command/dungeons/TombOfAnnihilationDungeon.java b/Mage/src/main/java/mage/game/command/dungeons/TombOfAnnihilationDungeon.java index be2c988301b..af928e4acfb 100644 --- a/Mage/src/main/java/mage/game/command/dungeons/TombOfAnnihilationDungeon.java +++ b/Mage/src/main/java/mage/game/command/dungeons/TombOfAnnihilationDungeon.java @@ -209,7 +209,7 @@ class OublietteTarget extends TargetSacrifice { @Override public Set possibleTargets(UUID sourceControllerId, Ability source, Game game) { Set possibleTargets = super.possibleTargets(sourceControllerId, source, game); - possibleTargets.removeIf(uuid -> !this.canTarget(sourceControllerId, uuid, null, game)); + possibleTargets.removeIf(uuid -> !this.canTarget(sourceControllerId, uuid, source, game)); return possibleTargets; } diff --git a/Mage/src/main/java/mage/game/command/emblems/TezzeretCruelCaptainEmblem.java b/Mage/src/main/java/mage/game/command/emblems/TezzeretCruelCaptainEmblem.java new file mode 100644 index 00000000000..e2975727a58 --- /dev/null +++ b/Mage/src/main/java/mage/game/command/emblems/TezzeretCruelCaptainEmblem.java @@ -0,0 +1,79 @@ +package mage.game.command.emblems; + +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.AddCardSubTypeTargetEffect; +import mage.abilities.effects.common.continuous.AddCardTypeTargetEffect; +import mage.abilities.effects.common.continuous.SetBasePowerToughnessTargetEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.abilities.triggers.BeginningOfCombatTriggeredAbility; +import mage.constants.*; +import mage.counters.CounterType; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.command.Emblem; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * @author TheElk801 + */ +public final class TezzeretCruelCaptainEmblem extends Emblem { + + // -7: You get an emblem with "At the beginning of combat on your turn, put three +1/+1 counters on target artifact you control. If it's not a creature, it becomes a 0/0 Robot artifact creature." + public TezzeretCruelCaptainEmblem() { + super("Emblem Tezzeret"); + Ability ability = new BeginningOfCombatTriggeredAbility( + Zone.COMMAND, TargetController.YOU, + new AddCountersTargetEffect(CounterType.P1P1.createInstance(3)), false + ); + ability.addEffect(new TezzeretCruelCaptainEmblemEffect()); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT)); + this.getAbilities().add(ability); + } + + private TezzeretCruelCaptainEmblem(final TezzeretCruelCaptainEmblem card) { + super(card); + } + + @Override + public TezzeretCruelCaptainEmblem copy() { + return new TezzeretCruelCaptainEmblem(this); + } +} + +class TezzeretCruelCaptainEmblemEffect extends OneShotEffect { + + TezzeretCruelCaptainEmblemEffect() { + super(Outcome.Benefit); + staticText = "If it's not a creature, it becomes a 0/0 Robot artifact creature"; + } + + private TezzeretCruelCaptainEmblemEffect(final TezzeretCruelCaptainEmblemEffect effect) { + super(effect); + } + + @Override + public TezzeretCruelCaptainEmblemEffect copy() { + return new TezzeretCruelCaptainEmblemEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (permanent == null || permanent.isCreature(game)) { + return false; + } + game.addEffect(new AddCardTypeTargetEffect( + Duration.Custom, CardType.ARTIFACT, CardType.CREATURE + ).setTargetPointer(new FixedTarget(permanent, game)), source); + game.addEffect(new AddCardSubTypeTargetEffect( + SubType.ROBOT, Duration.Custom + ).setTargetPointer(new FixedTarget(permanent, game)), source); + game.addEffect(new SetBasePowerToughnessTargetEffect( + 0, 0, Duration.Custom + ).setTargetPointer(new FixedTarget(permanent, game)), source); + return true; + } +} diff --git a/Mage/src/main/java/mage/game/command/planes/AkoumPlane.java b/Mage/src/main/java/mage/game/command/planes/AkoumPlane.java index bcf839a0580..a1892cf8a57 100644 --- a/Mage/src/main/java/mage/game/command/planes/AkoumPlane.java +++ b/Mage/src/main/java/mage/game/command/planes/AkoumPlane.java @@ -16,6 +16,7 @@ import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.EnchantedPredicate; import mage.game.command.Plane; import mage.target.Target; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; import mage.watchers.common.PlanarRollWatcher; @@ -44,7 +45,7 @@ public class AkoumPlane extends Plane { // Active player can roll the planar die: Whenever you roll {CHAOS}, destroy target creature that isn't enchanted Effect chaosEffect = new DestroyTargetEffect("destroy target creature that isn't enchanted"); - Target chaosTarget = new TargetCreaturePermanent(filter); + Target chaosTarget = new TargetPermanent(filter); List chaosEffects = new ArrayList(); chaosEffects.add(chaosEffect); diff --git a/Mage/src/main/java/mage/game/command/planes/BantPlane.java b/Mage/src/main/java/mage/game/command/planes/BantPlane.java index 0a8f555508e..4b5ec23f954 100644 --- a/Mage/src/main/java/mage/game/command/planes/BantPlane.java +++ b/Mage/src/main/java/mage/game/command/planes/BantPlane.java @@ -27,7 +27,7 @@ import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; import mage.game.command.Plane; import mage.target.Target; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import mage.watchers.common.PlanarRollWatcher; import java.util.ArrayList; @@ -62,7 +62,7 @@ public class BantPlane extends Plane { // Active player can roll the planar die: Whenever you roll {CHAOS}, put a divinity counter on target green, white, or blue creature. That creature gains indestructible for as long as it has a divinity counter on it. Effect chaosEffect = new ConditionalContinuousEffect(new GainAbilityTargetEffect(IndestructibleAbility.getInstance(), Duration.Custom), new TargetHasCounterCondition(CounterType.DIVINITY), rule); - Target chaosTarget = new TargetCreaturePermanent(1, 1, filter2, false); + Target chaosTarget = new TargetPermanent(filter2); Effect chaosEffect2 = new AddCountersTargetEffect(CounterType.DIVINITY.createInstance()); List chaosEffects = new ArrayList(); diff --git a/Mage/src/main/java/mage/game/command/planes/FeedingGroundsPlane.java b/Mage/src/main/java/mage/game/command/planes/FeedingGroundsPlane.java index 2cf165b8343..f10bdc9ca9e 100644 --- a/Mage/src/main/java/mage/game/command/planes/FeedingGroundsPlane.java +++ b/Mage/src/main/java/mage/game/command/planes/FeedingGroundsPlane.java @@ -25,7 +25,7 @@ import mage.game.Game; import mage.game.command.Plane; import mage.game.stack.Spell; import mage.target.Target; -import mage.target.common.TargetCreaturePermanent; +import mage.target.TargetPermanent; import mage.util.CardUtil; import mage.watchers.common.PlanarRollWatcher; @@ -48,7 +48,7 @@ public class FeedingGroundsPlane extends Plane { // Active player can roll the planar die: Whenever you roll {CHAOS}, target red or green creature gets X +1/+1 counters Effect chaosEffect = new AddCountersTargetEffect(CounterType.P1P1.createInstance(), TargetManaValue.instance); - Target chaosTarget = new TargetCreaturePermanent(1, 1, StaticFilters.FILTER_PERMANENT_A_CREATURE, false); + Target chaosTarget = new TargetPermanent(StaticFilters.FILTER_PERMANENT_A_CREATURE); List chaosEffects = new ArrayList<>(); chaosEffects.add(chaosEffect); diff --git a/Mage/src/main/java/mage/game/command/planes/NayaPlane.java b/Mage/src/main/java/mage/game/command/planes/NayaPlane.java index c622443917b..2704ed07911 100644 --- a/Mage/src/main/java/mage/game/command/planes/NayaPlane.java +++ b/Mage/src/main/java/mage/game/command/planes/NayaPlane.java @@ -23,7 +23,7 @@ import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; import mage.game.command.Plane; import mage.target.Target; -import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.TargetPermanent; import mage.watchers.common.PlanarRollWatcher; import java.util.ArrayList; @@ -50,7 +50,7 @@ public class NayaPlane extends Plane { // Active player can roll the planar die: Whenever you roll {CHAOS}, target red, green or white creature you control gets +1/+1 until end of turn for each land you control DynamicValue dynamicValue = new PermanentsOnBattlefieldCount(StaticFilters.FILTER_CONTROLLED_PERMANENT_LANDS); Effect chaosEffect = new BoostTargetEffect(dynamicValue, dynamicValue, Duration.EndOfTurn); - Target chaosTarget = new TargetControlledCreaturePermanent(1, 1, filter, false); + Target chaosTarget = new TargetPermanent(filter); List chaosEffects = new ArrayList<>(); chaosEffects.add(chaosEffect); diff --git a/Mage/src/main/java/mage/game/permanent/token/EldraziSpawnToken.java b/Mage/src/main/java/mage/game/permanent/token/EldraziSpawnToken.java index 17e31578470..5b91322b813 100644 --- a/Mage/src/main/java/mage/game/permanent/token/EldraziSpawnToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/EldraziSpawnToken.java @@ -14,7 +14,7 @@ import mage.constants.Zone; public final class EldraziSpawnToken extends TokenImpl { public EldraziSpawnToken() { - super("Eldrazi Spawn Token", "0/1 colorless Eldrazi Spawn creature token with \"Sacrifice this creature: Add {C}.\""); + super("Eldrazi Spawn Token", "0/1 colorless Eldrazi Spawn creature token with \"Sacrifice this token: Add {C}.\""); cardType.add(CardType.CREATURE); subtype.add(SubType.ELDRAZI); subtype.add(SubType.SPAWN); diff --git a/Mage/src/main/java/mage/game/permanent/token/LandMineToken.java b/Mage/src/main/java/mage/game/permanent/token/LandMineToken.java index 7ca06d55e7c..f0da2b9fd4a 100644 --- a/Mage/src/main/java/mage/game/permanent/token/LandMineToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/LandMineToken.java @@ -11,6 +11,7 @@ import mage.constants.Zone; import mage.filter.common.FilterAttackingCreature; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** @@ -29,7 +30,7 @@ public final class LandMineToken extends TokenImpl { cardType.add(CardType.ARTIFACT); Ability ability = new SimpleActivatedAbility(new DamageTargetEffect(2), new ManaCostsImpl<>("{R}")); ability.addCost(new SacrificeSourceCost()); - ability.addTarget(new TargetCreaturePermanent(filter)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage/src/main/java/mage/game/permanent/token/QueenMarchesaAssassinToken.java b/Mage/src/main/java/mage/game/permanent/token/QueenMarchesaAssassinToken.java index a55a5821e01..da3427f80be 100644 --- a/Mage/src/main/java/mage/game/permanent/token/QueenMarchesaAssassinToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/QueenMarchesaAssassinToken.java @@ -12,7 +12,7 @@ import mage.constants.SubType; public final class QueenMarchesaAssassinToken extends TokenImpl { public QueenMarchesaAssassinToken() { - super("Assassin Token", "1/1 black Assassin creature tokens with deathtouch and haste"); + super("Assassin Token", "1/1 black Assassin creature token with deathtouch and haste"); cardType.add(CardType.CREATURE); color.setBlack(true); subtype.add(SubType.ASSASSIN); diff --git a/Mage/src/main/java/mage/game/permanent/token/Robot33Token.java b/Mage/src/main/java/mage/game/permanent/token/Robot33Token.java new file mode 100644 index 00000000000..069d3aace94 --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/Robot33Token.java @@ -0,0 +1,28 @@ +package mage.game.permanent.token; + +import mage.MageInt; +import mage.constants.CardType; +import mage.constants.SubType; + +/** + * @author TheElk801 + */ +public final class Robot33Token extends TokenImpl { + + public Robot33Token() { + super("Robot Token", "3/3 colorless Robot artifact creature token"); + cardType.add(CardType.ARTIFACT); + cardType.add(CardType.CREATURE); + subtype.add(SubType.ROBOT); + power = new MageInt(3); + toughness = new MageInt(3); + } + + private Robot33Token(final Robot33Token token) { + super(token); + } + + public Robot33Token copy() { + return new Robot33Token(this); + } +} diff --git a/Mage/src/main/java/mage/game/permanent/token/RobotToken.java b/Mage/src/main/java/mage/game/permanent/token/RobotToken.java index 4829e4c853c..92164fd6074 100644 --- a/Mage/src/main/java/mage/game/permanent/token/RobotToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/RobotToken.java @@ -10,12 +10,12 @@ import mage.constants.SubType; public final class RobotToken extends TokenImpl { public RobotToken() { - super("Robot Token", "3/3 colorless Robot artifact creature token"); + super("Robot Token", "2/2 colorless Robot artifact creature token"); cardType.add(CardType.ARTIFACT); cardType.add(CardType.CREATURE); subtype.add(SubType.ROBOT); - power = new MageInt(3); - toughness = new MageInt(3); + power = new MageInt(2); + toughness = new MageInt(2); } private RobotToken(final RobotToken token) { diff --git a/Mage/src/main/java/mage/game/permanent/token/SandWarriorToken.java b/Mage/src/main/java/mage/game/permanent/token/SandWarriorToken.java index 609017a96cd..bdcbb823b95 100644 --- a/Mage/src/main/java/mage/game/permanent/token/SandWarriorToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/SandWarriorToken.java @@ -10,7 +10,7 @@ import mage.constants.SubType; public final class SandWarriorToken extends TokenImpl { public SandWarriorToken() { - super("Sand Warrior Token", "1/1 red, green, and white Sand Warrior creature tokens"); + super("Sand Warrior Token", "1/1 red, green, and white Sand Warrior creature token"); cardType.add(CardType.CREATURE); color.setRed(true); color.setGreen(true); diff --git a/Mage/src/main/java/mage/game/permanent/token/ThePrydwenSteelFlagshipHumanKnightToken.java b/Mage/src/main/java/mage/game/permanent/token/ThePrydwenSteelFlagshipHumanKnightToken.java index 4e17cf36883..c6509c84863 100644 --- a/Mage/src/main/java/mage/game/permanent/token/ThePrydwenSteelFlagshipHumanKnightToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/ThePrydwenSteelFlagshipHumanKnightToken.java @@ -19,7 +19,7 @@ public class ThePrydwenSteelFlagshipHumanKnightToken extends TokenImpl { * /!\ You need to add ArtifactEnteredControllerWatcher to any card using this token */ public ThePrydwenSteelFlagshipHumanKnightToken() { - super("Human Knight Token", "2/2 white Human Knight creature token with \"This creature " + + super("Human Knight Token", "2/2 white Human Knight creature token with \"This token " + "gets +2/+2 as long as an artifact entered the battlefield under your control this turn.\""); cardType.add(CardType.CREATURE); color.setWhite(true); diff --git a/Mage/src/main/java/mage/players/Player.java b/Mage/src/main/java/mage/players/Player.java index 1028d914a0c..eb4fe3f69c0 100644 --- a/Mage/src/main/java/mage/players/Player.java +++ b/Mage/src/main/java/mage/players/Player.java @@ -816,6 +816,9 @@ public interface Player extends MageItem, Copyable { void construct(Tournament tournament, Deck deck); + /** + * Draft related: pick next card from a booster + */ void pickCard(List cards, Deck deck, Draft draft); // TODO: add result, process it in AI code (if something put creature to attack then it can broke current AI logic) diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index 33227e25d36..e830b0d70bb 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -5450,7 +5450,7 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public SurveilResult doSurveil(int value, Ability source, Game game) { GameEvent event = new GameEvent(GameEvent.EventType.SURVEIL, getId(), source, getId(), value, true); - if (game.replaceEvent(event)) { + if (game.replaceEvent(event) || event.getAmount() < 1) { return SurveilResult.noSurveil(); } game.informPlayers(getLogName() + " surveils " + event.getAmount() + CardUtil.getSourceLogName(game, source)); diff --git a/Mage/src/main/java/mage/target/Target.java b/Mage/src/main/java/mage/target/Target.java index e5268c1ea98..b95d18c8550 100644 --- a/Mage/src/main/java/mage/target/Target.java +++ b/Mage/src/main/java/mage/target/Target.java @@ -26,10 +26,9 @@ public interface Target extends Copyable, Serializable { * Warning, for "up to" targets it will return true all the time, so make sure your dialog * use do-while logic and call "choose" one time min or use isChoiceCompleted */ + @Deprecated // TODO: replace with UUID abilityControllerId, Ability source, Game game boolean isChosen(Game game); - boolean isChoiceCompleted(Game game); - boolean isChoiceCompleted(UUID abilityControllerId, Ability source, Game game); void clearChosen(); @@ -84,7 +83,7 @@ public interface Target extends Copyable, Serializable { /** * @param id - * @param source WARNING, it can be null for AI or other calls from events (TODO: introduce normal source in AI ComputerPlayer) + * @param source WARNING, it can be null for AI or other calls from events * @param game * @return */ @@ -188,14 +187,22 @@ public interface Target extends Copyable, Serializable { Target copy(); // some targets are chosen from players that are not the controller of the ability (e.g. Pandemonium) + // TODO: research usage of setTargetController and setAbilityController - target adjusters must set it both, example: Necrotic Plague + // replace by shared method like setAbilityAndTargetControllers() + @Deprecated void setTargetController(UUID playerId); UUID getTargetController(); + // TODO: research usage of setTargetController and setAbilityController - target adjusters must set it both, example: Necrotic Plague + // replace by shared method like setAbilityAndTargetControllers() + @Deprecated void setAbilityController(UUID playerId); UUID getAbilityController(); + UUID getAffectedAbilityControllerId(UUID choosingPlayerId); + Player getTargetController(Game game, UUID playerId); int getTargetTag(); diff --git a/Mage/src/main/java/mage/target/TargetAmount.java b/Mage/src/main/java/mage/target/TargetAmount.java index ccbfde6d66a..d28b1852459 100644 --- a/Mage/src/main/java/mage/target/TargetAmount.java +++ b/Mage/src/main/java/mage/target/TargetAmount.java @@ -16,13 +16,15 @@ import java.util.*; import java.util.stream.Collectors; /** + * Distribute value between targets list (damage, counters, etc) + * * @author BetaSteward_at_googlemail.com */ public abstract class TargetAmount extends TargetImpl { boolean amountWasSet = false; DynamicValue amount; - int remainingAmount; + int remainingAmount; // before any change to it - make sure you call prepareAmount protected TargetAmount(DynamicValue amount, int minNumberOfTargets, int maxNumberOfTargets) { this.amount = amount; @@ -46,15 +48,42 @@ public abstract class TargetAmount extends TargetImpl { @Override public boolean isChosen(Game game) { - return isChoiceCompleted(game); + if (!super.isChosen(game)) { + return false; + } + + // selection not started + if (!amountWasSet) { + return false; + } + + // distribution + if (getMinNumberOfTargets() == 0 && this.targets.isEmpty()) { + // allow 0 distribution, e.g. for "up to" targets like Vivien, Arkbow Ranger + return true; + } else { + // need full distribution + return remainingAmount == 0; + } } @Override - public boolean isChoiceCompleted(Game game) { - return amountWasSet - && (remainingAmount == 0 - || (getMinNumberOfTargets() < getMaxNumberOfTargets() - && getTargets().size() >= getMinNumberOfTargets())); + public boolean isChoiceCompleted(UUID abilityControllerId, Ability source, Game game) { + // make sure target request called one time minimum (for "up to" targets) + // choice is selected after any addTarget call (by test, AI or human players) + if (!isChoiceSelected()) { + return false; + } + + // make sure selected targets are valid + if (!isChosen(game)) { + return false; + } + + // TODO: need auto-choose here? See super + + // all other use cases are fine + return true; } @Override @@ -68,9 +97,14 @@ public abstract class TargetAmount extends TargetImpl { this.amount = amount; } - public void setAmount(Ability source, Game game) { - remainingAmount = amount.calculate(game, source, null); - amountWasSet = true; + /** + * Prepare new targets for choosing + */ + public void prepareAmount(Ability source, Game game) { + if (!amountWasSet) { + remainingAmount = amount.calculate(game, source, null); + amountWasSet = true; + } } public DynamicValue getAmount() { @@ -83,12 +117,11 @@ public abstract class TargetAmount extends TargetImpl { @Override public void addTarget(UUID id, int amount, Ability source, Game game, boolean skipEvent) { - if (!amountWasSet) { - setAmount(source, game); - } + prepareAmount(source, game); + if (amount <= remainingAmount) { - super.addTarget(id, amount, source, game, skipEvent); remainingAmount -= amount; + super.addTarget(id, amount, source, game, skipEvent); } } @@ -100,37 +133,70 @@ public abstract class TargetAmount extends TargetImpl { } @Override + public boolean choose(Outcome outcome, UUID playerId, UUID sourceId, Ability source, Game game) { + throw new IllegalArgumentException("Wrong code usage. TargetAmount must be called by player.chooseTarget, not player.choose"); + } + + @Override + @Deprecated // TODO: replace by player.chooseTargetAmount call public boolean chooseTarget(Outcome outcome, UUID playerId, Ability source, Game game) { - Player player = game.getPlayer(playerId); - if (player == null) { + Player targetController = getTargetController(game, playerId); + if (targetController == null) { return false; } - if (!amountWasSet) { - setAmount(source, game); - } + prepareAmount(source, game); - while (remainingAmount > 0) { - chosen = false; - if (!player.canRespond()) { - chosen = isChosen(game); + chosen = false; + do { + int prevTargetsCount = this.getTargets().size(); + + // stop by disconnect + if (!targetController.canRespond()) { break; } - if (!getTargetController(game, playerId).chooseTargetAmount(outcome, this, source, game)) { - chosen = isChosen(game); - break; + + // MAKE A CHOICE + if (isRandom()) { + // random choice + throw new IllegalArgumentException("Wrong code usage. TargetAmount do not support random choices"); + } else { + // player's choice + + // TargetAmount do not support auto-choice + + // manual + + // stop by cancel/done + if (!targetController.chooseTargetAmount(outcome, this, source, game)) { + break; + } + + // continue to next target } + chosen = isChosen(game); - } - return isChosen(game); + // stop by full complete + if (isChoiceCompleted(targetController.getId(), source, game)) { + break; + } + + // stop by nothing to choose (actual for human and done button?) + if (prevTargetsCount == this.getTargets().size()) { + break; + } + + // can select next target + } while (true); + + chosen = isChosen(game); + return chosen && !this.getTargets().isEmpty(); } @Override final public List getTargetOptions(Ability source, Game game) { - if (!amountWasSet) { - setAmount(source, game); - } + prepareAmount(source, game); List options = new ArrayList<>(); Set possibleTargets = possibleTargets(source.getControllerId(), source, game); @@ -370,9 +436,8 @@ public abstract class TargetAmount extends TargetImpl { } public void setTargetAmount(UUID targetId, int amount, Ability source, Game game) { - if (!amountWasSet) { - setAmount(source, game); - } + prepareAmount(source, game); + remainingAmount -= (amount - this.getTargetAmount(targetId)); this.setTargetAmount(targetId, amount, game); } @@ -396,4 +461,13 @@ public abstract class TargetAmount extends TargetImpl { // Each of these targets must receive at least one of whatever is being divided. return amount instanceof StaticValue && max == ((StaticValue) amount).getValue(); } + + @Override + public String toString() { + if (amountWasSet) { + return super.toString() + String.format(" (remain amount %d of %s)", this.remainingAmount, this.amount.toString()); + } else { + return super.toString() + String.format(" (remain not prepared, %s)", this.amount.toString()); + } + } } diff --git a/Mage/src/main/java/mage/target/TargetImpl.java b/Mage/src/main/java/mage/target/TargetImpl.java index 8c5f1f73ea2..48f6f4bf73f 100644 --- a/Mage/src/main/java/mage/target/TargetImpl.java +++ b/Mage/src/main/java/mage/target/TargetImpl.java @@ -111,7 +111,7 @@ public abstract class TargetImpl implements Target { if (min > 0 && max == Integer.MAX_VALUE) { sb.append(CardUtil.numberToText(min)); sb.append(" or more "); - } else if (!targetName.startsWith("X ") && (min != 1 || max != 1)) { + } else if (!targetName.startsWith("X ") && !targetName.startsWith("up to ") && (min != 1 || max != 1)) { targetName = targetName.replace("another", "other"); //If non-singular, use "other" instead of "another" if (getUseAnyNumber()) { @@ -260,12 +260,6 @@ public abstract class TargetImpl implements Target { return chosen || (targets.size() >= getMinNumberOfTargets() && targets.size() <= getMaxNumberOfTargets()); } - @Override - @Deprecated // TODO: replace usage in cards by full version from choose methods - public boolean isChoiceCompleted(Game game) { - return isChoiceCompleted(null, null, game); - } - @Override public boolean isChoiceCompleted(UUID abilityControllerId, Ability source, Game game) { // make sure target request called one time minimum (for "up to" targets) @@ -407,10 +401,7 @@ public abstract class TargetImpl implements Target { return false; } - UUID abilityControllerId = playerId; - if (this.getTargetController() != null && this.getAbilityController() != null) { - abilityControllerId = this.getAbilityController(); - } + UUID abilityControllerId = this.getAffectedAbilityControllerId(playerId); chosen = false; do { @@ -445,7 +436,7 @@ public abstract class TargetImpl implements Target { } while (true); chosen = isChosen(game); - return this.getTargets().size() > 0; + return chosen && !this.getTargets().isEmpty(); } @Override @@ -455,10 +446,7 @@ public abstract class TargetImpl implements Target { return false; } - UUID abilityControllerId = playerId; - if (this.getTargetController() != null && this.getAbilityController() != null) { - abilityControllerId = this.getAbilityController(); - } + UUID abilityControllerId = this.getAffectedAbilityControllerId(playerId); List randomPossibleTargets = new ArrayList<>(possibleTargets(playerId, source, game)); @@ -528,7 +516,7 @@ public abstract class TargetImpl implements Target { } while (true); chosen = isChosen(game); - return this.getTargets().size() > 0; + return chosen && !this.getTargets().isEmpty(); } @Override @@ -727,6 +715,20 @@ public abstract class TargetImpl implements Target { return abilityController; } + @Override + public UUID getAffectedAbilityControllerId(UUID choosingPlayerId) { + // controller hints: + // - target.getTargetController(), this.getId(), choosingPlayerId -- player that must makes choices (must be same with this.getId) + // - target.getAbilityController(), abilityControllerId -- affected player/controller for all actions/filters + // - affected controller can be different from target controller (another player makes choices for controller) + // sometimes a target selection can be made from a player that does not control the ability + UUID abilityControllerId = choosingPlayerId; + if (this.getAbilityController() != null) { + abilityControllerId = this.getAbilityController(); + } + return abilityControllerId; + } + @Override public Player getTargetController(Game game, UUID playerId) { if (getTargetController() != null) { diff --git a/Mage/src/main/java/mage/target/Targets.java b/Mage/src/main/java/mage/target/Targets.java index 3ae7326bcdc..cba1f867cef 100644 --- a/Mage/src/main/java/mage/target/Targets.java +++ b/Mage/src/main/java/mage/target/Targets.java @@ -63,8 +63,8 @@ public class Targets extends ArrayList implements Copyable { return unchosenIndex < res.size() ? res.get(unchosenIndex) : null; } - public boolean isChoiceCompleted(Game game) { - return stream().allMatch(t -> t.isChoiceCompleted(game)); + public boolean isChoiceCompleted(UUID abilityControllerId, Ability source, Game game) { + return stream().allMatch(t -> t.isChoiceCompleted(abilityControllerId, source, game)); } public void clearChosen() { @@ -101,9 +101,7 @@ public class Targets extends ArrayList implements Copyable { // stop on cancel/done if (!target.choose(outcome, playerId, sourceId, source, game)) { - if (!target.isChosen(game)) { - break; - } + break; } // target done, can take next one diff --git a/Mage/src/main/java/mage/target/common/TargetAnyTarget.java b/Mage/src/main/java/mage/target/common/TargetAnyTarget.java index 87de24a32ab..47ad600a4f2 100644 --- a/Mage/src/main/java/mage/target/common/TargetAnyTarget.java +++ b/Mage/src/main/java/mage/target/common/TargetAnyTarget.java @@ -3,6 +3,8 @@ package mage.target.common; import mage.filter.common.FilterAnyTarget; /** + * Warning, it's a target for damage effects only (ignore lands, artifacts and other non-damageable objects) + * * @author JRHerlehy Created on 4/8/18. */ public class TargetAnyTarget extends TargetPermanentOrPlayer { @@ -13,20 +15,12 @@ public class TargetAnyTarget extends TargetPermanentOrPlayer { this(1); } - public TargetAnyTarget(FilterAnyTarget filter) { - this(1, 1, filter); - } - public TargetAnyTarget(int numTargets) { this(numTargets, numTargets); } public TargetAnyTarget(int minNumTargets, int maxNumTargets) { - this(minNumTargets, maxNumTargets, defaultFilter); - } - - public TargetAnyTarget(int minNumTargets, int maxNumTargets, FilterAnyTarget filter) { - super(minNumTargets, maxNumTargets, filter, false); + super(minNumTargets, maxNumTargets, defaultFilter, false); } protected TargetAnyTarget(final TargetAnyTarget target) { diff --git a/Mage/src/main/java/mage/target/common/TargetCardInGraveyardBattlefieldOrStack.java b/Mage/src/main/java/mage/target/common/TargetCardInGraveyardBattlefieldOrStack.java index 7257e334805..b86014f5cac 100644 --- a/Mage/src/main/java/mage/target/common/TargetCardInGraveyardBattlefieldOrStack.java +++ b/Mage/src/main/java/mage/target/common/TargetCardInGraveyardBattlefieldOrStack.java @@ -18,6 +18,7 @@ import java.util.Set; import java.util.UUID; /** + * * @author LevelX2 */ public class TargetCardInGraveyardBattlefieldOrStack extends TargetCard { @@ -97,7 +98,7 @@ public class TargetCardInGraveyardBattlefieldOrStack extends TargetCard { @Override public boolean canTarget(UUID id, Game game) { - return this.canTarget(null, id, null, game); + return this.canTarget(null, id, null, game); // wtf } @Override diff --git a/Mage/src/main/java/mage/target/common/TargetCardInLibrary.java b/Mage/src/main/java/mage/target/common/TargetCardInLibrary.java index cfb91500bec..a6c111bca01 100644 --- a/Mage/src/main/java/mage/target/common/TargetCardInLibrary.java +++ b/Mage/src/main/java/mage/target/common/TargetCardInLibrary.java @@ -76,10 +76,7 @@ public class TargetCardInLibrary extends TargetCard { Cards cardsId = new CardsImpl(); cards.forEach(cardsId::add); - UUID abilityControllerId = playerId; - if (this.getTargetController() != null && this.getAbilityController() != null) { - abilityControllerId = this.getAbilityController(); - } + UUID abilityControllerId = this.getAffectedAbilityControllerId(playerId); chosen = false; do { diff --git a/Mage/src/main/java/mage/target/common/TargetControlledCreaturePermanent.java b/Mage/src/main/java/mage/target/common/TargetControlledCreaturePermanent.java index 784e5e3d2a0..caccb2487e2 100644 --- a/Mage/src/main/java/mage/target/common/TargetControlledCreaturePermanent.java +++ b/Mage/src/main/java/mage/target/common/TargetControlledCreaturePermanent.java @@ -1,7 +1,6 @@ package mage.target.common; import mage.filter.StaticFilters; -import mage.filter.common.FilterControlledCreaturePermanent; /** * @author BetaSteward_at_googlemail.com @@ -17,15 +16,7 @@ public class TargetControlledCreaturePermanent extends TargetControlledPermanent } public TargetControlledCreaturePermanent(int minNumTargets, int maxNumTargets) { - this(minNumTargets, maxNumTargets, maxNumTargets > 1 ? StaticFilters.FILTER_CONTROLLED_CREATURES : StaticFilters.FILTER_CONTROLLED_CREATURE, false); - } - - public TargetControlledCreaturePermanent(FilterControlledCreaturePermanent filter) { - this(1, 1, filter, false); - } - - public TargetControlledCreaturePermanent(int minNumTargets, int maxNumTargets, FilterControlledCreaturePermanent filter, boolean notTarget) { - super(minNumTargets, maxNumTargets, filter, notTarget); + super(minNumTargets, maxNumTargets, maxNumTargets > 1 ? StaticFilters.FILTER_CONTROLLED_CREATURES : StaticFilters.FILTER_CONTROLLED_CREATURE, false); } protected TargetControlledCreaturePermanent(final TargetControlledCreaturePermanent target) { diff --git a/Mage/src/main/java/mage/target/common/TargetCreatureOrPlaneswalker.java b/Mage/src/main/java/mage/target/common/TargetCreatureOrPlaneswalker.java index ffb62653343..a4a717529e9 100644 --- a/Mage/src/main/java/mage/target/common/TargetCreatureOrPlaneswalker.java +++ b/Mage/src/main/java/mage/target/common/TargetCreatureOrPlaneswalker.java @@ -1,14 +1,8 @@ - package mage.target.common; -import mage.abilities.Ability; -import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent; -import mage.game.Game; -import mage.players.Player; +import mage.filter.StaticFilters; import mage.target.TargetPermanent; -import java.util.UUID; - /** * @author LevelX2 */ @@ -23,11 +17,7 @@ public class TargetCreatureOrPlaneswalker extends TargetPermanent { } public TargetCreatureOrPlaneswalker(int minNumTargets, int maxNumTargets) { - this(minNumTargets, maxNumTargets, new FilterCreatureOrPlaneswalkerPermanent(), false); - } - - public TargetCreatureOrPlaneswalker(int minNumTargets, int maxNumTargets, FilterCreatureOrPlaneswalkerPermanent filter, boolean notTarget) { - super(minNumTargets, maxNumTargets, filter, notTarget); + super(minNumTargets, maxNumTargets, StaticFilters.FILTER_PERMANENT_CREATURE_OR_PLANESWALKER, false); } protected TargetCreatureOrPlaneswalker(final TargetCreatureOrPlaneswalker target) { @@ -38,17 +28,4 @@ public class TargetCreatureOrPlaneswalker extends TargetPermanent { public TargetCreatureOrPlaneswalker copy() { return new TargetCreatureOrPlaneswalker(this); } - - @Override - public boolean isLegal(Ability source, Game game) { - for (UUID playerId : targets.keySet()) { - Player targetPlayer = game.getPlayer(playerId); - if (targetPlayer != null) { - // there seems to be no possibility to add more predicates for theplayer so return here true - return true; - } - } - return super.isLegal(source, game); - } - } diff --git a/Mage/src/main/java/mage/target/common/TargetCreatureOrPlayer.java b/Mage/src/main/java/mage/target/common/TargetCreatureOrPlayer.java index 838e9a95a41..13cf4cd72ec 100644 --- a/Mage/src/main/java/mage/target/common/TargetCreatureOrPlayer.java +++ b/Mage/src/main/java/mage/target/common/TargetCreatureOrPlayer.java @@ -1,22 +1,17 @@ package mage.target.common; import mage.filter.common.FilterCreatureOrPlayer; +import mage.filter.common.FilterPermanentOrPlayer; /** * @author BetaSteward_at_googlemail.com */ public class TargetCreatureOrPlayer extends TargetPermanentOrPlayer { + private static final FilterPermanentOrPlayer filter = new FilterCreatureOrPlayer(); + public TargetCreatureOrPlayer() { - this(1, 1, new FilterCreatureOrPlayer()); - } - - public TargetCreatureOrPlayer(FilterCreatureOrPlayer filter) { - this(1, 1, filter); - } - - public TargetCreatureOrPlayer(int minNumTargets, int maxNumTargets, FilterCreatureOrPlayer filter) { - super(minNumTargets, maxNumTargets, filter, false); + super(1, 1, filter, false); } protected TargetCreatureOrPlayer(final TargetCreatureOrPlayer target) { @@ -27,5 +22,4 @@ public class TargetCreatureOrPlayer extends TargetPermanentOrPlayer { public TargetCreatureOrPlayer copy() { return new TargetCreatureOrPlayer(this); } - } diff --git a/Mage/src/main/java/mage/target/common/TargetCreaturePermanent.java b/Mage/src/main/java/mage/target/common/TargetCreaturePermanent.java index c7028a67508..17efca5ae8d 100644 --- a/Mage/src/main/java/mage/target/common/TargetCreaturePermanent.java +++ b/Mage/src/main/java/mage/target/common/TargetCreaturePermanent.java @@ -1,8 +1,6 @@ - package mage.target.common; import mage.filter.StaticFilters; -import mage.filter.common.FilterCreaturePermanent; import mage.target.TargetPermanent; /** @@ -14,20 +12,12 @@ public class TargetCreaturePermanent extends TargetPermanent { this(1); } - public TargetCreaturePermanent(FilterCreaturePermanent filter) { - this(1, 1, filter, false); - } - public TargetCreaturePermanent(int numTargets) { this(numTargets, numTargets); } public TargetCreaturePermanent(int minNumTargets, int maxNumTargets) { - this(minNumTargets, maxNumTargets, maxNumTargets > 1 ? StaticFilters.FILTER_PERMANENT_CREATURES : StaticFilters.FILTER_PERMANENT_CREATURE, false); - } - - public TargetCreaturePermanent(int minNumTargets, int maxNumTargets, FilterCreaturePermanent filter, boolean notTarget) { - super(minNumTargets, maxNumTargets, filter, notTarget); + super(minNumTargets, maxNumTargets, maxNumTargets > 1 ? StaticFilters.FILTER_PERMANENT_CREATURES : StaticFilters.FILTER_PERMANENT_CREATURE, false); } protected TargetCreaturePermanent(final TargetCreaturePermanent target) { diff --git a/Mage/src/main/java/mage/target/common/TargetCreaturePermanentWithDifferentTypes.java b/Mage/src/main/java/mage/target/common/TargetCreaturePermanentWithDifferentTypes.java deleted file mode 100644 index 74013310160..00000000000 --- a/Mage/src/main/java/mage/target/common/TargetCreaturePermanentWithDifferentTypes.java +++ /dev/null @@ -1,49 +0,0 @@ - -package mage.target.common; - -import mage.abilities.Ability; -import mage.filter.common.FilterCreaturePermanent; -import mage.game.Game; -import mage.game.permanent.Permanent; - -import java.util.UUID; - -/** - * @author LevelX2 - */ -public class TargetCreaturePermanentWithDifferentTypes extends TargetCreaturePermanent { - - public TargetCreaturePermanentWithDifferentTypes(int minNumTargets, int maxNumTargets, FilterCreaturePermanent filter, boolean notTarget) { - super(minNumTargets, maxNumTargets, filter, notTarget); - } - - protected TargetCreaturePermanentWithDifferentTypes(final TargetCreaturePermanentWithDifferentTypes target) { - super(target); - } - - @Override - public TargetCreaturePermanentWithDifferentTypes copy() { - return new TargetCreaturePermanentWithDifferentTypes(this); - } - - @Override - public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) { - if (super.canTarget(controllerId, id, source, game)) { - Permanent creature = game.getPermanent(id); - if (creature != null) { - for (Object object : getTargets()) { - UUID targetId = (UUID) object; - Permanent selectedCreature = game.getPermanent(targetId); - if (selectedCreature != null - && !creature.getId().equals(selectedCreature.getId())) { - if (creature.shareCreatureTypes(game, selectedCreature)) { - return false; - } - } - } - return true; - } - } - return false; - } -} diff --git a/Mage/src/main/java/mage/target/common/TargetDiscard.java b/Mage/src/main/java/mage/target/common/TargetDiscard.java index 4e732d8ba09..299319b30c3 100644 --- a/Mage/src/main/java/mage/target/common/TargetDiscard.java +++ b/Mage/src/main/java/mage/target/common/TargetDiscard.java @@ -1,18 +1,16 @@ - package mage.target.common; -import mage.constants.Zone; import mage.abilities.Ability; import mage.cards.Card; +import mage.constants.Zone; import mage.filter.FilterCard; +import mage.filter.StaticFilters; +import mage.filter.predicate.card.OwnerIdPredicate; import mage.game.Game; import mage.target.TargetCard; import java.util.UUID; -import mage.filter.StaticFilters; -import mage.filter.predicate.card.OwnerIdPredicate; - /** * @author BetaSteward_at_googlemail.com */ @@ -54,5 +52,4 @@ public class TargetDiscard extends TargetCard { public TargetDiscard copy() { return new TargetDiscard(this); } - } diff --git a/Mage/src/main/java/mage/target/common/TargetOpponentOrPlaneswalker.java b/Mage/src/main/java/mage/target/common/TargetOpponentOrPlaneswalker.java index d30b65d64e8..3fc95ab5fc9 100644 --- a/Mage/src/main/java/mage/target/common/TargetOpponentOrPlaneswalker.java +++ b/Mage/src/main/java/mage/target/common/TargetOpponentOrPlaneswalker.java @@ -1,25 +1,28 @@ package mage.target.common; import mage.filter.common.FilterOpponentOrPlaneswalker; +import mage.filter.common.FilterPermanentOrPlayer; /** * @author LevelX2 */ public class TargetOpponentOrPlaneswalker extends TargetPermanentOrPlayer { + private static final FilterPermanentOrPlayer filter = new FilterOpponentOrPlaneswalker(); + public TargetOpponentOrPlaneswalker() { this(1); } - public TargetOpponentOrPlaneswalker(FilterOpponentOrPlaneswalker filter) { - this(1, 1, filter, false); - } - public TargetOpponentOrPlaneswalker(int numTargets) { - this(numTargets, numTargets, new FilterOpponentOrPlaneswalker("opponent or planeswalker"), false); + this(numTargets, numTargets); } - public TargetOpponentOrPlaneswalker(int minNumTargets, int maxNumTargets, FilterOpponentOrPlaneswalker filter, boolean notTarget) { + public TargetOpponentOrPlaneswalker(int minNumTargets, int maxNumTargets) { + this(minNumTargets, maxNumTargets, false); + } + + public TargetOpponentOrPlaneswalker(int minNumTargets, int maxNumTargets, boolean notTarget) { super(minNumTargets, maxNumTargets, filter, notTarget); } diff --git a/Mage/src/main/java/mage/target/targetadjustment/DefineByTriggerTargetAdjuster.java b/Mage/src/main/java/mage/target/targetadjustment/DefineByTriggerTargetAdjuster.java new file mode 100644 index 00000000000..e0e9e741805 --- /dev/null +++ b/Mage/src/main/java/mage/target/targetadjustment/DefineByTriggerTargetAdjuster.java @@ -0,0 +1,19 @@ +package mage.target.targetadjustment; + +import mage.abilities.Ability; +import mage.game.Game; + +/** + * Use this to indicate that the targets are dynamically added via the Ability directly + * While still satisfying the Verify target check + * + * @author notgreat + */ +public enum DefineByTriggerTargetAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + //Do nothing + } +} diff --git a/Mage/src/main/java/mage/util/CardUtil.java b/Mage/src/main/java/mage/util/CardUtil.java index 8cd26e37641..d4c968bd4dd 100644 --- a/Mage/src/main/java/mage/util/CardUtil.java +++ b/Mage/src/main/java/mage/util/CardUtil.java @@ -44,7 +44,6 @@ import mage.game.permanent.PermanentMeld; import mage.game.permanent.PermanentToken; import mage.game.permanent.token.Token; import mage.game.stack.Spell; -import mage.game.stack.StackObject; import mage.players.Player; import mage.players.PlayerList; import mage.target.Target; @@ -85,7 +84,7 @@ public final class CardUtil { public static final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS"); private static final List costWords = Arrays.asList( - "put", "return", "exile", "discard", "sacrifice", "remove", "tap", "reveal", "pay", "collect", "forage" + "put", "return", "exile", "discard", "mill", "sacrifice", "remove", "tap", "reveal", "pay", "have", "collect", "forage" ); // search set code in commands like "set_code-card_name" @@ -1133,49 +1132,6 @@ public final class CardUtil { return res; } - /** - * For finding the spell or ability on the stack for "becomes the target" triggers. - * Also ensures that spells/abilities that target the same object twice only trigger each "becomes the target" ability once. - * If this is the first attempt at triggering for a given ability targeting a given object, - * this method records that in the game state for later checks by this same method, to not return the same object again. - * - * @param checkingReference must be unique for each usage (this.getId().toString() of the TriggeredAbility, or this.getKey() of the watcher) - * @param event the GameEvent.EventType.TARGETED from checkTrigger() or watch() - * @param game the Game from checkTrigger() or watch() - * @return the StackObject which targeted the source, or null if already used or not found - */ - public static StackObject findTargetingStackObject(String checkingReference, GameEvent event, Game game) { - // In case of multiple simultaneous triggered abilities from the same source, - // need to get the actual one that targeted, see #8026, #8378, rulings for Battle Mammoth - // In case of copied triggered abilities, need to trigger on each independently, see #13498 - // Also avoids triggering on cancelled selections, see #8802 - String stateKey = "targetedMap" + checkingReference; - Map> targetMap = (Map>) game.getState().getValue(stateKey); - // targetMap: key - targetId; value - Set of stackObject Ids - if (targetMap == null) { - targetMap = new HashMap<>(); - } else { - targetMap = new HashMap<>(targetMap); // must have new object reference if saved back to game state - } - Set targetingObjects = targetMap.computeIfAbsent(event.getTargetId(), k -> new HashSet<>()); - for (StackObject stackObject : game.getStack()) { - Ability stackAbility = stackObject.getStackAbility(); - if (stackAbility == null || !stackAbility.getSourceId().equals(event.getSourceId())) { - continue; - } - if (CardUtil.getAllSelectedTargets(stackAbility, game).contains(event.getTargetId())) { - if (!targetingObjects.add(stackObject.getId())) { - continue; // The trigger/watcher already recorded that target of the stack object, check for another - } - // Otherwise, store this combination of trigger/watcher + target + stack object - targetMap.put(event.getTargetId(), targetingObjects); - game.getState().setValue(stateKey, targetMap); - return stackObject; - } - } - return null; - } - /** * For overriding `canTarget()` with usages such as "any number of target cards with total mana value X or less". * Call this after super.canTarget() returns true. diff --git a/Mage/src/main/java/mage/util/DebugUtil.java b/Mage/src/main/java/mage/util/DebugUtil.java index 4c090a4557e..c76f83243eb 100644 --- a/Mage/src/main/java/mage/util/DebugUtil.java +++ b/Mage/src/main/java/mage/util/DebugUtil.java @@ -68,16 +68,24 @@ public class DebugUtil { public static String NETWORK_PROFILE_REQUESTS_DUMP_FILE_NAME = "httpRequests.log"; /** - * Return method and source line number like "secondMethod - DebugUtilTest.java:21" + * Return source line number for better debugging like "secondMethod - DebugUtilTest.java:21" * - * @param skipMethodsAmount use 0 to return current method info, use 1 for prev method, use 2 for prev-prev method + * @param skipMethodsAmount use 0 to return current method info, use 1 for prev method, use 2 for prev-prev method, etc + * @param infoType use "class" for full class name and "method" for short method name */ - public static String getMethodNameWithSource(final int skipMethodsAmount) { + public static String getMethodNameWithSource(int skipMethodsAmount, String infoType) { // 3 is default methods amount to skip: // - getMethodNameWithSource // - TraceHelper.getMethodNameWithSource // - Thread.currentThread().getStackTrace() - return TraceHelper.getMethodNameWithSource(3 + skipMethodsAmount); + switch (infoType) { + case "class": + return TraceHelper.getClassNameWithSource(3 + skipMethodsAmount); + case "method": + return TraceHelper.getMethodNameWithSource(3 + skipMethodsAmount); + default: + throw new IllegalArgumentException("Unknown info type: " + infoType); + } } } @@ -88,6 +96,9 @@ public class DebugUtil { */ class TraceHelper { + /** + * Example: showDialog - ChooseTargetTestableDialog.java:72 + */ public static String getMethodNameWithSource(final int depth) { StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); if (stackTrace.length == 0) { @@ -96,4 +107,17 @@ class TraceHelper { return String.format("%s - %s:%d", stackTrace[depth].getMethodName(), stackTrace[depth].getFileName(), stackTrace[depth].getLineNumber()); } } + + /** + * Compatible with IntelliJ IDEA's logs navigation (will be clickable) + * Example: mage.utils.testers.ChooseTargetTestableDialog(ChooseTargetTestableDialog.java:62) + */ + public static String getClassNameWithSource(final int depth) { + StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); + if (stackTrace.length == 0) { + return "[no access to stack]"; + } else { + return String.format("%s(%s:%d)", stackTrace[depth].getClassName(), stackTrace[depth].getFileName(), stackTrace[depth].getLineNumber()); + } + } } \ No newline at end of file diff --git a/Mage/src/main/java/mage/util/FuzzyTestsUtil.java b/Mage/src/main/java/mage/util/FuzzyTestsUtil.java new file mode 100644 index 00000000000..1523c9040a5 --- /dev/null +++ b/Mage/src/main/java/mage/util/FuzzyTestsUtil.java @@ -0,0 +1,90 @@ +package mage.util; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.EntersBattlefieldEffect; +import mage.abilities.keyword.PhasingAbility; +import mage.cards.Card; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +import java.util.Map; +import java.util.UUID; + +/** + * Helper class for fuzzy testing + *

+ * Support: + * - [x] enable by command line; + * - [x] phased out permanents must be hidden + * - [ ] TODO: out of range players and permanents must be hidden + * - [ ] TODO: leave/disconnected players must be hidden + *

+ * How-to use: + * - enable here or by command line + * - run unit tests and research the fails + * + * @author JayDi85 + */ +public class FuzzyTestsUtil { + + /** + * Phased out permanents must be hidden + * Make sure other cards and effects do not see phased out permanents and ignore it + *

+ * Use case: + * - each permanent on battlefield will have copied phased out version with all abilities and effects + *

+ * How-to use: + * - set true or run with -Dxmage.tests.addRandomPhasedOutPermanents=true + */ + public static boolean ADD_RANDOM_PHASED_OUT_PERMANENTS = false; + + static { + String val = System.getProperty("xmage.tests.addRandomPhasedOutPermanents"); + if (val != null) { + ADD_RANDOM_PHASED_OUT_PERMANENTS = Boolean.parseBoolean(val); + } + } + + /** + * Create duplicated phased out permanent + */ + public static void addRandomPhasedOutPermanent(Permanent originalPermanent, Ability source, Game game) { + if (!ADD_RANDOM_PHASED_OUT_PERMANENTS) { + return; + } + Player samplePlayer = game.getPlayers().values().stream().findFirst().orElse(null); + if (samplePlayer == null || !samplePlayer.isTestsMode()) { + return; + } + + // copy permanent and put it to battlefield as phased out (diff sides also supported here) + // TODO: add phased out tests support (must not fail on it) + Card originalCardSide = game.getCard(originalPermanent.getId()); + Card originalCardMain = originalCardSide.getMainCard(); + if (!originalCardMain.hasAbility(PhasingAbility.getInstance(), game)) { + boolean canCreate = true; + Card doppelgangerCardMain = game.copyCard(originalCardMain, source, originalPermanent.getControllerId()); + Map mapOldToNew = CardUtil.getOriginalToCopiedPartsMap(originalCardMain, doppelgangerCardMain); + Card doppelgangerCardSide = (Card) mapOldToNew.getOrDefault(originalCardSide.getId(), null); + doppelgangerCardSide.addAbility(PhasingAbility.getInstance()); + + // compatibility workaround: remove all etb abilities to skip any etb choices (e.g. copy effect) + doppelgangerCardSide.getAbilities().removeIf(a -> a.getEffects().stream().anyMatch(e -> e instanceof EntersBattlefieldEffect)); + // compatibility workaround: ignore aura to skip any etb choices (e.g. select new target) + if (doppelgangerCardSide.hasSubtype(SubType.AURA, game)) { + canCreate = false; + } + + if (canCreate) { + doppelgangerCardSide.putOntoBattlefield(game, Zone.BATTLEFIELD, source, originalPermanent.getControllerId()); + Permanent doppelgangerPerm = CardUtil.getPermanentFromCardPutToBattlefield(doppelgangerCardSide, game); + doppelgangerPerm.phaseOut(game, true); // use indirect, so no phase in on untap + } + } + } +} diff --git a/Mage/src/main/java/mage/watchers/WatcherUtils.java b/Mage/src/main/java/mage/watchers/WatcherUtils.java deleted file mode 100644 index b90425706c6..00000000000 --- a/Mage/src/main/java/mage/watchers/WatcherUtils.java +++ /dev/null @@ -1,20 +0,0 @@ - -package mage.watchers; - -import mage.MageObject; -import mage.abilities.Ability; -import mage.game.Game; -import org.apache.log4j.Logger; - -/** - * - * @author LevelX2 - */ -public final class WatcherUtils { - - public static void logMissingWatcher(Game game, Ability source, Class watcherClass, Class usingClass) { - MageObject sourceObject = source.getSourceObject(game); - Logger.getLogger(usingClass).error("Needed watcher is not started " + watcherClass.getSimpleName() - + " - " + (sourceObject == null ? " no source object" : sourceObject.getName())); - } -} diff --git a/Mage/src/main/java/mage/watchers/common/BlockedAttackerWatcher.java b/Mage/src/main/java/mage/watchers/common/BlockedAttackerWatcher.java index 1ceae3d0172..3b4beba4aca 100644 --- a/Mage/src/main/java/mage/watchers/common/BlockedAttackerWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/BlockedAttackerWatcher.java @@ -1,9 +1,8 @@ package mage.watchers.common; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; +import java.util.stream.Collectors; + import mage.MageObjectReference; import mage.constants.WatcherScope; import mage.game.Game; @@ -17,7 +16,9 @@ import mage.watchers.Watcher; */ public class BlockedAttackerWatcher extends Watcher { - private final Map> blockData = new HashMap<>(); + // key: blocking creatures + // value: set of creatures blocked + private final Map> blockerMap = new HashMap<>(); /** * Game default watcher @@ -29,31 +30,31 @@ public class BlockedAttackerWatcher extends Watcher { @Override public void watch(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.BLOCKER_DECLARED) { - MageObjectReference blocker = new MageObjectReference(event.getSourceId(), game); - Set blockedAttackers = blockData.get(blocker); - if (blockedAttackers != null) { - blockedAttackers.add(new MageObjectReference(event.getTargetId(), game)); - } else { - blockedAttackers = new HashSet<>(); - blockedAttackers.add(new MageObjectReference(event.getTargetId(), game)); - blockData.put(blocker, blockedAttackers); - } + blockerMap.computeIfAbsent(new MageObjectReference(event.getSourceId(), game), k -> new HashSet<>()) + .add(new MageObjectReference(event.getTargetId(), game)); } } @Override public void reset() { super.reset(); - blockData.clear(); + blockerMap.clear(); } public boolean creatureHasBlockedAttacker(Permanent attacker, Permanent blocker, Game game) { - Set blockedAttackers = blockData.get(new MageObjectReference(blocker, game)); - return blockedAttackers != null && blockedAttackers.contains(new MageObjectReference(attacker, game)); + return blockerMap.getOrDefault(new MageObjectReference(blocker, game), Collections.emptySet()) + .contains(new MageObjectReference(attacker, game)); } - public boolean creatureHasBlockedAttacker(MageObjectReference attacker, MageObjectReference blocker, Game game) { - Set blockedAttackers = blockData.get(blocker); - return blockedAttackers != null && blockedAttackers.contains(attacker); + public boolean creatureHasBlockedAttacker(MageObjectReference attacker, MageObjectReference blocker) { + return blockerMap.getOrDefault(blocker, Collections.emptySet()).contains(attacker); + } + + public Set getBlockedCreatures(MageObjectReference blocker, Game game) { + return blockerMap.getOrDefault(blocker, Collections.emptySet()) + .stream() + .map(m -> m.getPermanent(game)) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); } } diff --git a/Mage/src/main/java/mage/watchers/common/ManaPaidSourceWatcher.java b/Mage/src/main/java/mage/watchers/common/ManaPaidSourceWatcher.java index c3921737ceb..01fe3ba122b 100644 --- a/Mage/src/main/java/mage/watchers/common/ManaPaidSourceWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/ManaPaidSourceWatcher.java @@ -37,6 +37,7 @@ public class ManaPaidSourceWatcher extends Watcher { private int colorlessSnow = 0; private int treasure = 0; private int creature = 0; + private int artifact = 0; private ManaPaidTracker() { super(); @@ -52,6 +53,7 @@ public class ManaPaidSourceWatcher extends Watcher { this.colorlessSnow = tracker.colorlessSnow; this.treasure = tracker.treasure; this.creature = tracker.creature; + this.artifact = tracker.artifact; } @Override @@ -67,6 +69,9 @@ public class ManaPaidSourceWatcher extends Watcher { if (sourceObject != null && sourceObject.isCreature(game)) { creature++; } + if (sourceObject != null && sourceObject.isArtifact(game)) { + artifact++; + } if (sourceObject != null && !sourceObject.isSnow(game)) { return; } @@ -157,6 +162,11 @@ public class ManaPaidSourceWatcher extends Watcher { return watcher == null ? 0 : watcher.manaMap.getOrDefault(sourceId, emptyTracker).creature; } + public static int getArtifactPaid(UUID sourceId, Game game) { + ManaPaidSourceWatcher watcher = game.getState().getWatcher(ManaPaidSourceWatcher.class); + return watcher == null ? 0 : watcher.manaMap.getOrDefault(sourceId, emptyTracker).artifact; + } + public static int getSnowPaid(UUID sourceId, Game game) { ManaPaidSourceWatcher watcher = game.getState().getWatcher(ManaPaidSourceWatcher.class); return watcher == null ? 0 : watcher.manaMap.getOrDefault(sourceId, emptyTracker).getSnow(); diff --git a/Mage/src/main/java/mage/watchers/common/NumberOfTimesPermanentTargetedATurnWatcher.java b/Mage/src/main/java/mage/watchers/common/NumberOfTimesPermanentTargetedATurnWatcher.java index b8e031bca49..08e5276cac2 100644 --- a/Mage/src/main/java/mage/watchers/common/NumberOfTimesPermanentTargetedATurnWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/NumberOfTimesPermanentTargetedATurnWatcher.java @@ -6,7 +6,6 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.stack.StackObject; -import mage.util.CardUtil; import mage.watchers.Watcher; import java.util.HashMap; @@ -29,7 +28,7 @@ public class NumberOfTimesPermanentTargetedATurnWatcher extends Watcher { if (event.getType() != GameEvent.EventType.TARGETED) { return; } - StackObject targetingObject = CardUtil.findTargetingStackObject(this.getKey(), event, game); + StackObject targetingObject = game.findTargetingStackObject(this.getKey(), event); if (targetingObject == null) { return; } diff --git a/Mage/src/main/java/mage/watchers/common/PlayerAttackedWatcher.java b/Mage/src/main/java/mage/watchers/common/PlayerAttackedWatcher.java index c806e4d68cb..d0695883859 100644 --- a/Mage/src/main/java/mage/watchers/common/PlayerAttackedWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/PlayerAttackedWatcher.java @@ -1,16 +1,14 @@ - - package mage.watchers.common; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - import mage.constants.WatcherScope; 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 LevelX2 */ diff --git a/Mage/src/main/resources/tokens-database.txt b/Mage/src/main/resources/tokens-database.txt index d7858933b16..df62e048268 100644 --- a/Mage/src/main/resources/tokens-database.txt +++ b/Mage/src/main/resources/tokens-database.txt @@ -145,6 +145,7 @@ |Generate|EMBLEM:INR|Emblem Tamiyo|||TamiyoFieldResearcherEmblem| |Generate|EMBLEM:INR|Emblem Wrenn|||WrennAndSevenEmblem| |Generate|EMBLEM:DFT|Emblem Chandra|||ChandraSparkHunterEmblem| +|Generate|EMBLEM:FIN|Emblem Sephiroth|||SephirothOneWingedAngelEmblem| # ALL PLANES @@ -530,6 +531,9 @@ # DGM |Generate|TOK:DGM|Elemental|||VoiceOfResurgenceToken| +# DIS +|Generate|TOK:DIS|Elemental|||ResearchDevelopmentToken| + # DKA |Generate|TOK:DKA|Human|||HumanToken| |Generate|TOK:DKA|Vampire|||SorinLordOfInnistradVampireToken| @@ -1136,6 +1140,9 @@ |Generate|TOK:ELD|Rat|||RatToken| |Generate|TOK:ELD|Wolf|||GarrukCursedHuntsmanToken| +# UND +|Generate|TOK:UND|Goblin|||GoblinToken| + # THB |Generate|TOK:THB|Elemental|||PurphorossInterventionToken| |Generate|TOK:THB|Goat|||GoatToken| @@ -1920,6 +1927,12 @@ |Generate|TOK:40K|Tyranid Gargoyle|||TyranidGargoyleToken| |Generate|TOK:40K|Tyranid Warrior|||TyranidWarriorToken| +# UNF +|Generate|TOK:UNF|Clown Robot|1||ClownRobotToken| +|Generate|TOK:UNF|Clown Robot|2||ClownRobotToken| +|Generate|TOK:UNF|Storm Crow|||StormCrowToken| +|Generate|TOK:UNF|Squirrel|||SquirrelToken| + # BRO |Generate|TOK:BRO|Bear|||BearToken| |Generate|TOK:BRO|Construct|1||KarnConstructToken| @@ -2234,6 +2247,7 @@ # WHO |Generate|TOK:WHO|Alien|||AlienToken| +|Generate|TOK:WHO|Alien Angel|||AlienAngelToken| |Generate|TOK:WHO|Alien Insect|||AlienInsectToken| |Generate|TOK:WHO|Alien Rhino|||AlienRhinoToken| |Generate|TOK:WHO|Alien Salamander|||AlienSalamanderToken| @@ -2270,7 +2284,7 @@ |Generate|TOK:PIP|Human Knight|||ThePrydwenSteelFlagshipHumanKnightToken| |Generate|TOK:PIP|Human Soldier|||HumanSoldierToken| |Generate|TOK:PIP|Junk|||JunkToken| -|Generate|TOK:PIP|Robot|||RobotToken| +|Generate|TOK:PIP|Robot|||Robot33Token| |Generate|TOK:PIP|Settlement|||SettlementToken| |Generate|TOK:PIP|Soldier|1||SoldierTokenWithHaste| |Generate|TOK:PIP|Soldier|2||SoldierToken| @@ -2736,7 +2750,8 @@ |Generate|TOK:TDC|Gold|||GoldToken| |Generate|TOK:TDC|Human|||HumanToken| |Generate|TOK:TDC|Inkling|||InklingToken| -|Generate|TOK:TDC|Insect|||InsectToken| +|Generate|TOK:TDC|Insect|1||InsectToken| +|Generate|TOK:TDC|Insect|2||InsectDeathToken| |Generate|TOK:TDC|Karox Bladewing|||KaroxBladewingToken| |Generate|TOK:TDC|Myr|||MyrToken| |Generate|TOK:TDC|Plant|||PlantToken| @@ -2748,6 +2763,7 @@ |Generate|TOK:TDC|Spider|||SpiderToken| |Generate|TOK:TDC|Spirit|||SpiritWhiteToken| |Generate|TOK:TDC|Thopter|||ThopterColorlessToken| +|Generate|TOK:TDC|Wall|||Wall13Token| # ACR |Generate|TOK:ACR|Assassin|||AssassinMenaceToken| @@ -2764,6 +2780,7 @@ |Generate|TOK:DSK|Everywhere|||EverywhereToken| |Generate|TOK:DSK|Glimmer|||GlimmerToken| |Generate|TOK:DSK|Gremlin|||Gremlin11Token| +|Generate|TOK:DSK|Horror|||HorrorEnchantmentCreatureToken| |Generate|TOK:DSK|Insect|1||InsectBlackGreenFlyingToken| |Generate|TOK:DSK|Insect|2||InsectWhiteToken| |Generate|TOK:DSK|Primo, the Indivisible|||PrimoTheIndivisibleToken| @@ -2774,7 +2791,49 @@ # FIN |Generate|TOK:FIN|Food|||FoodToken| -|Generate|TOK:FIN|Hero|||HeroToken| +|Generate|TOK:FIN|Hero|1||HeroToken| +|Generate|TOK:FIN|Hero|2||HeroToken| +|Generate|TOK:FIN|Hero|3||HeroToken| +|Generate|TOK:FIN|Hero|4||HeroToken| +|Generate|TOK:FIN|Hero|5||HeroToken| +|Generate|TOK:FIN|Hero|6||HeroToken| +|Generate|TOK:FIN|Hero|7||HeroToken| +|Generate|TOK:FIN|Hero|8||HeroToken| +|Generate|TOK:FIN|Hero|9||HeroToken| +|Generate|TOK:FIN|Hero|10||HeroToken| +|Generate|TOK:FIN|Hero|11||HeroToken| +|Generate|TOK:FIN|Hero|12||HeroToken| +|Generate|TOK:FIN|Hero|13||HeroToken| +|Generate|TOK:FIN|Hero|14||HeroToken| +|Generate|TOK:FIN|Hero|15||HeroToken| +|Generate|TOK:FIN|Hero|16||HeroToken| +|Generate|TOK:FIN|Knight|||WaylayToken| +|Generate|TOK:FIN|Moogle|1||MoogleToken| +|Generate|TOK:FIN|Moogle|2||MoogleToken| +|Generate|TOK:FIN|Robot|||RobotBlueToken| +|Generate|TOK:FIN|Horror|||Horror3Token| +|Generate|TOK:FIN|Wizard|1||BlackWizardToken| +|Generate|TOK:FIN|Wizard|2||BlackWizardToken| +|Generate|TOK:FIN|Wizard|3||BlackWizardToken| +|Generate|TOK:FIN|Bird|1||ChocoboToken| +|Generate|TOK:FIN|Bird|2||ChocoboToken| +|Generate|TOK:FIN|Frog|||FrogGreenToken| +|Generate|TOK:FIN|Angelo|||AngeloToken| +|Generate|TOK:FIN|Darkstar|||DarkstarToken| +|Generate|TOK:FIN|Elemental|||ElementalAllColorsToken| +|Generate|TOK:FIN|Treasure|1||TreasureToken| +|Generate|TOK:FIN|Treasure|2||TreasureToken| + +# FIN +|Generate|TOK:FIC|Human Soldier|||HumanSoldierToken| +|Generate|TOK:FIC|Soldier|||SoldierToken| +|Generate|TOK:FIC|Spirit|||SpiritWhiteToken| +|Generate|TOK:FIC|Bird|||BirdVigilanceToken| +|Generate|TOK:FIC|Squid|||SquidToken| +|Generate|TOK:FIC|Zombie|||ZombieToken| +|Generate|TOK:FIC|Rebel|||RebelRedToken| +|Generate|TOK:FIC|The Blackjack|||TheBlackjackToken| +|Generate|TOK:FIC|Clue|||ClueArtifactToken| # JVC |Generate|TOK:JVC|Elemental Shaman|||ElementalShamanToken| @@ -2786,6 +2845,7 @@ # UGL |Generate|TOK:UGL|Goblin|||GoblinToken| |Generate|TOK:UGL|Pegasus|||PegasusToken| +|Generate|TOK:UGL|Rabid Sheep|||RabidSheepToken| |Generate|TOK:UGL|Soldier|||SoldierToken| |Generate|TOK:UGL|Squirrel|||SquirrelToken| |Generate|TOK:UGL|Zombie|||ZombieToken| diff --git a/Utils/known-sets.txt b/Utils/known-sets.txt index 1a0b1a4d250..41e5637f9c5 100644 --- a/Utils/known-sets.txt +++ b/Utils/known-sets.txt @@ -18,6 +18,7 @@ Arena League|ArenaLeague| Asia Pacific Land Program|AsiaPacificLandProgram| Assassin's Creed|AssassinsCreed| Avacyn Restored|AvacynRestored| +Avatar: The Last Airbender|AvatarTheLastAirbender| Battlebond|Battlebond| Battle for Zendikar|BattleForZendikar| Betrayers of Kamigawa|BetrayersOfKamigawa| @@ -86,6 +87,8 @@ Duel Decks: Zendikar vs. Eldrazi|DuelDecksZendikarVsEldrazi| Duels of the Planeswalkers|DuelsOfThePlaneswalkers| Duskmourn: House of Horror|DuskmournHouseOfHorror| Duskmourn: House of Horror Commander|DuskmournHouseOfHorrorCommander| +Edge of Eternities|EdgeOfEternities| +Edge of Eternities Commander|EdgeOfEternitiesCommander| Eighth Edition|EighthEdition| Eldritch Moon|EldritchMoon| Eternal Masters|EternalMasters| diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 21675cca7f4..9ee840f5d31 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -59108,3 +59108,34 @@ Green Goblin, Nemesis|Marvel's Spider-Man Eternal|23|R|{2}{B}{R}|Legendary Creat Doc Ock, Evil Inventor|Marvel's Spider-Man Eternal|24|R|{5}{U}{B}|Legendary Creature - Human Scientist Villain|8|8|At the beginning of combat on your turn, target noncreature artifact you control becomes an 8/8 Robot Villain artifact creature in addition to its other types.| Sensational Spider-Man|Marvel's Spider-Man Eternal|25|R|{1}{W}{U}|Legendary Creature - Spider Human Hero|3|3|Whenever Sensational Spider-Man attacks, tap target creature defending player controls and put a stun counter on it. Then you may remove up to three stun counters from among all permanents. Draw cards equal to the number of stun counters removed this way.| Pumpkin Bombs|Marvel's Spider-Man Eternal|26|R|{1}{R}|Artifact|||{T}, Discard two cards: Draw three cards, then put a fuse counter on this artifact. It deals damage equal to the number of fuse counters on it to target opponent. They gain control of this artifact.| +Tezzeret, Cruel Captain|Edge of Eternities|2|M|{3}|Legendary Planeswalker - Tezzeret|4|Whenever an artifact you control enters, put a loyalty counter on Tezzeret.$0: Untap target artifact or creature. If it's an artifact creature, put a +1/+1 counter on it.$-3: Search your library for an artifact card with mana value 1 or less, reveal it, put it in your hand, then shuffle.$-7: You get an emblem with "At the beginning of combat on your turn, put three +1/+1 counters on target artifact you control. If it's not a creature, it becomes a 0/0 Robot artifact creature."| +The Seriema|Edge of Eternities|35|R|{1}{W}{W}|Legendary Artifact - Spacecraft|||When The Seriema enters, search your library for a legendary creature card, reveal it, put it into your hand, then shuffle.$Station$STATION 7+$Flying$Other tapped legendary creatures you control have indestructible.$5/5| +Sothera, the Supervoid|Edge of Eternities|115|M|{2}{B}{B}|Legendary Enchantment|||Whenever a creature you control dies, each opponent chooses a creature they control and exiles it.$At the beginning of your end step, if a player controls no creatures, sacrifice Sothera, then put a creature card exiled with it onto the battlefield under your control with two additional +1/+1 counters on it.| +Harmonious Grovestrider|Edge of Eternities|189|U|{3}{G}{G}|Creature - Beast|*|*|Ward {2}$This creature's power and toughness are each equal to the number of lands you control.| +Alpharael, Dreaming Acolyte|Edge of Eternities|212|U|{1}{U}{B}|Legendary Creature - Human Cleric|2|3|When Alpharael enters, draw two cards. Then discard two cards unless you discard an artifact card. During your turn, Alpharael has deathtouch.| +Sami, Ship's Engineer|Edge of Eternities|225|U|{2}{R}{W}|Legendary Creature - Human Artificer|2|4|At the beginning of your end step, if you control two or more tapped creatures, create a tapped 2/2 colorless Robot artifact creature token.| +Tannuk, Memorial Ensign|Edge of Eternities|233|U|{1}{R}{G}|Legendary Creature - Kavu Pilot|2|4|Landfall - Whenever a land you control enters, Tannuk deals 1 damage to each opponent. If this is the second time this ability has resolved this turn, draw a card.| +Breeding Pool|Edge of Eternities|251|R||Land - Forest Island|||({T}: Add {G} or {U}.)$As this land enters, you may pay 2 life. If you don't, it enters tapped.| +Godless Shrine|Edge of Eternities|254|R||Land - Plains Swamp|||({T}: Add {W} or {B}.)$As this land enters, you may pay 2 life. If you don't, it enters tapped.| +Sacred Foundry|Edge of Eternities|256|R||Land - Mountain Plains|||({T}: Add {R} or {W}.)$As this land enters, you may pay 2 life. If you don't, it enters tapped.| +Stomping Ground|Edge of Eternities|258|R||Land - Mountain Forest|||({T}: Add {R} or {G}.)$As this land enters, you may pay 2 life. If you don't, it enters tapped.| +Watery Grave|Edge of Eternities|261|R||Land - Island Swamp|||({T}: Add {U} or {B}.)$As this land enters, you may pay 2 life. If you don't, it enters tapped.| +Plains|Edge of Eternities|262|C||Basic Land - Plains|||({T}: Add {W}.)| +Island|Edge of Eternities|263|C||Basic Land - Island|||({T}: Add {U}.)| +Swamp|Edge of Eternities|264|C||Basic Land - Swamp|||({T}: Add {B}.)| +Mountain|Edge of Eternities|265|C||Basic Land - Mountain|||({T}: Add {R}.)| +Forest|Edge of Eternities|266|C||Basic Land - Forest|||({T}: Add {G}.)| +Tezzeret, Cruel Captain|Edge of Eternities|287|M|{3}|Legendary Planeswalker - Tezzeret|4|Whenever an artifact you control enters, put a loyalty counter on Tezzeret.$0: Untap target artifact or creature. If it's an artifact creature, put a +1/+1 counter on it.$-3: Search your library for an artifact card with mana value 1 or less, reveal it, put it in your hand, then shuffle.$-7: You get an emblem with "At the beginning of combat on your turn, put three +1/+1 counters on target artifact you control. If it's not a creature, it becomes a 0/0 Robot artifact creature."| +The Seriema|Edge of Eternities|323|R|{1}{W}{W}|Legendary Artifact - Spacecraft|||When The Seriema enters, search your library for a legendary creature card, reveal it, put it into your hand, then shuffle.$Station$STATION 7+$Flying$Other tapped legendary creatures you control have indestructible.$5/5| +Sothera, the Supervoid|Edge of Eternities|360|M|{2}{B}{B}|Legendary Enchantment|||Whenever a creature you control dies, each opponent chooses a creature they control and exiles it.$At the beginning of your end step, if a player controls no creatures, sacrifice Sothera, then put a creature card exiled with it onto the battlefield under your control with two additional +1/+1 counters on it.| +Plains|Edge of Eternities|367|C||Basic Land - Plains|||({T}: Add {W}.)| +Island|Edge of Eternities|368|C||Basic Land - Island|||({T}: Add {U}.)| +Swamp|Edge of Eternities|369|C||Basic Land - Swamp|||({T}: Add {B}.)| +Mountain|Edge of Eternities|370|C||Basic Land - Mountain|||({T}: Add {R}.)| +Forest|Edge of Eternities|371|C||Basic Land - Forest|||({T}: Add {G}.)| +Sothera, the Supervoid|Edge of Eternities|382|M|{2}{B}{B}|Legendary Enchantment|||Whenever a creature you control dies, each opponent chooses a creature they control and exiles it.$At the beginning of your end step, if a player controls no creatures, sacrifice Sothera, then put a creature card exiled with it onto the battlefield under your control with two additional +1/+1 counters on it.| +Sothera, the Supervoid|Edge of Eternities|386|M|{2}{B}{B}|Legendary Enchantment|||Whenever a creature you control dies, each opponent chooses a creature they control and exiles it.$At the beginning of your end step, if a player controls no creatures, sacrifice Sothera, then put a creature card exiled with it onto the battlefield under your control with two additional +1/+1 counters on it.| +Kilo, Apogee Mind|Edge of Eternities Commander|3|M|{U}{R}{W}|Legendary Artifact Creature - Robot Artificer|3|3|Haste$Whenever Kilo becomes tapped, proliferate.| +Szarel, Genesis Shepherd|Edge of Eternities Commander|4|M|{2}{B}{R}{G}|Legendary Creature - Insect Druid|2|5|Flying$You may play lands from your graveyard.$Whenever you sacrifice another nontoken permanent during your turn, put a number of +1/+1 counters equal to Szarel's power on up to one other target creature.| +Avatar Aang|Avatar: The Last Airbender|363|M|{R}{G}{W}{U}|Legendary Creature - Human Avatar Ally|4|4|Flying, firebending 2$Whenever you waterbend, earthbend, firebend, or airbend, draw a card. Then if you've done all four this turn, transform Avatar Aang.| +Aang, Master of Elements|Avatar: The Last Airbender|363|M||Legendary Creature - Avatar Ally|6|6|Flying$Spelsl you cast cost {W}{U}{B}{R}{G} less to cast.$At the beginning of each upkeep, you may transform Aang, Master of Elements. If you do, you gain 4 life, draw four cards, put four +1/+1 counters on him, and he deals 4 damage to each opponent.| diff --git a/Utils/mtg-sets-data.txt b/Utils/mtg-sets-data.txt index af90b04b5b6..2a0c35d220e 100644 --- a/Utils/mtg-sets-data.txt +++ b/Utils/mtg-sets-data.txt @@ -29,6 +29,7 @@ Anthologies|ATH| Antiquities|ATQ| Assassin's Creed|ACR| Avacyn Restored|AVR| +Avatar: The Last Airbender|TLA| Battle for Zendikar|BFZ| Battlebond|BBD| Born of the Gods|BNG| @@ -100,6 +101,8 @@ Darksteel|DST| Dragons of Tarkir|DTK| Archenemy: Nicol Bolas|E01| Explorers of Ixalan|E02| +Edge of Eternities|EOE| +Edge of Eternities Commander|EOC| Eternal Masters|EMA| Eldritch Moon|EMN| European Land Program|EURO| diff --git a/pom.xml b/pom.xml index f61deeb6eff..329e9c45206 100644 --- a/pom.xml +++ b/pom.xml @@ -274,8 +274,8 @@ org.slf4j - slf4j-log4j12 - 1.7.32 + slf4j-reload4j + 2.0.17