master #9

Merged
Failure merged 25 commits from External/mage:master into master 2024-12-18 22:41:22 -08:00
166 changed files with 1505 additions and 579 deletions

View file

@ -87,7 +87,7 @@ public class AddLandDialog extends MageDialog {
landSetNames.add(expansionInfo.getName());
}
if (landSetNames.isEmpty()) {
throw new IllegalArgumentException("No set with basic land was found");
throw new IllegalArgumentException("No set with basic land was found (possible memory problems, need client restart)");
}
if (landSetNames.size() > 1) {
landSetNames.add("<Random lands>");
@ -477,6 +477,7 @@ public class AddLandDialog extends MageDialog {
}//GEN-LAST:event_btnSetFastSearchActionPerformed
private void autoAddLands() {
// suggest lands amount for deck without lands
int deckSize = ((Number) spnDeckSize.getValue()).intValue();
int[] lands = DeckBuildUtils.landCountSuggestion(deckSize, deck.getMaindeckCards());
spnPlains.setValue(lands[0]);

View file

@ -61,7 +61,7 @@ public class ScryfallImageSupportTokens {
put("RNA/Treasure", "https://api.scryfall.com/cards/trna/12/en?format=image");
put("RNA/Zombie", "https://api.scryfall.com/cards/trna/3/en?format=image");
//GRN
// GRN
put("GRN/Angel", "https://api.scryfall.com/cards/tgrn/1/en?format=image");
put("GRN/Bird Illusion", "https://api.scryfall.com/cards/tgrn/3/en?format=image");
put("GRN/Elf Knight", "https://api.scryfall.com/cards/tgrn/6/en?format=image");
@ -71,7 +71,7 @@ public class ScryfallImageSupportTokens {
put("GRN/Soldier", "https://api.scryfall.com/cards/tgrn/2/en?format=image");
put("GRN/Emblem Vraska", "https://api.scryfall.com/cards/tgrn/8/en?format=image");
//DOM
// DOM
put("DOM/Cleric", "https://api.scryfall.com/cards/tdom/4/en?format=image");
put("DOM/Construct", "https://api.scryfall.com/cards/tdom/14/en?format=image");
put("DOM/Demon", "https://api.scryfall.com/cards/tdom/7/en?format=image");
@ -89,7 +89,7 @@ public class ScryfallImageSupportTokens {
put("DOM/Emblem Teferi", "https://api.scryfall.com/cards/tdom/16/en?format=image");
put("DOM/Zombie Knight", "https://api.scryfall.com/cards/tdom/5/en?format=image");
//XLN
// XLN
put("XLN/Dinosaur", "https://api.scryfall.com/cards/txln/5/en?format=image");
put("XLN/Illusion", "https://api.scryfall.com/cards/txln/2/en?format=image");
put("XLN/Merfolk", "https://api.scryfall.com/cards/txln/3/en?format=image");
@ -101,12 +101,12 @@ public class ScryfallImageSupportTokens {
put("XLN/Treasure/4", "https://api.scryfall.com/cards/txln/10/en?format=image");
put("XLN/Vampire", "https://api.scryfall.com/cards/txln/1/en?format=image");
//HOU
// HOU
put("HOU/Horse", "https://api.scryfall.com/cards/thou/10/en?format=image");
put("HOU/Insect", "https://api.scryfall.com/cards/thou/12/en?format=image");
put("HOU/Snake", "https://api.scryfall.com/cards/thou/11/en?format=image");
//AKH - tokens
// AKH - tokens
put("AKH/Beast", "https://api.scryfall.com/cards/takh/21/en?format=image");
put("AKH/Cat", "https://api.scryfall.com/cards/takh/16/en?format=image");
put("AKH/Drake", "https://api.scryfall.com/cards/takh/18/en?format=image");
@ -117,7 +117,7 @@ public class ScryfallImageSupportTokens {
put("AKH/Warrior", "https://api.scryfall.com/cards/takh/17/en?format=image");
put("AKH/Wurm", "https://api.scryfall.com/cards/takh/24/en?format=image");
put("AKH/Zombie", "https://api.scryfall.com/cards/takh/20/en?format=image");
//AKH - embalm ability (token from card)
// AKH - embalm ability (token from card)
put("AKH/Angel of Sanctions", "https://api.scryfall.com/cards/takh/1/en?format=image");
put("AKH/Anointer Priest", "https://api.scryfall.com/cards/takh/2/en?format=image");
put("AKH/Aven Initiate", "https://api.scryfall.com/cards/takh/3/en?format=image");
@ -134,13 +134,13 @@ public class ScryfallImageSupportTokens {
put("AKH/Unwavering Initiate", "https://api.scryfall.com/cards/takh/14/en?format=image");
put("AKH/Vizier of Many Faces", "https://api.scryfall.com/cards/takh/15/en?format=image");
//AER
// AER
put("AER/Etherium Cell", "https://api.scryfall.com/cards/taer/3/en?format=image");
put("AER/Gremlin", "https://api.scryfall.com/cards/taer/1/en?format=image");
put("AER/Ragavan", "https://api.scryfall.com/cards/taer/2/en?format=image");
put("AER/Emblem Tezzeret", "https://api.scryfall.com/cards/taer/4/en?format=image");
//KLD
// KLD
put("KLD/Beast", "https://api.scryfall.com/cards/tkld/1/en?format=image");
put("KLD/Emblem Chandra", "https://api.scryfall.com/cards/tkld/10/en?format=image");
put("KLD/Construct/1", "https://api.scryfall.com/cards/tkld/2/en?format=image");
@ -154,7 +154,7 @@ public class ScryfallImageSupportTokens {
put("KLD/Thopter/2", "https://api.scryfall.com/cards/tkld/8/en?format=image");
put("KLD/Thopter/3", "https://api.scryfall.com/cards/tkld/9/en?format=image");
//EMN
// EMN
put("EMN/Eldrazi Horror", "https://api.scryfall.com/cards/temn/1/en?format=image");
put("EMN/Human", "https://api.scryfall.com/cards/temn/7/en?format=image");
put("EMN/Human Wizard", "https://api.scryfall.com/cards/temn/2/en?format=image");
@ -166,7 +166,7 @@ public class ScryfallImageSupportTokens {
put("EMN/Zombie/3", "https://api.scryfall.com/cards/temn/5/en?format=image");
put("EMN/Zombie/4", "https://api.scryfall.com/cards/temn/6/en?format=image");
//SOI
// SOI
put("SOI/Angel", "https://api.scryfall.com/cards/tsoi/1/en?format=image");
put("SOI/Emblem Arlinn", "https://api.scryfall.com/cards/tsoi/18/en?format=image");
put("SOI/Clue/1", "https://api.scryfall.com/cards/tsoi/11/en?format=image");
@ -186,7 +186,7 @@ public class ScryfallImageSupportTokens {
put("SOI/Wolf", "https://api.scryfall.com/cards/tsoi/9/en?format=image");
put("SOI/Zombie", "https://api.scryfall.com/cards/tsoi/5/en?format=image");
//OGW
// OGW
put("OGW/Angel", "https://api.scryfall.com/cards/togw/7/en?format=image");
put("OGW/Eldrazi Scion/1", "https://api.scryfall.com/cards/togw/1/en?format=image");
put("OGW/Eldrazi Scion/2", "https://api.scryfall.com/cards/togw/2/en?format=image");
@ -199,7 +199,7 @@ public class ScryfallImageSupportTokens {
put("OGW/Plant", "https://api.scryfall.com/cards/togw/11/en?format=image");
put("OGW/Zombie", "https://api.scryfall.com/cards/togw/8/en?format=image");
//BFZ
// BFZ
put("BFZ/Dragon", "https://api.scryfall.com/cards/tbfz/8/en?format=image");
put("BFZ/Eldrazi", "https://api.scryfall.com/cards/tbfz/1/en?format=image");
put("BFZ/Eldrazi Scion/1", "https://api.scryfall.com/cards/tbfz/2/en?format=image");
@ -319,7 +319,7 @@ public class ScryfallImageSupportTokens {
put("C18/Worm", "https://api.scryfall.com/cards/tc18/18/en?format=image");
put("C18/Zombie", "https://api.scryfall.com/cards/tc18/9/en?format=image");
//C19
// C19
put("C19/Assassin", "https://api.scryfall.com/cards/tc19/9/en?format=image");
put("C19/Beast/1", "https://api.scryfall.com/cards/tc19/13/en?format=image");
put("C19/Beast/2", "https://api.scryfall.com/cards/tc19/14/en?format=image");
@ -2167,7 +2167,7 @@ public class ScryfallImageSupportTokens {
put("WOC/Spirit", "https://api.scryfall.com/cards/twoc/17/en?format=image");
put("WOC/Virtuous", "https://api.scryfall.com/cards/twoc/3/en?format=image");
//WHO
// WHO
put("WHO/Alien Insect", "https://api.scryfall.com/cards/twho/19/en?format=image");
// 8ED
@ -2491,6 +2491,9 @@ public class ScryfallImageSupportTokens {
put("FDN/Emblem Vivien", "https://api.scryfall.com/cards/tfdn/25/en?format=image");
put("FDN/Zombie", "https://api.scryfall.com/cards/tfdn/15/en?format=image");
// H17
put("H17/Dragon", "https://api.scryfall.com/cards/h17/4/en?format=image");
// generate supported sets
supportedSets.clear();
for (String cardName : this.keySet()) {

View file

@ -16,20 +16,35 @@ public class DownloaderTest {
@Test
public void test_DownloadText_ByHttp() {
String s = XmageURLConnection.downloadText("http://google.com");
String s = XmageURLConnection.downloadText("http://example.com");
Assert.assertTrue("must have text data", s.contains("<head>"));
}
@Test
public void test_DownloadText_ByHttps() {
String s = XmageURLConnection.downloadText("https://google.com");
String s = XmageURLConnection.downloadText("https://example.com");
Assert.assertTrue("must have text data", s.contains("<head>"));
}
@Test
public void test_DownloadText_ByRedirectProtocol() {
// http to https restricted by design, see https://stackoverflow.com/a/1884427/1276632
// it's not critical for a client (e.g. for images download), so no needs in custom implementation
// like xmage launcher does
String s = XmageURLConnection.downloadText("http://github.com");
Assert.assertTrue("must have fail on https redirect (301 result)", s.isEmpty());
}
@Test
public void test_DownloadText_ByRedirectUri() {
String s = XmageURLConnection.downloadText("https://github.com/magefree/mage/issues/new");
Assert.assertTrue("must have text data (redirect to login page)", s.contains("Sign in to GitHub"));
}
@Test
public void test_DownloadFile_ByHttp() throws IOException {
// use any public image here
InputStream stream = XmageURLConnection.downloadBinary("http://www.google.com/tia/tia.png");
InputStream stream = XmageURLConnection.downloadBinary("http://xmage.today/images/xmage-logo.png");
Assert.assertNotNull(stream);
BufferedImage image = ImageIO.read(stream);
Assert.assertNotNull(stream);
@ -39,7 +54,7 @@ public class DownloaderTest {
@Test
public void test_DownloadFile_ByHttps() throws IOException {
// use any public image here
InputStream stream = XmageURLConnection.downloadBinary("https://www.google.com/tia/tia.png");
InputStream stream = XmageURLConnection.downloadBinary("https://xmage.today/images/xmage-logo.png");
Assert.assertNotNull(stream);
BufferedImage image = ImageIO.read(stream);
Assert.assertNotNull(stream);

View file

@ -18,7 +18,7 @@ public class MageVersion implements Serializable, Comparable<MageVersion> {
public static final int MAGE_VERSION_MAJOR = 1;
public static final int MAGE_VERSION_MINOR = 4;
public static final int MAGE_VERSION_RELEASE = 55;
public static final String MAGE_VERSION_RELEASE_INFO = "V2"; // V1, V1a, V1b for releases; V1-beta3, V1-beta4 for betas
public static final String MAGE_VERSION_RELEASE_INFO = "V3"; // V1, V1a, V1b for releases; V1-beta3, V1-beta4 for betas
// strict mode
// Each update requires a strict version

View file

@ -59,6 +59,7 @@ public class Legacy extends Constructed {
banned.add("Necropotence");
banned.add("Oath of Druids");
banned.add("Oko, Thief of Crowns");
banned.add("Psychic Frog");
banned.add("Ragavan, Nimble Pilferer");
banned.add("Sensei's Divining Top");
banned.add("Skullclamp");
@ -73,6 +74,7 @@ public class Legacy extends Constructed {
banned.add("Treasure Cruise");
banned.add("Underworld Breach");
banned.add("Vampiric Tutor");
banned.add("Vexing Bauble");
banned.add("Wheel of Fortune");
banned.add("Windfall");
banned.add("Wrenn and Six");

View file

@ -23,6 +23,7 @@ public class Modern extends Constructed {
}
}
banned.add("Amped Raptor");
banned.add("Ancient Den");
banned.add("Arcum's Astrolabe");
banned.add("Birthing Pod");
@ -35,21 +36,19 @@ public class Modern extends Constructed {
banned.add("Dig Through Time");
banned.add("Dread Return");
banned.add("Eye of Ugin");
banned.add("Faithless Looting");
banned.add("Field of the Dead");
banned.add("Fury");
banned.add("Gitaxian Probe");
banned.add("Glimpse of Nature");
banned.add("Golgari Grave-Troll");
banned.add("Great Furnace");
banned.add("Green Sun's Zenith");
banned.add("Grief");
banned.add("Hogaak, Arisen Necropolis");
banned.add("Hypergenesis");
banned.add("Jegantha, the Wellspring");
banned.add("Krark-Clan Ironworks");
banned.add("Lurrus of the Dream-Den");
banned.add("Mental Misstep");
banned.add("Mox Opal");
banned.add("Mycosynth Lattice");
banned.add("Mystic Sanctuary");
banned.add("Nadu, Winged Wisdom");
@ -64,8 +63,8 @@ public class Modern extends Constructed {
banned.add("Sensei's Divining Top");
banned.add("Simian Spirit Guide");
banned.add("Skullclamp");
banned.add("Splinter Twin");
banned.add("Summer Bloom");
banned.add("The One Ring");
banned.add("Tibalt's Trickery");
banned.add("Treasure Cruise");
banned.add("Tree of Tales");

View file

@ -31,6 +31,7 @@ public class Pioneer extends Constructed {
banned.add("Flooded Strand");
banned.add("Geological Appraiser");
banned.add("Inverter of Truth");
banned.add("Jegantha, the Wellspring");
banned.add("Karn, the Great Creator");
banned.add("Kethis, the Hidden Hand");
banned.add("Leyline of Abundance");

View file

@ -11,7 +11,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.counters.CounterType;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.PowerPredicate;
import mage.target.common.TargetCreaturePermanent;
@ -43,7 +42,7 @@ public final class AbzanCharm extends CardImpl {
this.getSpellAbility().addMode(mode);
// *Distribute two +1/+1 counters among one or two target creatures.
mode = new Mode(new DistributeCountersEffect(2, "one or two target creatures"));
mode = new Mode(new DistributeCountersEffect());
mode.addTarget(new TargetCreaturePermanentAmount(2));
this.getSpellAbility().addMode(mode);

View file

@ -26,7 +26,7 @@ public final class AerialVolley extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{G}");
// Aerial Volley deals 3 damage divided as you choose among one, two, or three target creatures with flying.
this.getSpellAbility().addEffect(new DamageMultiEffect(3));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(3, filter));
}

View file

@ -9,7 +9,6 @@ import mage.abilities.effects.common.counter.DistributeCountersEffect;
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.predicate.Predicates;
@ -38,7 +37,7 @@ public final class AjaniMentorOfHeroes extends CardImpl {
this.setStartingLoyalty(4);
// +1: Distribute three +1/+1 counters among one, two, or three target creatures you control
Ability ability = new LoyaltyAbility(new DistributeCountersEffect(3, "one, two, or three target creatures you control"), 1);
Ability ability = new LoyaltyAbility(new DistributeCountersEffect(), 1);
ability.addTarget(new TargetCreaturePermanentAmount(3, StaticFilters.FILTER_CONTROLLED_CREATURES));
this.addAbility(ability);

View file

@ -15,11 +15,9 @@ import mage.constants.*;
import mage.abilities.keyword.CompleatedAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.command.emblems.AjaniSleeperAgentEmblem;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetCreaturePermanentAmount;
/**
@ -42,12 +40,10 @@ public final class AjaniSleeperAgent extends CardImpl {
this.addAbility(new LoyaltyAbility(new AjaniSleeperAgentEffect(), 1));
// 3: Distribute three +1/+1 counters among up to three target creatures. They gain vigilance until end of turn.
Ability ability = new LoyaltyAbility(new DistributeCountersEffect(3, "up to three target creatures"), -3);
Ability ability = new LoyaltyAbility(new DistributeCountersEffect()
.setText("distribute three +1/+1 counters among up to three target creatures"), -3);
ability.addEffect(new GainAbilityTargetEffect(VigilanceAbility.getInstance()).setText("They gain vigilance until end of turn"));
Target target = new TargetCreaturePermanentAmount(3);
target.setMinNumberOfTargets(0);
target.setMaxNumberOfTargets(3);
ability.addTarget(target);
ability.addTarget(new TargetCreaturePermanentAmount(3, 0, 3));
this.addAbility(ability);
// 6: You get an emblem with "Whenever you cast a creature or planeswalker spell, target opponent gets two poison counters."

View file

@ -32,7 +32,7 @@ public final class AmethystDragon extends AdventureCard {
// Explosive Crystal
// Explosive Crystal deals 4 damage divided as you choose among any number of targets.
this.getSpellCard().getSpellAbility().addEffect(new DamageMultiEffect(4));
this.getSpellCard().getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellCard().getSpellAbility().addTarget(new TargetAnyTargetAmount(4));
this.finalizeAdventure();

View file

@ -34,7 +34,7 @@ public final class AngelOfSalvation extends CardImpl {
this.addAbility(new ConvokeAbility());
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Angel of Salvation enters the battlefield, prevent the next 5 damage that would be dealt this turn to any number of target creatures and/or players, divided as you choose.
// When Angel of Salvation enters, prevent the next 5 damage that would be dealt this turn to any number of targets, divided as you choose.
Ability ability = new EntersBattlefieldTriggeredAbility(new PreventDamageToTargetMultiAmountEffect(Duration.EndOfTurn, 5));
ability.addTarget(new TargetAnyTargetAmount(5));
this.addAbility(ability);

View file

@ -17,7 +17,7 @@ public final class ArcLightning extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{R}");
// Arc Lightning deals 3 damage divided as you choose among one, two, or three targets.
this.getSpellAbility().addEffect(new DamageMultiEffect(3));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetAnyTargetAmount(3));
}

View file

@ -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.target.common.TargetAnyTargetAmount;
/**
@ -29,7 +28,7 @@ public final class ArcMage extends CardImpl {
this.toughness = new MageInt(2);
// {2}{R}, {tap}, Discard a card: Arc Mage deals 2 damage divided as you choose among one or two targets.
Ability ability = new SimpleActivatedAbility(new DamageMultiEffect(2), new ManaCostsImpl<>("{2}{R}"));
Ability ability = new SimpleActivatedAbility(new DamageMultiEffect(), new ManaCostsImpl<>("{2}{R}"));
ability.addCost(new TapSourceCost());
ability.addCost(new DiscardCardCost());
ability.addTarget(new TargetAnyTargetAmount(2));

View file

@ -9,7 +9,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.target.common.TargetCreaturePermanentAmount;
@ -28,7 +27,7 @@ public final class ArmamentCorps extends CardImpl {
this.toughness = new MageInt(4);
// When Armament Corps enters the battlefield, distribute two +1/+1 counters among one or two target creatures you control.
Ability ability = new EntersBattlefieldTriggeredAbility(new DistributeCountersEffect(2, "one or two target creatures you control"), false);
Ability ability = new EntersBattlefieldTriggeredAbility(new DistributeCountersEffect(), false);
ability.addTarget(new TargetCreaturePermanentAmount(2, StaticFilters.FILTER_CONTROLLED_CREATURES));
this.addAbility(ability);
}

View file

@ -27,7 +27,7 @@ public final class ArrowVolleyTrap extends CardImpl {
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl<>("{1}{W}"), ArrowVolleyTrapCondition.instance));
// Arrow Volley Trap deals 5 damage divided as you choose among any number of target attacking creatures.
this.getSpellAbility().addEffect(new DamageMultiEffect(5));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(5, StaticFilters.FILTER_ATTACKING_CREATURES));
}

View file

@ -59,10 +59,10 @@ public final class AureliasFury extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{R}{W}");
// Aurelia's Fury deals X damage divided as you choose among any number of target creatures and/or players.
// 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.
DynamicValue xValue = GetXValue.instance;
this.getSpellAbility().addEffect(new DamageMultiEffect(xValue));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addEffect(new AureliasFuryEffect());
this.getSpellAbility().addTarget(new TargetAnyTargetAmount(xValue));
this.getSpellAbility().addWatcher(new AureliasFuryDamagedByWatcher());

View file

@ -31,9 +31,9 @@ public final class AvacynsJudgment extends CardImpl {
ability.setRuleAtTheTop(true);
this.addAbility(ability);
// Avacyn's Judgment deals 2 damage divided as you choose among any number of target creatures and/or players. If Avacyn's Judgment's madness cost was paid, it deals X damage divided as you choose among those creatures and/or players instead.
// Avacyn's Judgment deals 2 damage divided as you choose among any number of targets. If this spell's madness cost was paid, it deals X damage divided as you choose among those creatures and/or players instead.
DynamicValue xValue = new AvacynsJudgmentManacostVariableValue();
Effect effect = new DamageMultiEffect(xValue);
Effect effect = new DamageMultiEffect();
effect.setText("{this} deals 2 damage divided as you choose among any number of targets. If this spell's madness cost was paid, it deals X damage divided as you choose among those permanents and/or players instead.");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addTarget(new TargetAnyTargetAmount(xValue));

View file

@ -115,8 +115,6 @@ class AwakenTheMaelstromEffect extends OneShotEffect {
return;
}
TargetPermanentAmount target = new TargetCreaturePermanentAmount(3, StaticFilters.FILTER_CONTROLLED_CREATURE);
target.setMinNumberOfTargets(1);
target.setMaxNumberOfTargets(3);
target.withNotTarget(true);
target.withChooseHint("to distribute counters");
target.chooseTarget(outcome, player.getId(), source, game);

View file

@ -0,0 +1,113 @@
package mage.cards.b;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ChooseCreatureTypeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import java.util.UUID;
/**
* @author PurpleCrowbar
*/
public final class BannerOfKinship extends CardImpl {
public BannerOfKinship(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}");
// As this artifact enters, choose a creature type. This artifact enters with a fellowship counter on it for each creature you control of the chosen type.
AsEntersBattlefieldAbility ability = new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.BoostCreature));
ability.addEffect(new BannerOfKinshipEffect());
this.addAbility(ability);
// Creatures you control of the chosen type get +1/+1 for each fellowship counter on this artifact.
this.addAbility(new SimpleStaticAbility(new BannerOfKinshipBoostEffect()));
}
private BannerOfKinship(final BannerOfKinship card) {
super(card);
}
@Override
public BannerOfKinship copy() {
return new BannerOfKinship(this);
}
}
class BannerOfKinshipEffect extends OneShotEffect {
BannerOfKinshipEffect() {
super(Outcome.BoostCreature);
this.staticText = "This artifact enters with a fellowship counter on it for each creature you control of the chosen type";
}
private BannerOfKinshipEffect(final BannerOfKinshipEffect effect) {
super(effect);
}
@Override
public BannerOfKinshipEffect copy() {
return new BannerOfKinshipEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanentEntering(source.getSourceId());
if (controller == null || permanent == null) {
return false;
}
SubType subtype = (SubType) game.getState().getValue(source.getSourceId() + "_type");
int amount = game.getBattlefield().getAllActivePermanents(new FilterControlledCreaturePermanent(subtype), source.getControllerId(), game).size();
if (amount > 0) {
permanent.addCounters(CounterType.FELLOWSHIP.createInstance(amount), source.getControllerId(), source, game);
}
return true;
}
}
class BannerOfKinshipBoostEffect extends ContinuousEffectImpl {
BannerOfKinshipBoostEffect() {
super(Duration.WhileOnBattlefield, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature);
staticText = "Creatures you control of the chosen type get +1/+1 for each fellowship counter on this artifact";
}
private BannerOfKinshipBoostEffect(final BannerOfKinshipBoostEffect effect) {
super(effect);
}
@Override
public BannerOfKinshipBoostEffect copy() {
return new BannerOfKinshipBoostEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
SubType subtype = (SubType) game.getState().getValue(permanent.getId() + "_type");
if (subtype != null) {
for (Permanent perm : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURES, source.getControllerId(), game)) {
if (perm.hasSubtype(subtype, game)) {
int boost = permanent.getCounters(game).getCount(CounterType.FELLOWSHIP);
perm.addPower(boost);
perm.addToughness(boost);
}
}
}
}
return true;
}
}

View file

@ -26,10 +26,7 @@ public final class BiogenicUpgrade extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{G}{G}");
// Distribute three +1/+1 counters among one, two, or three target creatures, then double the number of +1/+1 counters on each of those creatures.
this.getSpellAbility().addEffect(new DistributeCountersEffect(
3,
"one, two, or three target creatures"
));
this.getSpellAbility().addEffect(new DistributeCountersEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(3));
this.getSpellAbility().addEffect(new BiogenicUpgradeEffect());
}

View file

@ -46,7 +46,7 @@ public final class BlasterHulk extends CardImpl {
// Whenever Blaster Hulk attacks, you get {E}{E}, then you may pay eight {E}. When you do, Blaster Hulk deals 8 damage divided as you choose among up to eight targets.
Ability ability = new AttacksTriggeredAbility(new GetEnergyCountersControllerEffect(2));
ReflexiveTriggeredAbility reflexiveAbility = new ReflexiveTriggeredAbility(new DamageMultiEffect(8)
ReflexiveTriggeredAbility reflexiveAbility = new ReflexiveTriggeredAbility(new DamageMultiEffect()
.setText("{this} deals 8 damage divided as you choose among up to eight targets"), false);
reflexiveAbility.addTarget(new TargetAnyTargetAmount(8));
ability.addEffect(new DoWhenCostPaid(reflexiveAbility, new PayEnergyCost(8),

View file

@ -79,8 +79,7 @@ class BlessingOfFrostEffect extends OneShotEffect {
int snow = ManaPaidSourceWatcher.getSnowPaid(source.getId(), game);
int potentialTarget = game.getBattlefield().count(StaticFilters.FILTER_CONTROLLED_CREATURE, player.getId(), source, game);
if (snow > 0 && potentialTarget > 0) {
TargetAmount target = new TargetCreaturePermanentAmount(snow, StaticFilters.FILTER_CONTROLLED_CREATURE);
target.setMinNumberOfTargets(1);
TargetAmount target = new TargetCreaturePermanentAmount(snow, 0, snow, StaticFilters.FILTER_CONTROLLED_CREATURE);
target.withNotTarget(true);
target.chooseTarget(outcome, player.getId(), source, game);
for (UUID targetId : target.getTargets()) {

View file

@ -5,7 +5,6 @@ import mage.abilities.keyword.MiracleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.counters.CounterType;
import mage.target.common.TargetCreaturePermanentAmount;
import java.util.UUID;
@ -19,7 +18,7 @@ public final class BlessingsOfNature extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{G}");
// Distribute four +1/+1 counters among any number of target creatures.
this.getSpellAbility().addEffect(new DistributeCountersEffect(4, "any number of target creatures"));
this.getSpellAbility().addEffect(new DistributeCountersEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(4));
this.addAbility(new MiracleAbility("{G}"));

View file

@ -28,9 +28,14 @@ public final class BogardanHellkite extends CardImpl {
this.power = new MageInt(5);
this.toughness = new MageInt(5);
// Flash
this.addAbility(FlashAbility.getInstance());
// Flying
this.addAbility(FlyingAbility.getInstance());
Ability ability = new EntersBattlefieldTriggeredAbility(new DamageMultiEffect(5, "it"), false);
// When Bogardan Hellkite enters, it deals 5 damage divided as you choose among any number of targets.
Ability ability = new EntersBattlefieldTriggeredAbility(new DamageMultiEffect("it"), false);
ability.addTarget(new TargetAnyTargetAmount(5));
this.addAbility(ability);
}

View file

@ -17,7 +17,7 @@ public final class Boulderfall extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{6}{R}{R}");
// Boulderfall deals 5 damage divided as you choose among any number of targets.
this.getSpellAbility().addEffect(new DamageMultiEffect(5));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetAnyTargetAmount(5));
}

View file

@ -7,7 +7,6 @@ import mage.abilities.effects.common.counter.DistributeCountersEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.counters.CounterType;
import mage.filter.common.FilterOwnedCard;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.target.common.TargetCardInHand;
@ -34,10 +33,7 @@ public final class BountyOfTheHunt extends CardImpl {
this.addAbility(new AlternativeCostSourceAbility(new ExileFromHandCost(new TargetCardInHand(filter))));
// Distribute three +1/+1 counters among one, two, or three target creatures. For each +1/+1 counter you put on a creature this way, remove a +1/+1 counter from that creature at the beginning of the next cleanup step.
this.getSpellAbility().addEffect(new DistributeCountersEffect(
3,
"one, two, or three target creatures"
).withRemoveAtEndOfTurn());
this.getSpellAbility().addEffect(new DistributeCountersEffect().withRemoveAtEndOfTurn());
this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(3));
}

View file

@ -16,7 +16,7 @@ import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.Target;
import mage.target.common.TargetPermanentAmount;
import mage.target.common.TargetCreaturePermanentAmount;
import java.util.UUID;
@ -37,7 +37,7 @@ public final class Broodlord extends CardImpl {
// Brood Telepathy -- When Broodlord enters the battlefield, distribute X +1/+1 counters among any number of other target creatures you control.
Ability ability = new EntersBattlefieldTriggeredAbility(new BroodlordEffect());
ability.addTarget(new TargetPermanentAmount(GetXValue.instance, StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE));
ability.addTarget(new TargetCreaturePermanentAmount(GetXValue.instance, StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE));
this.addAbility(ability.withFlavorWord("Brood Telepathy"));
}

View file

@ -53,11 +53,11 @@ public final class CaptainAmericaFirstAvenger extends CardImpl {
// Throw ... {3}, Unattach an Equipment from Captain America: He deals damage equal to that Equipments mana value divided as you choose among one, two, or three targets.
Ability ability = new SimpleActivatedAbility(
new DamageMultiEffect(CaptainAmericaFirstAvengerValue.instance).setText(
new DamageMultiEffect().setText(
"he deals damage equal to that Equipment's mana value divided as you choose among one, two, or three targets."),
new GenericManaCost(3));
ability.addCost(new CaptainAmericaFirstAvengerUnattachCost());
ability.addTarget(new TargetAnyTargetAmount(CaptainAmericaFirstAvengerValue.instance, 3));
ability.addTarget(new TargetAnyTargetAmount(CaptainAmericaFirstAvengerValue.instance, 1, 3));
this.addAbility(ability.withFlavorWord("Throw ..."));
// ... Catch At the beginning of combat on your turn, attach up to one target Equipment you control to Captain America.

View file

@ -26,7 +26,7 @@ import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetAttackingCreature;
import mage.target.common.TargetPermanentAmount;
import mage.target.common.TargetCreaturePermanentAmount;
/**
*
@ -40,11 +40,8 @@ public final class CaseOfTheTrampledGarden extends CardImpl {
this.subtype.add(SubType.CASE);
// When this Case enters the battlefield, distribute two +1/+1 counters among one or two target creatures you control.
Ability initialAbility = new EntersBattlefieldTriggeredAbility(new DistributeCountersEffect(2,
"one or two target creatures you control"));
TargetPermanentAmount target = new TargetPermanentAmount(2, StaticFilters.FILTER_CONTROLLED_CREATURES);
target.setMinNumberOfTargets(1);
initialAbility.addTarget(target);
Ability initialAbility = new EntersBattlefieldTriggeredAbility(new DistributeCountersEffect());
initialAbility.addTarget(new TargetCreaturePermanentAmount(2, StaticFilters.FILTER_CONTROLLED_CREATURES));
// To solve -- Creatures you control have total power 8 or greater.
// Solved -- Whenever you attack, put a +1/+1 counter on target attacking creature. It gains trample until end of turn.
Ability solvedAbility = new ConditionalTriggeredAbility(

View file

@ -50,7 +50,7 @@ public final class ChandraFlameshaper extends CardImpl {
// -4: Chandra deals 8 damage divided as you choose among any number of target creatures and/or planeswalkers.
Ability minusFourAbility = new LoyaltyAbility(
new DamageMultiEffect(8, "{this}"), -4
new DamageMultiEffect(), -4
);
minusFourAbility.addTarget(new TargetCreatureOrPlaneswalkerAmount(8));
this.addAbility(minusFourAbility);

View file

@ -17,7 +17,7 @@ public final class ChandrasPyrohelix extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}");
// Chandra's Pyrohelix deals 2 damage divided as you choose among one or two targets.
this.getSpellAbility().addEffect(new DamageMultiEffect(2));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetAnyTargetAmount(2));
}

View file

@ -24,7 +24,7 @@ public final class Conflagrate extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{X}{R}");
// Conflagrate deals X damage divided as you choose among any number of targets.
this.getSpellAbility().addEffect(new DamageMultiEffect(GetXValue.instance));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetAnyTargetAmount(GetXValue.instance));
// Flashback-{R}{R}, Discard X cards.

View file

@ -38,10 +38,7 @@ public final class Contagion extends CardImpl {
// Distribute two -2/-1 counters among one or two target creatures.
this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(2));
this.getSpellAbility().addEffect(new DistributeCountersEffect(
CounterType.M2M1, 2,
"one or two target creatures"
));
this.getSpellAbility().addEffect(new DistributeCountersEffect(CounterType.M2M1));
}
private Contagion(final Contagion card) {

View file

@ -31,15 +31,9 @@ public final class CourtOfGarenbrig extends CardImpl {
this.addAbility(new EntersBattlefieldTriggeredAbility(new BecomesMonarchSourceEffect()).addHint(MonarchHint.instance));
// At the beginning of your upkeep, distribute two +1/+1 counters among up to two target creatures. Then if you're the monarch, double the number of +1/+1 counters on each creature you control.
Ability ability = new BeginningOfUpkeepTriggeredAbility(
new DistributeCountersEffect(
2, "up to two target creatures"
)
);
TargetCreaturePermanentAmount target = new TargetCreaturePermanentAmount(2);
target.setMinNumberOfTargets(0);
target.setMaxNumberOfTargets(2);
ability.addTarget(target);
Ability ability = new BeginningOfUpkeepTriggeredAbility(new DistributeCountersEffect()
.setText("distribute two +1/+1 counters among up to two target creatures"));
ability.addTarget(new TargetCreaturePermanentAmount(2, 0, 2));
ability.addEffect(new ConditionalOneShotEffect(
new DoubleCounterOnEachPermanentEffect(CounterType.P1P1, StaticFilters.FILTER_CONTROLLED_CREATURE),
MonarchIsSourceControllerCondition.instance

View file

@ -64,6 +64,7 @@ class CuratorsWardTriggeredAbility extends TriggeredAbilityImpl {
public CuratorsWardTriggeredAbility() {
super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(2), false);
setLeavesTheBattlefieldTrigger(true);
}
private CuratorsWardTriggeredAbility(final CuratorsWardTriggeredAbility ability) {

View file

@ -4,7 +4,6 @@ import mage.abilities.effects.common.counter.DistributeCountersEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.target.common.TargetCreaturePermanentAmount;
@ -19,10 +18,7 @@ public final class DefendTheCelestus extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{G}{G}");
// Distribute three +1/+1 counters among one, two, or three target creatures you control.
this.getSpellAbility().addEffect(new DistributeCountersEffect(
3,
"one, two, or three target creatures you control"
));
this.getSpellAbility().addEffect(new DistributeCountersEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(
3, StaticFilters.FILTER_CONTROLLED_CREATURES
));

View file

@ -18,7 +18,7 @@ public final class DeftDismissal extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{W}");
// Deft Dismissal deals 3 damage divided as you choose among one, two, or three target attacking or blocking creatures.
this.getSpellAbility().addEffect(new DamageMultiEffect(3));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(3, StaticFilters.FILTER_ATTACKING_OR_BLOCKING_CREATURES));
}

View file

@ -43,11 +43,8 @@ public final class DragonlordAtarka extends CardImpl {
this.addAbility(TrampleAbility.getInstance());
// When Dragonlord Atarka enters the battlefield, it deals 5 damage divided as you choose among any number of target creatures and/or planeswalkers your opponents control.
Ability ability = new EntersBattlefieldTriggeredAbility(new DamageMultiEffect(5, "it"), false);
TargetCreatureOrPlaneswalkerAmount target = new TargetCreatureOrPlaneswalkerAmount(5, filter);
target.setMinNumberOfTargets(1);
target.setMaxNumberOfTargets(5);
ability.addTarget(target);
Ability ability = new EntersBattlefieldTriggeredAbility(new DamageMultiEffect("it"), false);
ability.addTarget(new TargetCreatureOrPlaneswalkerAmount(5, filter));
this.addAbility(ability);
}

View file

@ -18,7 +18,7 @@ public final class Electrolyze extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}{R}");
// Electrolyze deals 2 damage divided as you choose among one or two targets.
this.getSpellAbility().addEffect(new DamageMultiEffect(2));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetAnyTargetAmount(2));
// Draw a card.
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("<br>"));

View file

@ -10,9 +10,7 @@ import mage.cards.AdventureCard;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.target.Target;
import mage.target.common.TargetCreaturePermanentAmount;
import java.util.UUID;
@ -37,14 +35,9 @@ public final class ElusiveOtter extends AdventureCard {
// Grove's Bounty
// Distribute X +1/+1 counters among any number of target creatures you control.
this.getSpellCard().getSpellAbility().addEffect(new DistributeCountersEffect(
CounterType.P1P1, GetXValue.instance,
"any number of target creatures you control"
));
Target target = new TargetCreaturePermanentAmount(GetXValue.instance, StaticFilters.FILTER_CONTROLLED_CREATURES);
target.setMinNumberOfTargets(0);
target.setMaxNumberOfTargets(Integer.MAX_VALUE);
this.getSpellCard().getSpellAbility().addTarget(target);
this.getSpellCard().getSpellAbility().addEffect(new DistributeCountersEffect());
this.getSpellCard().getSpellAbility().addTarget(
new TargetCreaturePermanentAmount(GetXValue.instance, StaticFilters.FILTER_CONTROLLED_CREATURES));
this.finalizeAdventure();
}

View file

@ -6,7 +6,6 @@ import mage.abilities.effects.common.counter.DistributeCountersEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.counters.CounterType;
import mage.target.common.TargetCreaturePermanentAmount;
/**
@ -19,7 +18,7 @@ public final class ElvenRite extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{G}");
// Distribute two +1/+1 counters among one or two target creatures.
this.getSpellAbility().addEffect(new DistributeCountersEffect(2, "one or two target creatures"));
this.getSpellAbility().addEffect(new DistributeCountersEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(2));
}

View file

@ -9,7 +9,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.TimingRule;
import mage.target.common.TargetAnyTargetAmount;
/**
@ -21,7 +20,7 @@ public final class Embolden extends CardImpl {
public Embolden(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}");
// Prevent the next 4 damage that would be dealt this turn to any number of target creatures and/or players, divided as you choose.
// Prevent the next 4 damage that would be dealt this turn to any number of targets, divided as you choose.
this.getSpellAbility().addEffect(new PreventDamageToTargetMultiAmountEffect(Duration.EndOfTurn, 4));
this.getSpellAbility().addTarget(new TargetAnyTargetAmount(4));

View file

@ -77,8 +77,7 @@ class FeastOfTheVictoriousDeadEffect extends OneShotEffect {
if (player == null || game.getBattlefield().count(StaticFilters.FILTER_CONTROLLED_CREATURE, player.getId(), source, game) < 1) {
return false;
}
TargetPermanentAmount target = new TargetCreaturePermanentAmount(amount, StaticFilters.FILTER_CONTROLLED_CREATURE);
target.setMinNumberOfTargets(1);
TargetPermanentAmount target = new TargetCreaturePermanentAmount(amount, 1, amount, StaticFilters.FILTER_CONTROLLED_CREATURE);
target.withNotTarget(true);
target.withChooseHint("to distribute " + amount + " counters");
target.chooseTarget(outcome, player.getId(), source, game);

View file

@ -22,7 +22,7 @@ public final class FieryJustice extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{R}{G}{W}");
// Fiery Justice deals 5 damage divided as you choose among any number of targets. Target opponent gains 5 life.
this.getSpellAbility().addEffect(new DamageMultiEffect(5));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetAnyTargetAmount(5));
Effect effect = new GainLifeTargetEffect(5);
effect.setTargetPointer(new SecondTargetPointer());

View file

@ -29,7 +29,7 @@ public final class FightWithFire extends CardImpl {
// Fight with Fire deals 5 damage to target creature. If this spell was kicked, it deals 10 damage divided as you choose among any number of targets instead.<i> (Those targets can include players and planeswalkers.)</i>
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new DamageMultiEffect(10),
new DamageMultiEffect(),
new DamageTargetEffect(5),
KickedCondition.ONCE,
"{this} deals 5 damage to target creature. If this spell was kicked, "

View file

@ -19,7 +19,7 @@ public final class FireAtWill extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R/W}{R/W}{R/W}");
// Fire at Will deals 3 damage divided as you choose among one, two, or three target attacking or blocking creatures.
this.getSpellAbility().addEffect(new DamageMultiEffect(3));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(3, StaticFilters.FILTER_ATTACKING_OR_BLOCKING_CREATURES));
}

View file

@ -26,7 +26,7 @@ public final class FireCovenant extends CardImpl {
// Fire Covenant deals X damage divided as you choose among any number of target creatures.
DynamicValue xValue = GetXValue.instance;
this.getSpellAbility().addEffect(new DamageMultiEffect(xValue));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(xValue));
}

View file

@ -18,7 +18,7 @@ public final class FireIce extends SplitCard {
// Fire
// Fire deals 2 damage divided as you choose among one or two targets.
getLeftHalfCard().getSpellAbility().addEffect(new DamageMultiEffect(2, "Fire"));
getLeftHalfCard().getSpellAbility().addEffect(new DamageMultiEffect());
getLeftHalfCard().getSpellAbility().addTarget(new TargetAnyTargetAmount(2));
// Ice

View file

@ -17,7 +17,7 @@ public final class FlamesOfTheFirebrand extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{R}");
// Flames of the Firebrand deals 3 damage divided as you choose among one, two, or three targets.
this.getSpellAbility().addEffect(new DamageMultiEffect(3));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetAnyTargetAmount(3));
}

View file

@ -32,7 +32,7 @@ public final class Flameshot extends CardImpl {
this.addAbility(new AlternativeCostSourceAbility(new DiscardTargetCost(new TargetCardInHand(filter))));
// Flameshot deals 3 damage divided as you choose among one, two, or three target creatures.
this.getSpellAbility().addEffect(new DamageMultiEffect(3));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(3));
}

View file

@ -17,7 +17,7 @@ public final class ForkedBolt extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{R}");
// Forked Bolt deals 2 damage divided as you choose among one or two targets.
this.getSpellAbility().addEffect(new DamageMultiEffect(2));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetAnyTargetAmount(2));
}

View file

@ -6,7 +6,6 @@ import mage.abilities.effects.common.DamageMultiEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.target.Target;
import mage.target.common.TargetCreaturePermanentAmount;
/**
@ -19,9 +18,8 @@ public final class ForkedLightning extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}");
// Forked Lightning deals 4 damage divided as you choose among one, two, or three target creatures.
this.getSpellAbility().addEffect(new DamageMultiEffect(4)
.setText("{this} deals 4 damage divided as you choose among one, two, or three target creatures"));
Target target=new TargetCreaturePermanentAmount(4);target.setMaxNumberOfTargets(3);this.getSpellAbility().addTarget(target);
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(4, 1, 3));
}
private ForkedLightning(final ForkedLightning card) {

View file

@ -43,7 +43,7 @@ public final class Fury extends CardImpl {
// When Fury enters the battlefield, it deals 4 damage divided as you choose among any number of target creatures and/or planeswalkers.
Ability ability = new EntersBattlefieldTriggeredAbility(
new DamageMultiEffect(4, "it")
new DamageMultiEffect("it")
);
ability.addTarget(new TargetCreatureOrPlaneswalkerAmount(4));
this.addAbility(ability);

View file

@ -26,7 +26,7 @@ public final class GangOfDevils extends CardImpl {
this.toughness = new MageInt(3);
// When Gang of Devils dies, it deals 3 damage divided as you choose among one, two, or three targets.
Ability ability = new DiesSourceTriggeredAbility(new DamageMultiEffect(3, "it"));
Ability ability = new DiesSourceTriggeredAbility(new DamageMultiEffect("it"));
ability.addTarget(new TargetAnyTargetAmount(3));
this.addAbility(ability);
}

View file

@ -46,7 +46,7 @@ public final class GhiredsBelligerence extends CardImpl {
class GhiredsBelligerenceEffect extends OneShotEffect {
private static final DamageMultiEffect effect = new DamageMultiEffect(GetXValue.instance);
private static final DamageMultiEffect effect = new DamageMultiEffect();
GhiredsBelligerenceEffect() {
super(Outcome.Benefit);

View file

@ -11,7 +11,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.counters.CounterType;
import mage.target.common.TargetCreaturePermanentAmount;
import java.util.UUID;
@ -32,9 +31,7 @@ public final class GlintWeaver extends CardImpl {
this.addAbility(ReachAbility.getInstance());
// When Glint Weaver enters the battlefield, distribute three +1/+1 counters among one, two, or three target creatures, then you gain life equal to the greatest toughness among creatures you control.
Ability ability = new EntersBattlefieldTriggeredAbility(new DistributeCountersEffect(
3, "one, two, or three target creatures"
));
Ability ability = new EntersBattlefieldTriggeredAbility(new DistributeCountersEffect());
ability.addEffect(new GainLifeEffect(GreatestToughnessAmongControlledCreaturesValue.instance)
.setText(", then you gain life equal to the greatest toughness among creatures you control"));
ability.addTarget(new TargetCreaturePermanentAmount(3));

View file

@ -28,6 +28,7 @@ public final class GracefulAntelope extends CardImpl {
// Plainswalk
this.addAbility(new PlainswalkAbility());
// Whenever Graceful Antelope deals combat damage to a player, you may have target land become a Plains until Graceful Antelope leaves the battlefield.
Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new BecomesBasicLandTargetEffect(Duration.UntilSourceLeavesBattlefield, SubType.PLAINS), true);
ability.addTarget(new TargetLandPermanent());

View file

@ -19,7 +19,7 @@ public final class HailOfArrows extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{W}");
// Hail of Arrows deals X damage divided as you choose among any number of target attacking creatures.
this.getSpellAbility().addEffect(new DamageMultiEffect(GetXValue.instance));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(GetXValue.instance, StaticFilters.FILTER_ATTACKING_CREATURES));
}

View file

@ -42,7 +42,7 @@ public final class HavengulLaboratory extends CardImpl {
ability.addCost(new TapSourceCost());
this.addAbility(ability);
// At the beginning of your end step, if you sacrificed three or more Clues this turn, transform Hawkins National Laboratory.
// At the beginning of your end step, if you sacrificed three or more Clues this turn, transform Havengul Laboratory.
this.addAbility(new TransformAbility());
this.addAbility(new BeginningOfEndStepTriggeredAbility(
TargetController.YOU, new TransformSourceEffect(),

View file

@ -22,6 +22,7 @@ import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCardInYourGraveyard;
import mage.util.CardUtil;
import java.util.HashSet;
import java.util.Set;
@ -35,7 +36,6 @@ public final class HavengulMystery extends CardImpl {
public HavengulMystery(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
this.supertype.add(SuperType.LEGENDARY);
this.nightCard = true;
// When this land transforms into Havengul Mystery, return target creature card from your graveyard to the battlefield.
@ -63,7 +63,7 @@ public final class HavengulMystery extends CardImpl {
}
static String makeKey(Ability source, Game game) {
return "HavengulMystery_" + source.getSourceId() + '_' + source.getSourceObjectZoneChangeCounter();
return "HavengulMystery_" + source.getSourceId() + '_' + CardUtil.getActualSourceObjectZoneChangeCounter(game, source);
}
}
@ -112,6 +112,7 @@ class HavengulMysteryLeavesAbility extends TriggeredAbilityImpl {
HavengulMysteryLeavesAbility() {
super(Zone.BATTLEFIELD, new TransformSourceEffect());
setLeavesTheBattlefieldTrigger(true);
}
private HavengulMysteryLeavesAbility(final HavengulMysteryLeavesAbility ability) {
@ -131,7 +132,12 @@ class HavengulMysteryLeavesAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
Set<MageObjectReference> morSet = (Set<MageObjectReference>) game.getState().getValue(HavengulMystery.makeKey(this, game));
if (zEvent.getFromZone() != Zone.BATTLEFIELD) {
return false;
}
String key = HavengulMystery.makeKey(this, game);
Set<MageObjectReference> morSet = (Set<MageObjectReference>) game.getState().getValue(key);
return morSet != null
&& !morSet.isEmpty()
&& morSet.stream().anyMatch(mor -> mor.refersTo(zEvent.getTarget(), game));

View file

@ -29,7 +29,7 @@ public final class IgniteDisorder extends CardImpl {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{R}");
// Ignite Disorder deals 3 damage divided as you choose among one, two, or three target white and/or blue creatures.
this.getSpellAbility().addEffect(new DamageMultiEffect(3));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(3, filter));
}

View file

@ -29,7 +29,7 @@ public final class ImpactResonance extends CardImpl {
// Impact Resonance deals X damage divided as you choose among any number of target creatures, where X is the greatest amount of damage dealt by a source to a permanent or player this turn.
DynamicValue xValue = GreatestAmountOfDamageDealtValue.instance;
Effect effect = new DamageMultiEffect(xValue);
Effect effect = new DamageMultiEffect();
effect.setText("{this} deals X damage divided as you choose among any number of target creatures, where X is the greatest amount of damage dealt by a source to a permanent or player this turn");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(xValue));

View file

@ -37,7 +37,7 @@ public final class InfernalHarvest extends CardImpl {
this.getSpellAbility().addCost(new InfernalHarvestAdditionalCost());
// Infernal Harvest deals X damage divided as you choose among any number of target creatures.
this.getSpellAbility().addEffect(new DamageMultiEffect(GetXValue.instance));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(GetXValue.instance));
}

View file

@ -30,7 +30,7 @@ public final class InfernoTitan extends CardImpl {
this.addAbility(new SimpleActivatedAbility(new BoostSourceEffect(1, 0, Duration.EndOfTurn), new ColoredManaCost(ColoredManaSymbol.R)));
// Whenever Inferno Titan enters the battlefield or attacks, it deals 3 damage divided as you choose among one, two, or three targets.
Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility(new DamageMultiEffect(3, "it"));
Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility(new DamageMultiEffect("it"));
ability.addTarget(new TargetAnyTargetAmount(3));
this.addAbility(ability);
}

View file

@ -85,7 +85,7 @@ class InvokeJusticeEffect extends OneShotEffect {
if (!game.getBattlefield().contains(filter, source, game, 1)) {
return false;
}
TargetPermanentAmount target = new TargetPermanentAmount(4, filter);
TargetPermanentAmount target = new TargetPermanentAmount(4, 0, filter);
target.withNotTarget(true);
target.chooseTarget(outcome, player.getId(), source, game);
for (UUID targetId : target.getTargets()) {

View file

@ -1,10 +1,11 @@
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.mana.DynamicManaAbility;
import mage.abilities.mana.GreenManaAbility;
import mage.cards.CardImpl;
@ -19,7 +20,9 @@ import mage.filter.StaticFilters;
*/
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}, "");
@ -33,7 +36,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)));
this.addAbility(new DynamicManaAbility(Mana.GreenMana(1), new PermanentsOnBattlefieldCount(StaticFilters.FILTER_PERMANENT_CREATURE_CONTROLLED)).addHint(hint));
}
private ItlimocCradleOfTheSun(final ItlimocCradleOfTheSun card) {

View file

@ -7,9 +7,8 @@ import mage.abilities.keyword.CraftAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.target.common.TargetPermanentAmount;
import mage.target.common.TargetCreaturePermanentAmount;
import java.util.UUID;
@ -23,12 +22,8 @@ public final class JadeSeedstones extends CardImpl {
this.secondSideCardClazz = mage.cards.j.JadeheartAttendant.class;
// When Jade Seedstones enters the battlefield, distribute three +1/+1 counters among one, two, or three target creatures you control.
Ability ability = new EntersBattlefieldTriggeredAbility(new DistributeCountersEffect(
3, "one, two, or three target creatures you control"
));
TargetPermanentAmount target = new TargetPermanentAmount(3, StaticFilters.FILTER_CONTROLLED_CREATURES);
target.setMinNumberOfTargets(1);
ability.addTarget(target);
Ability ability = new EntersBattlefieldTriggeredAbility(new DistributeCountersEffect());
ability.addTarget(new TargetCreaturePermanentAmount(3, StaticFilters.FILTER_CONTROLLED_CREATURES));
this.addAbility(ability);
// Craft with creature {5}{G}{G}

View file

@ -30,7 +30,7 @@ public final class JawsOfStone extends CardImpl {
// Jaws of Stone deals X damage divided as you choose among any number of targets, where X is the number of Mountains you control as you cast this spell.
PermanentsOnBattlefieldCount mountains = new PermanentsOnBattlefieldCount(filter, null);
Effect effect = new DamageMultiEffect(mountains);
Effect effect = new DamageMultiEffect();
effect.setText(rule);
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addTarget(new TargetAnyTargetAmount(mountains));

View file

@ -13,7 +13,6 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.counters.CounterType;
import mage.target.common.TargetCreaturePermanentAmount;
/**
@ -33,7 +32,7 @@ public final class JuganTheRisingStar extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Jugan, the Rising Star dies, you may distribute five +1/+1 counters among any number of target creatures.
Ability ability = new DiesSourceTriggeredAbility(new DistributeCountersEffect(5, "any number of target creatures"), true);
Ability ability = new DiesSourceTriggeredAbility(new DistributeCountersEffect(), true);
ability.addTarget(new TargetCreaturePermanentAmount(5));
this.addAbility(ability);
}

View file

@ -11,7 +11,6 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.filter.StaticFilters;
import mage.target.common.TargetControlledPermanent;
import mage.target.common.TargetAnyTargetAmount;
/**
@ -29,7 +28,7 @@ public final class KuldothaFlamefiend extends CardImpl {
// When Kuldotha Flamefiend enters the battlefield, you may sacrifice an artifact. If you do, Kuldotha Flamefiend deals 4 damage divided as you choose among any number of targets.
EntersBattlefieldTriggeredAbility ability =
new EntersBattlefieldTriggeredAbility(new DoIfCostPaid(new DamageMultiEffect(4), new SacrificeTargetCost(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT_AN)), false);
new EntersBattlefieldTriggeredAbility(new DoIfCostPaid(new DamageMultiEffect(), new SacrificeTargetCost(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT_AN)), false);
ability.addTarget(new TargetAnyTargetAmount(4));
this.addAbility(ability);
}

View file

@ -15,10 +15,8 @@ import mage.abilities.keyword.LifelinkAbility;
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.target.TargetAmount;
import mage.target.common.TargetCreaturePermanentAmount;
import mage.watchers.common.PlayerGainedLifeWatcher;
@ -44,18 +42,13 @@ public final class LathielTheBounteousDawn extends CardImpl {
// 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(
1, ""
), false),
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."
);
TargetAmount target = new TargetCreaturePermanentAmount(
ability.addTarget(new TargetCreaturePermanentAmount(
LathielTheBounteousDawnValue.instance,
StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE
);
target.setMinNumberOfTargets(0);
ability.addTarget(target);
StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE));
this.addAbility(ability.addHint(LathielTheBounteousDawnValue.getHint()), new PlayerGainedLifeWatcher());
}

View file

@ -11,7 +11,6 @@ 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.target.Target;
@ -57,7 +56,8 @@ enum LivingInfernoAdjuster implements TargetAdjuster {
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(ability.getSourceId());
if (sourcePermanent != null) {
ability.getTargets().clear();
ability.addTarget(new TargetCreaturePermanentAmount(sourcePermanent.getPower().getValue()));
int power = sourcePermanent.getPower().getValue();
ability.addTarget(new TargetCreaturePermanentAmount(power, 0, power));
}
}
}

View file

@ -6,7 +6,6 @@ import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.condition.Condition;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
@ -51,11 +50,10 @@ public class LukkaBoundToRuin extends CardImpl {
// 4: Lukka deals X damage divided as you choose among any number of target creatures and/or planeswalkers,
// where X is the greatest power among creatures you controlled as you activated this ability.
DynamicValue xValue = GreatestPowerAmongControlledCreaturesValue.instance;
DamageMultiEffect damageMultiEffect = new DamageMultiEffect(xValue);
DamageMultiEffect damageMultiEffect = new DamageMultiEffect();
damageMultiEffect.setText("Lukka deals X damage divided as you choose " +
"among any number of target creatures and/or planeswalkers, " +
"where X is the greatest power among creatures you controlled as you activated this ability.");
"where X is the greatest power among creatures you control as you activate this ability.");
ability = new LoyaltyAbility(damageMultiEffect, -4);
ability.setTargetAdjuster(LukkaBoundToRuinAdjuster.instance);
this.addAbility(ability);
@ -135,9 +133,6 @@ enum LukkaBoundToRuinAdjuster implements TargetAdjuster {
// Maximum targets is equal to the damage - as each target need to be assigned at least 1 damage
ability.getTargets().clear();
int xValue = GreatestPowerAmongControlledCreaturesValue.instance.calculate(game, ability, null);
TargetCreatureOrPlaneswalkerAmount targetCreatureOrPlaneswalkerAmount = new TargetCreatureOrPlaneswalkerAmount(xValue);
targetCreatureOrPlaneswalkerAmount.setMinNumberOfTargets(0);
targetCreatureOrPlaneswalkerAmount.setMaxNumberOfTargets(xValue);
ability.addTarget(targetCreatureOrPlaneswalkerAmount);
ability.addTarget(new TargetCreatureOrPlaneswalkerAmount(xValue, 0, xValue));
}
}

View file

@ -21,7 +21,7 @@ public final class MagicMissile extends CardImpl {
this.addAbility(new CantBeCounteredSourceAbility().setRuleAtTheTop(true));
// Magic Missile deals 3 damage divided as you choose among one, two, or three targets.
this.getSpellAbility().addEffect(new DamageMultiEffect(3));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetAnyTargetAmount(3));
}

View file

@ -30,7 +30,7 @@ public final class MagmaOpus extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{6}{U}{R}");
// Magma Opus deals 4 damage divided as you choose among any number of targets. Tap two target permanents. Create a 4/4 blue and red Elemental creature token. Draw two cards.
this.getSpellAbility().addEffect(new DamageMultiEffect(4));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetAnyTargetAmount(4).withChooseHint("damage"));
this.getSpellAbility().addEffect(new TapTargetEffect("tap two target permanents").setTargetPointer(new SecondTargetPointer()));
this.getSpellAbility().addTarget(new TargetPermanent(2, StaticFilters.FILTER_PERMANENTS).withChooseHint("tap"));

View file

@ -30,7 +30,7 @@ public final class MagmaticCore extends CardImpl {
// At the beginning of your end step, Magmatic Core deals X damage divided as you choose among any number of target creatures, where X is the number of age counters on it.
DynamicValue value = new CountersSourceCount(CounterType.AGE);
Ability ability = new BeginningOfEndStepTriggeredAbility(
new DamageMultiEffect(value)
new DamageMultiEffect()
.setText("{this} deals X damage divided as you choose "
+ "among any number of target creatures,"
+ " where X is the number of age counters on it.")

View file

@ -22,7 +22,8 @@ public final class MeteorShower extends CardImpl {
// Meteor Shower deals X plus 1 damage divided as you choose among any number of targets.
DynamicValue xValue = new IntPlusDynamicValue(1, GetXValue.instance);
this.getSpellAbility().addEffect(new DamageMultiEffect(xValue));
this.getSpellAbility().addEffect(new DamageMultiEffect()
.setText("{this} deals X plus 1 damage divided as you choose among any number of targets"));
this.getSpellAbility().addTarget(new TargetAnyTargetAmount(xValue));
}

View file

@ -19,10 +19,11 @@ public final class MeteorSwarm extends CardImpl {
// Meteor Swarm deals 8 damage divided as you choose among X target creatures and/or planeswalkers.
this.getSpellAbility().addEffect(
new DamageMultiEffect(8).
new DamageMultiEffect().
setText("{this} deals 8 damage divided as you choose among X target creatures and/or planeswalkers.")
);
this.getSpellAbility().addTarget(new TargetCreatureOrPlaneswalkerAmount(8));
// Minimum number of targets will be overridden to X by the adjuster
this.getSpellAbility().addTarget(new TargetCreatureOrPlaneswalkerAmount(8, 1, 8));
this.getSpellAbility().setTargetAdjuster(new XTargetsCountAdjuster());
}

View file

@ -27,7 +27,7 @@ public final class MoggMob extends CardImpl {
// Sacrifice Mogg Mob: It deals 3 damage divided as you choose among one, two, or three targets.
Ability ability = new SimpleActivatedAbility(
new DamageMultiEffect(3, "it"), new SacrificeSourceCost()
new DamageMultiEffect("it"), new SacrificeSourceCost()
);
ability.addTarget(new TargetAnyTargetAmount(3));
this.addAbility(ability);

View file

@ -22,7 +22,7 @@ public final class MonstrousOnslaught extends CardImpl {
// Monstrous Onslaught deals X damage divided as you choose among any number of target creatures, where X is the greatest power among creatures you control as you cast Monstrous Onslaught.
DynamicValue xValue = GreatestPowerAmongControlledCreaturesValue.instance;
Effect effect = new DamageMultiEffect(xValue);
Effect effect = new DamageMultiEffect();
effect.setText("{this} deals X damage divided as you choose among any number of target creatures, where X is the greatest power among creatures you control as you cast this spell");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(xValue));

View file

@ -44,10 +44,8 @@ public final class MyojinOfToweringMight extends CardImpl {
), new CastFromHandWatcher());
// Remove an indestructible counter from Myojin of Towering Might: Distribute eight +1/+1 counters among any number of target creatures you control. They gain trample until end of turn.
Ability ability = new SimpleActivatedAbility(new DistributeCountersEffect(
8,
"any number of target creatures you control"
), new RemoveCountersSourceCost(CounterType.INDESTRUCTIBLE.createInstance()));
Ability ability = new SimpleActivatedAbility(new DistributeCountersEffect(),
new RemoveCountersSourceCost(CounterType.INDESTRUCTIBLE.createInstance()));
ability.addEffect(new GainAbilityTargetEffect(
TrampleAbility.getInstance(), Duration.EndOfTurn
).setText("They gain trample until end of turn"));

View file

@ -11,7 +11,6 @@ import mage.abilities.effects.common.DamageMultiEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ColoredManaSymbol;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
@ -34,7 +33,7 @@ public final class MythosOfVadrok extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}{R}");
// Mythos of Vadrok deals 5 damage divided as you choose among any number of target creatures and/or planeswalkers. If {W}{U} was spent to cast this spell, until your next turn, those permanents can't attack or block and their activated abilities can't be activated.
this.getSpellAbility().addEffect(new DamageMultiEffect(5));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetCreatureOrPlaneswalkerAmount(5));
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new MythosOfVadrokEffect(), condition, "If {W}{U} was spent to cast this spell, " +

View file

@ -41,7 +41,7 @@ public final class NahirisSacrifice extends CardImpl {
this.getSpellAbility().addCost(new SacrificeXManaValueCost(filter,true));
// Nahiris Sacrifice deals X damage divided as you choose among any number of target creatures.
Effect effect = new DamageMultiEffect(GetXValue.instance);
Effect effect = new DamageMultiEffect();
effect.setText("{this} deals X damage divided as you choose among any number of target creatures.");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(GetXValue.instance));

View file

@ -13,11 +13,10 @@ import mage.abilities.keyword.PartnerAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.counters.CounterType;
import mage.filter.FilterPermanent;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanentAmount;
import mage.target.common.TargetPermanentAmount;
import java.util.UUID;
@ -88,10 +87,10 @@ class NumaJoragaChieftainEffect extends OneShotEffect {
return false;
}
ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(
new DistributeCountersEffect(costX, ""),
new DistributeCountersEffect(),
false, "distribute " + costX + " +1/+1 counters among any number of target Elves"
);
ability.addTarget(new TargetCreaturePermanentAmount(costX, filter));
ability.addTarget(new TargetPermanentAmount(costX, 0, filter));
game.fireReflexiveTriggeredAbility(ability, source);
return true;
}

View file

@ -35,7 +35,7 @@ public final class OmnivorousFlytrap extends CardImpl {
// Delirium -- Whenever Omnivorous Flytrap enters or attacks, if there are four or more card types among cards in your graveyard, distribute two +1/+1 counters among one or two target creatures. Then if there are six or more card types among cards in your graveyard, double the number of +1/+1 counters on those creatures.
Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility(
new DistributeCountersEffect(CounterType.P1P1, 2, "one or two target creatures"))
new DistributeCountersEffect())
.withInterveningIf(DeliriumCondition.instance);
ability.addEffect(new ConditionalOneShotEffect(
new OmnivorousFlytrapEffect(),

View file

@ -50,12 +50,7 @@ public final class OnduKnotmaster extends AdventureCard {
// Throw a Line
// Distribute two +1/+1 counters among one or two target creatures.
this.getSpellCard().getSpellAbility().addEffect(
new DistributeCountersEffect(
2,
"one or two target creatures"
)
);
this.getSpellCard().getSpellAbility().addEffect(new DistributeCountersEffect());
this.getSpellCard().getSpellAbility().addTarget(new TargetCreaturePermanentAmount(2));
this.finalizeAdventure();

View file

@ -38,7 +38,7 @@ public final class OrcaSiegeDemon extends CardImpl {
this.addAbility(new DiesCreatureTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false, true));
// When Orca dies, it deals damage equal to its power divided as you choose among any number of targets.
Ability ability = new DiesSourceTriggeredAbility(new DamageMultiEffect(SourcePermanentPowerValue.NOT_NEGATIVE)
Ability ability = new DiesSourceTriggeredAbility(new DamageMultiEffect()
.setText("it deals damage equal to its power divided as you choose among any number of targets."));
ability.addTarget(new TargetAnyTargetAmount(SourcePermanentPowerValue.NOT_NEGATIVE));
this.addAbility(ability);

View file

@ -12,7 +12,6 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.target.common.TargetCreaturePermanentAmount;
@ -40,14 +39,9 @@ public final class PicnicRuiner extends AdventureCard {
// Stolen Goodies
// Distribute three +1/+1 counters among any number of target creatures you control.
this.getSpellCard().getSpellAbility().addEffect(
new DistributeCountersEffect(
3,
"any number of target creatures you control"
)
);
this.getSpellCard().getSpellAbility().addEffect(new DistributeCountersEffect());
this.getSpellCard().getSpellAbility().addTarget(
new TargetCreaturePermanentAmount(3, StaticFilters.FILTER_CONTROLLED_CREATURES)
new TargetCreaturePermanentAmount(3, 0, 3, StaticFilters.FILTER_CONTROLLED_CREATURES)
);
this.finalizeAdventure();

View file

@ -27,13 +27,13 @@ public final class PollenRemedy extends CardImpl {
// Kicker-Sacrifice a land.
this.addAbility(new KickerAbility(new SacrificeTargetCost(StaticFilters.FILTER_LAND)));
// Prevent the next 3 damage that would be dealt this turn to any number of target creatures and/or players, divided as you choose.
// Prevent the next 3 damage that would be dealt this turn to any number of targets, divided as you choose.
// If Pollen Remedy was kicked, prevent the next 6 damage this way instead.
Effect effect = new ConditionalReplacementEffect(new PreventDamageToTargetMultiAmountEffect(Duration.EndOfTurn, 6),
KickedCondition.ONCE, new PreventDamageToTargetMultiAmountEffect(Duration.EndOfTurn, 3));
effect.setText("Prevent the next 3 damage that would be dealt this turn to any number of targets, divided as you choose. If this spell was kicked, prevent the next 6 damage this way instead.");
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addTarget(new TargetAnyTargetAmount(3));
this.getSpellAbility().addTarget(new TargetAnyTargetAmount(3, 0, 3));
this.getSpellAbility().setTargetAdjuster(new ConditionalTargetAdjuster(KickedCondition.ONCE,
new TargetAnyTargetAmount(6)));
}

View file

@ -79,7 +79,7 @@ enum PolukranosWorldEaterAdjuster implements TargetAdjuster {
public void adjustTargets(Ability ability, Game game) {
int xValue = ((BecomesMonstrousSourceTriggeredAbility) ability).getMonstrosityValue();
ability.getTargets().clear();
ability.addTarget(new TargetCreaturePermanentAmount(xValue, StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE));
ability.addTarget(new TargetCreaturePermanentAmount(xValue, 0, xValue, StaticFilters.FILTER_OPPONENTS_PERMANENT_CREATURE));
}
}

View file

@ -33,8 +33,7 @@ public final class Portcullis extends CardImpl {
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.
// 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(),

View file

@ -33,7 +33,7 @@ public final class Pyrokinesis extends CardImpl {
this.addAbility(new AlternativeCostSourceAbility(new ExileFromHandCost(new TargetCardInHand(filter))));
// Pyrokinesis deals 4 damage divided as you choose among any number of target creatures.
this.getSpellAbility().addEffect(new DamageMultiEffect(4));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(4));
}

View file

@ -19,7 +19,7 @@ public final class Pyrotechnics extends CardImpl {
// Pyrotechnics deals 4 damage divided as you choose among any number of targets.
this.getSpellAbility().addEffect(new DamageMultiEffect(4));
this.getSpellAbility().addEffect(new DamageMultiEffect());
this.getSpellAbility().addTarget(new TargetAnyTargetAmount(4));
}

View file

@ -0,0 +1,114 @@
package mage.cards.q;
import mage.MageIdentifier;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.DealsDamageToAnyTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.MyTurnCondition;
import mage.abilities.costs.Cost;
import mage.abilities.costs.Costs;
import mage.abilities.costs.CostsImpl;
import mage.abilities.costs.common.RemoveCounterCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.dynamicvalue.common.SavedDamageValue;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
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 java.util.UUID;
/**
* @author PurpleCrowbar
*/
public final class QuilledGreatwurm extends CardImpl {
public QuilledGreatwurm(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}{G}");
this.subtype.add(SubType.WURM);
this.power = new MageInt(7);
this.toughness = new MageInt(7);
// Trample
this.addAbility(TrampleAbility.getInstance());
// Whenever a creature you control deals combat damage during your turn, put that many +1/+1 counters on it.
this.addAbility(new ConditionalTriggeredAbility(new DealsDamageToAnyTriggeredAbility(
Zone.BATTLEFIELD, new AddCountersTargetEffect(
CounterType.P1P1.createInstance(), SavedDamageValue.MANY
), StaticFilters.FILTER_CONTROLLED_A_CREATURE, SetTargetPointer.PERMANENT, true, false
), MyTurnCondition.instance, "Whenever a creature you control deals combat damage during your turn, put that many +1/+1 counters on it"));
// You may cast this card from your graveyard by removing six counters from among creatures you control in addition to paying its other costs.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new QuilledGreatwurmEffect()).setIdentifier(MageIdentifier.QuilledGreatwurmAlternateCast));
}
private QuilledGreatwurm(final QuilledGreatwurm card) {
super(card);
}
@Override
public QuilledGreatwurm copy() {
return new QuilledGreatwurm(this);
}
}
class QuilledGreatwurmEffect extends AsThoughEffectImpl {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent();
static {
filter.add(CounterAnyPredicate.instance);
}
QuilledGreatwurmEffect() {
super(AsThoughEffectType.CAST_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfGame, Outcome.Benefit);
this.staticText = "you may cast {this} from your graveyard by removing six counters " +
"from among creatures you control in addition to paying its other costs";
}
private QuilledGreatwurmEffect(final QuilledGreatwurmEffect effect) {
super(effect);
}
@Override
public QuilledGreatwurmEffect copy() {
return new QuilledGreatwurmEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public boolean applies(UUID objectId, Ability source, UUID affectControllerId, Game game) {
if (!source.getSourceId().equals(objectId)
|| !source.isControlledBy(affectControllerId)
|| game.getState().getZone(objectId) != Zone.GRAVEYARD) {
return false;
}
Player controller = game.getPlayer(affectControllerId);
if (controller == null) {
return false;
}
Costs<Cost> costs = new CostsImpl<>();
costs.add(new RemoveCounterCost(new TargetControlledCreaturePermanent(1, 6, filter, true), null, 6));
controller.setCastSourceIdWithAlternateMana(
objectId, new ManaCostsImpl<>("{4}{G}{G}"), costs,
MageIdentifier.QuilledGreatwurmAlternateCast
);
return true;
}
}

View file

@ -14,7 +14,7 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.counters.CounterType;
import mage.filter.StaticFilters;
import mage.target.common.TargetPermanentAmount;
import mage.target.common.TargetCreaturePermanentAmount;
/**
*
@ -39,10 +39,8 @@ public final class QuirionBeastcaller extends CardImpl {
// When Quirion Beastcaller dies, distribute X +1/+1 counters among any number of target creatures you control, where X is the number of +1/+1 counters on Quirion Beastcaller.
Ability ability = new DiesSourceTriggeredAbility(new DistributeCountersEffect(
// Amount here is only used for text generation. Real amount is set in target.
1, "any number of target creatures you control"
).setText("distribute X +1/+1 counters among any number of target creatures you control, where X is the number of +1/+1 counters on {this}"));
ability.addTarget(new TargetPermanentAmount(new CountersSourceCount(CounterType.P1P1), StaticFilters.FILTER_CONTROLLED_CREATURES));
ability.addTarget(new TargetCreaturePermanentAmount(new CountersSourceCount(CounterType.P1P1), StaticFilters.FILTER_CONTROLLED_CREATURES));
this.addAbility(ability);
}

View file

@ -40,7 +40,7 @@ public final class RalCallerOfStorms extends CardImpl {
));
// -2: Ral, Caller of Storms deals 3 damage divided as you choose among one, two, or three targets.
Ability ability = new LoyaltyAbility(new DamageMultiEffect(3), -2);
Ability ability = new LoyaltyAbility(new DamageMultiEffect(), -2);
ability.addTarget(new TargetAnyTargetAmount(3));
this.addAbility(ability);

View file

@ -75,7 +75,7 @@ public final class RalLeylineProdigy extends CardImpl {
this.addAbility(new LoyaltyAbility(new RalLeylineProdigyCostReductionEffect(), 1));
// -2: Ral deals 2 damage divided as you choose among one or two targets. Draw a card if you control a blue permanent other than Ral.
Ability ability = new LoyaltyAbility(new DamageMultiEffect(2), -2);
Ability ability = new LoyaltyAbility(new DamageMultiEffect(), -2);
ability.addTarget(new TargetAnyTargetAmount(2));
ability.addEffect(new ConditionalOneShotEffect(
new DrawCardSourceControllerEffect(1),

View file

@ -73,13 +73,13 @@ class RavenousGigantotheriumAbility extends EntersBattlefieldTriggeredAbility {
}
int power = Math.max(permanent.getPower().getValue(), 0);
this.getEffects().clear();
this.addEffect(new DamageMultiEffect(power));
this.addEffect(new DamageMultiEffect());
this.addEffect(new RavenousGigantotheriumEffect());
this.getTargets().clear();
if (power < 1) {
return true;
}
this.addTarget(new TargetCreaturePermanentAmount(power));
this.addTarget(new TargetCreaturePermanentAmount(power, 0, power));
return true;
}

Some files were not shown because too many files have changed in this diff Show more