diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/UI.java b/Mage.Client/src/main/java/org/mage/card/arcane/UI.java index e701cce8a0..0b2ed25f00 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/UI.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/UI.java @@ -148,7 +148,6 @@ public final class UI { } public static String getDisplayManaCost (String manaCost) { - manaCost = manaCost.replace("/", ""); // A pipe in the cost means "process left of the pipe as the card color, but display right of the pipe as the cost". int pipePosition = manaCost.indexOf("{|}"); if (pipePosition != -1) { 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 6e1974efe5..6fe57b2d0a 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 @@ -823,9 +823,6 @@ public class HumanPlayer extends PlayerImpl { protected boolean playManaHandling(Ability abilityToCast, ManaCost unpaid, String promptText, Game game) { updateGameStatePriority("playMana", game); Map options = new HashMap<>(); - if (unpaid.getText().contains("P}")) { - options.put(Constants.Option.SPECIAL_BUTTON, (Serializable) "Pay 2 life"); - } game.firePlayManaEvent(playerId, "Pay " + promptText, options); waitForResponse(game); if (!this.canRespond()) { @@ -838,18 +835,6 @@ public class HumanPlayer extends PlayerImpl { } else if (response.getString() != null && response.getString().equals("special")) { if (unpaid instanceof ManaCostsImpl) { specialManaAction(unpaid, game); - // TODO: delve or convoke cards with PhyrexianManaCost won't work together (this combinaton does not exist yet) - @SuppressWarnings("unchecked") - ManaCostsImpl costs = (ManaCostsImpl) unpaid; - for (ManaCost cost : costs.getUnpaid()) { - if (cost instanceof PhyrexianManaCost) { - PhyrexianManaCost ph = (PhyrexianManaCost) cost; - if (ph.canPay(null, null, playerId, game)) { - ((PhyrexianManaCost) cost).pay(null, game, null, playerId, false, null); - } - break; - } - } } } else if (response.getManaType() != null) { // this mana type can be paid once from pool @@ -907,7 +892,7 @@ public class HumanPlayer extends PlayerImpl { } Spell spell = game.getStack().getSpell(abilityToCast.getSourceId()); if (spell != null && spell.isDoneActivatingManaAbilities()) { - game.informPlayer(this, "You can't no longer use activated mana abilities to pay for the current spell. Cancel and recast the spell and activate mana abilities first."); + game.informPlayer(this, "You can no longer use activated mana abilities to pay for the current spell. Cancel and recast the spell and activate mana abilities first."); return; } Zone zone = game.getState().getZone(object.getId()); diff --git a/Mage.Sets/src/mage/cards/a/ActOfAggression.java b/Mage.Sets/src/mage/cards/a/ActOfAggression.java index dbfbafa4e1..f8e9df80ee 100644 --- a/Mage.Sets/src/mage/cards/a/ActOfAggression.java +++ b/Mage.Sets/src/mage/cards/a/ActOfAggression.java @@ -54,7 +54,7 @@ public class ActOfAggression extends CardImpl { } public ActOfAggression(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{RP}{RP}"); + super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{R/P}{R/P}"); this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.EndOfTurn)); diff --git a/Mage.Sets/src/mage/cards/a/ApostlesBlessing.java b/Mage.Sets/src/mage/cards/a/ApostlesBlessing.java index e6039af9c1..78d95a968c 100644 --- a/Mage.Sets/src/mage/cards/a/ApostlesBlessing.java +++ b/Mage.Sets/src/mage/cards/a/ApostlesBlessing.java @@ -63,9 +63,9 @@ public class ApostlesBlessing extends CardImpl { } public ApostlesBlessing(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{WP}"); + super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W/P}"); - // ({WP} can be paid with either {W} or 2 life.) + // ({W/P} can be paid with either {W} or 2 life.) // Target artifact or creature you control gains protection from artifacts or from the color of your choice until end of turn. this.getSpellAbility().addEffect(new ApostlesBlessingEffect()); this.getSpellAbility().addTarget(new TargetControlledPermanent(filter)); diff --git a/Mage.Sets/src/mage/cards/b/BirthingPod.java b/Mage.Sets/src/mage/cards/b/BirthingPod.java index 2ede7fdac7..79db650753 100644 --- a/Mage.Sets/src/mage/cards/b/BirthingPod.java +++ b/Mage.Sets/src/mage/cards/b/BirthingPod.java @@ -57,11 +57,11 @@ import mage.target.common.TargetControlledCreaturePermanent; public class BirthingPod extends CardImpl { public BirthingPod(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}{GP}"); + super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}{G/P}"); - // {1}{GP}, {tap}, Sacrifice a creature: Search your library for a creature card with converted mana cost equal to 1 plus the sacrificed creature's converted mana cost, + // {1}{G/P}, {tap}, Sacrifice a creature: Search your library for a creature card with converted mana cost equal to 1 plus the sacrificed creature's converted mana cost, // put that card onto the battlefield, then shuffle your library. Activate this ability only any time you could cast a sorcery. - Ability ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new BirthingPodEffect(), new ManaCostsImpl("{1}{GP}")); + Ability ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new BirthingPodEffect(), new ManaCostsImpl("{1}{G/P}")); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent())); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/b/BlindingSouleater.java b/Mage.Sets/src/mage/cards/b/BlindingSouleater.java index c77c476e5d..5cd65289f2 100644 --- a/Mage.Sets/src/mage/cards/b/BlindingSouleater.java +++ b/Mage.Sets/src/mage/cards/b/BlindingSouleater.java @@ -53,7 +53,7 @@ public class BlindingSouleater extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(3); - // {WP},{T}: Tap target creature. ( can be paid with either or 2 life.) + // {W/P},{T}: Tap target creature. ( can be paid with either or 2 life.) SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new TapTargetEffect(), new PhyrexianManaCost(ColoredManaSymbol.W)); diff --git a/Mage.Sets/src/mage/cards/c/CathedralMembrane.java b/Mage.Sets/src/mage/cards/c/CathedralMembrane.java index d464bd56e7..544b9137aa 100644 --- a/Mage.Sets/src/mage/cards/c/CathedralMembrane.java +++ b/Mage.Sets/src/mage/cards/c/CathedralMembrane.java @@ -51,13 +51,13 @@ import java.util.UUID; public class CathedralMembrane extends CardImpl { public CathedralMembrane(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{1}{WP}"); + super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{1}{W/P}"); this.subtype.add("Wall"); this.power = new MageInt(0); this.toughness = new MageInt(3); - // ({WP} can be paid with either {W} or 2 life.) + // ({W/P} can be paid with either {W} or 2 life.) this.addAbility(DefenderAbility.getInstance()); // When Cathedral Membrane dies during combat, it deals 6 damage to each creature it blocked this combat. diff --git a/Mage.Sets/src/mage/cards/c/CorrosiveGale.java b/Mage.Sets/src/mage/cards/c/CorrosiveGale.java index d833980c12..40ba94ad44 100644 --- a/Mage.Sets/src/mage/cards/c/CorrosiveGale.java +++ b/Mage.Sets/src/mage/cards/c/CorrosiveGale.java @@ -50,7 +50,7 @@ public class CorrosiveGale extends CardImpl { } public CorrosiveGale(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{GP}"); + super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{G/P}"); this.getSpellAbility().addEffect(new DamageAllEffect(new ManacostVariableValue(), filter)); diff --git a/Mage.Sets/src/mage/cards/d/Dismember.java b/Mage.Sets/src/mage/cards/d/Dismember.java index 3939c51769..72db3fa530 100644 --- a/Mage.Sets/src/mage/cards/d/Dismember.java +++ b/Mage.Sets/src/mage/cards/d/Dismember.java @@ -44,7 +44,7 @@ import mage.target.common.TargetCreaturePermanent; public class Dismember extends CardImpl { public Dismember (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{BP}{BP}"); + super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{B/P}{B/P}"); // Target creature gets -5/-5 until end of turn. diff --git a/Mage.Sets/src/mage/cards/g/GitaxianProbe.java b/Mage.Sets/src/mage/cards/g/GitaxianProbe.java index 4e2353124c..8bf19e2dc5 100644 --- a/Mage.Sets/src/mage/cards/g/GitaxianProbe.java +++ b/Mage.Sets/src/mage/cards/g/GitaxianProbe.java @@ -42,7 +42,7 @@ import mage.target.TargetPlayer; public class GitaxianProbe extends CardImpl { public GitaxianProbe(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{UP}"); + super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{U/P}"); // Look at target player's hand. this.getSpellAbility().addEffect(new LookAtTargetPlayerHandEffect()); diff --git a/Mage.Sets/src/mage/cards/g/GutShot.java b/Mage.Sets/src/mage/cards/g/GutShot.java index 5166e4ce7d..3fe09ad40e 100644 --- a/Mage.Sets/src/mage/cards/g/GutShot.java +++ b/Mage.Sets/src/mage/cards/g/GutShot.java @@ -41,7 +41,7 @@ import mage.target.common.TargetCreatureOrPlayer; public class GutShot extends CardImpl { public GutShot(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{RP}"); + super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{R/P}"); this.getSpellAbility().addEffect(new DamageTargetEffect(1)); this.getSpellAbility().addTarget(new TargetCreatureOrPlayer()); diff --git a/Mage.Sets/src/mage/cards/h/HexParasite.java b/Mage.Sets/src/mage/cards/h/HexParasite.java index 63bb4f7dc6..e57539bbf1 100644 --- a/Mage.Sets/src/mage/cards/h/HexParasite.java +++ b/Mage.Sets/src/mage/cards/h/HexParasite.java @@ -58,8 +58,8 @@ public class HexParasite extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(1); - // {X}{BP}: Remove up to X counters from target permanent. For each counter removed this way, Hex Parasite gets +1/+0 until end of turn. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new HexParasiteEffect(), new ManaCostsImpl("{X}{BP}")); + // {X}{B/P}: Remove up to X counters from target permanent. For each counter removed this way, Hex Parasite gets +1/+0 until end of turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new HexParasiteEffect(), new ManaCostsImpl("{X}{B/P}")); ability.addTarget(new TargetPermanent()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/l/Lashwrithe.java b/Mage.Sets/src/mage/cards/l/Lashwrithe.java index f1430f0a9d..ddc499ae16 100644 --- a/Mage.Sets/src/mage/cards/l/Lashwrithe.java +++ b/Mage.Sets/src/mage/cards/l/Lashwrithe.java @@ -64,7 +64,7 @@ public class Lashwrithe extends CardImpl { this.addAbility(new LivingWeaponAbility()); PermanentsOnBattlefieldCount value = new PermanentsOnBattlefieldCount(filter); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(value, value))); - this.addAbility(new EquipAbility(Outcome.BoostCreature, new ManaCostsImpl("{BP}{BP}"))); + this.addAbility(new EquipAbility(Outcome.BoostCreature, new ManaCostsImpl("{B/P}{B/P}"))); } public Lashwrithe(final Lashwrithe card) { diff --git a/Mage.Sets/src/mage/cards/m/MarrowShards.java b/Mage.Sets/src/mage/cards/m/MarrowShards.java index 80a5832bb5..00dd8f4615 100644 --- a/Mage.Sets/src/mage/cards/m/MarrowShards.java +++ b/Mage.Sets/src/mage/cards/m/MarrowShards.java @@ -41,7 +41,7 @@ import mage.filter.common.FilterAttackingCreature; public class MarrowShards extends CardImpl { public MarrowShards(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{WP}"); + super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{W/P}"); this.getSpellAbility().addEffect(new DamageAllEffect(1, new FilterAttackingCreature())); diff --git a/Mage.Sets/src/mage/cards/m/MentalMisstep.java b/Mage.Sets/src/mage/cards/m/MentalMisstep.java index 3c5a86e4e7..ef520c581d 100644 --- a/Mage.Sets/src/mage/cards/m/MentalMisstep.java +++ b/Mage.Sets/src/mage/cards/m/MentalMisstep.java @@ -50,7 +50,7 @@ public class MentalMisstep extends CardImpl { } public MentalMisstep(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{UP}"); + super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{U/P}"); // Counter target spell with converted mana cost 1. this.getSpellAbility().addEffect(new CounterTargetEffect()); diff --git a/Mage.Sets/src/mage/cards/m/MoltensteelDragon.java b/Mage.Sets/src/mage/cards/m/MoltensteelDragon.java index 2a5131a39e..613b525cd6 100644 --- a/Mage.Sets/src/mage/cards/m/MoltensteelDragon.java +++ b/Mage.Sets/src/mage/cards/m/MoltensteelDragon.java @@ -47,7 +47,7 @@ import mage.constants.Zone; public class MoltensteelDragon extends CardImpl { public MoltensteelDragon(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}{RP}{RP}"); + super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}{R/P}{R/P}"); this.subtype.add("Dragon"); this.power = new MageInt(4); diff --git a/Mage.Sets/src/mage/cards/m/MutagenicGrowth.java b/Mage.Sets/src/mage/cards/m/MutagenicGrowth.java index efa0cfea1d..dd82416c2f 100644 --- a/Mage.Sets/src/mage/cards/m/MutagenicGrowth.java +++ b/Mage.Sets/src/mage/cards/m/MutagenicGrowth.java @@ -43,7 +43,7 @@ import mage.target.common.TargetCreaturePermanent; public class MutagenicGrowth extends CardImpl { public MutagenicGrowth (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{GP}"); + super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{G/P}"); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2, Duration.EndOfTurn)); diff --git a/Mage.Sets/src/mage/cards/n/NornsAnnex.java b/Mage.Sets/src/mage/cards/n/NornsAnnex.java index 5ee1fed2c4..0a72b7b9f8 100644 --- a/Mage.Sets/src/mage/cards/n/NornsAnnex.java +++ b/Mage.Sets/src/mage/cards/n/NornsAnnex.java @@ -42,11 +42,11 @@ import mage.constants.Zone; public class NornsAnnex extends CardImpl { public NornsAnnex(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}{WP}{WP}"); + super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}{W/P}{W/P}"); - // {WP} ({WP} can be paid with either or 2 life.) - // Creatures can't attack you or a planeswalker you control unless their controller pays {WP} for each of those creatures. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackYouUnlessPayManaAllEffect(new ManaCostsImpl<>("{WP}"), true))); + // {W/P} ({W/P} can be paid with either or 2 life.) + // Creatures can't attack you or a planeswalker you control unless their controller pays {W/P} for each of those creatures. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackYouUnlessPayManaAllEffect(new ManaCostsImpl<>("{W/P}"), true))); } public NornsAnnex(final NornsAnnex card) { diff --git a/Mage.Sets/src/mage/cards/n/NoxiousRevival.java b/Mage.Sets/src/mage/cards/n/NoxiousRevival.java index 2692fc62de..d802a6565d 100644 --- a/Mage.Sets/src/mage/cards/n/NoxiousRevival.java +++ b/Mage.Sets/src/mage/cards/n/NoxiousRevival.java @@ -42,7 +42,7 @@ import mage.target.common.TargetCardInGraveyard; public class NoxiousRevival extends CardImpl { public NoxiousRevival (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{GP}"); + super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{G/P}"); this.getSpellAbility().addEffect(new PutOnLibraryTargetEffect(true)); this.getSpellAbility().addTarget(new TargetCardInGraveyard()); diff --git a/Mage.Sets/src/mage/cards/p/PhyrexianMetamorph.java b/Mage.Sets/src/mage/cards/p/PhyrexianMetamorph.java index 7fa187afc3..c56fd2e4c7 100644 --- a/Mage.Sets/src/mage/cards/p/PhyrexianMetamorph.java +++ b/Mage.Sets/src/mage/cards/p/PhyrexianMetamorph.java @@ -61,7 +61,7 @@ public class PhyrexianMetamorph extends CardImpl { } public PhyrexianMetamorph(UUID ownerId, CardSetInfo setInfo) { - super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}{UP}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}{U/P}"); this.subtype.add("Shapeshifter"); this.power = new MageInt(0); @@ -83,7 +83,7 @@ public class PhyrexianMetamorph extends CardImpl { }; - // {UP} ( can be paid with either {U} or 2 life.) + // {U/P} ( can be paid with either {U} or 2 life.) // You may have Phyrexian Metamorph enter the battlefield as a copy of any artifact or creature on the battlefield, except it's an artifact in addition to its other types. Effect effect = new CopyPermanentEffect(filter, phyrexianMetamorphApplier); effect.setText("You may have {this} enter the battlefield as a copy of any artifact or creature on the battlefield, except it's an artifact in addition to its other types"); diff --git a/Mage.Sets/src/mage/cards/p/PithDriller.java b/Mage.Sets/src/mage/cards/p/PithDriller.java index 2049cf2f10..6df97e0c21 100644 --- a/Mage.Sets/src/mage/cards/p/PithDriller.java +++ b/Mage.Sets/src/mage/cards/p/PithDriller.java @@ -44,7 +44,7 @@ import mage.target.common.TargetCreaturePermanent; public class PithDriller extends CardImpl { public PithDriller(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}{BP}"); + super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}{B/P}"); this.subtype.add("Horror"); this.power = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/p/PorcelainLegionnaire.java b/Mage.Sets/src/mage/cards/p/PorcelainLegionnaire.java index 67fd014fb1..2ec9cc2350 100644 --- a/Mage.Sets/src/mage/cards/p/PorcelainLegionnaire.java +++ b/Mage.Sets/src/mage/cards/p/PorcelainLegionnaire.java @@ -41,7 +41,7 @@ import mage.cards.CardSetInfo; public class PorcelainLegionnaire extends CardImpl { public PorcelainLegionnaire(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{2}{WP}"); + super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{2}{W/P}"); this.subtype.add("Soldier"); this.power = new MageInt(3); diff --git a/Mage.Sets/src/mage/cards/p/PostmortemLunge.java b/Mage.Sets/src/mage/cards/p/PostmortemLunge.java index fc10cd35b6..35f22cb092 100644 --- a/Mage.Sets/src/mage/cards/p/PostmortemLunge.java +++ b/Mage.Sets/src/mage/cards/p/PostmortemLunge.java @@ -60,7 +60,7 @@ import mage.target.targetpointer.FixedTarget; public class PostmortemLunge extends CardImpl { public PostmortemLunge(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{BP}"); + super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{B/P}"); // Return target creature card with converted mana cost X from your graveyard to the battlefield. It gains haste. Exile it at the beginning of the next end step. this.getSpellAbility().addEffect(new PostmortemLungeEffect()); diff --git a/Mage.Sets/src/mage/cards/r/RageExtractor.java b/Mage.Sets/src/mage/cards/r/RageExtractor.java index 866c1af851..6d3f98edd5 100644 --- a/Mage.Sets/src/mage/cards/r/RageExtractor.java +++ b/Mage.Sets/src/mage/cards/r/RageExtractor.java @@ -49,7 +49,7 @@ import mage.target.common.TargetCreatureOrPlayer; public class RageExtractor extends CardImpl { public RageExtractor(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}{RP}"); + super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}{R/P}"); this.addAbility(new RageExtractorTriggeredAbility()); diff --git a/Mage.Sets/src/mage/cards/r/RuthlessInvasion.java b/Mage.Sets/src/mage/cards/r/RuthlessInvasion.java index 56c7a95a20..d438d1d5f7 100644 --- a/Mage.Sets/src/mage/cards/r/RuthlessInvasion.java +++ b/Mage.Sets/src/mage/cards/r/RuthlessInvasion.java @@ -46,7 +46,7 @@ import mage.game.permanent.Permanent; public class RuthlessInvasion extends CardImpl { public RuthlessInvasion (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{RP}"); + super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{R/P}"); this.getSpellAbility().addEffect(new RuthlessInvasionEffect()); } diff --git a/Mage.Sets/src/mage/cards/s/SlashPanther.java b/Mage.Sets/src/mage/cards/s/SlashPanther.java index bbadca8d95..6ae2486151 100644 --- a/Mage.Sets/src/mage/cards/s/SlashPanther.java +++ b/Mage.Sets/src/mage/cards/s/SlashPanther.java @@ -41,7 +41,7 @@ import mage.cards.CardSetInfo; public class SlashPanther extends CardImpl { public SlashPanther(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}{RP}"); + super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}{R/P}"); this.subtype.add("Cat"); this.power = new MageInt(4); diff --git a/Mage.Sets/src/mage/cards/s/Spellskite.java b/Mage.Sets/src/mage/cards/s/Spellskite.java index d613df99c6..b0b3ee3e6a 100644 --- a/Mage.Sets/src/mage/cards/s/Spellskite.java +++ b/Mage.Sets/src/mage/cards/s/Spellskite.java @@ -61,8 +61,8 @@ public class Spellskite extends CardImpl { this.power = new MageInt(0); this.toughness = new MageInt(4); - // {UP}: Change a target of target spell or ability to Spellskite. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SpellskiteEffect(), new ManaCostsImpl("{UP}")); + // {U/P}: Change a target of target spell or ability to Spellskite. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SpellskiteEffect(), new ManaCostsImpl("{U/P}")); ability.addTarget(new TargetStackObject()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SpinedThopter.java b/Mage.Sets/src/mage/cards/s/SpinedThopter.java index c920b90049..31e4977f22 100644 --- a/Mage.Sets/src/mage/cards/s/SpinedThopter.java +++ b/Mage.Sets/src/mage/cards/s/SpinedThopter.java @@ -41,7 +41,7 @@ import mage.cards.CardSetInfo; public class SpinedThopter extends CardImpl { public SpinedThopter(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{2}{UP}"); + super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{2}{U/P}"); this.subtype.add("Thopter"); this.power = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/s/SurgicalExtraction.java b/Mage.Sets/src/mage/cards/s/SurgicalExtraction.java index 449c5aeb14..6da76539b6 100644 --- a/Mage.Sets/src/mage/cards/s/SurgicalExtraction.java +++ b/Mage.Sets/src/mage/cards/s/SurgicalExtraction.java @@ -63,7 +63,7 @@ public class SurgicalExtraction extends CardImpl { } public SurgicalExtraction(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{BP}"); + super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{B/P}"); // Choose target card in a graveyard other than a basic land card. Search its owner's graveyard, // hand, and library for any number of cards with the same name as that card and exile them. diff --git a/Mage.Sets/src/mage/cards/t/TezzeretsGambit.java b/Mage.Sets/src/mage/cards/t/TezzeretsGambit.java index f5a8033352..1f658f36a4 100644 --- a/Mage.Sets/src/mage/cards/t/TezzeretsGambit.java +++ b/Mage.Sets/src/mage/cards/t/TezzeretsGambit.java @@ -41,7 +41,7 @@ import mage.cards.CardSetInfo; public class TezzeretsGambit extends CardImpl { public TezzeretsGambit(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{UP}"); + super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{U/P}"); this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2)); this.getSpellAbility().addEffect(new ProliferateEffect()); diff --git a/Mage.Sets/src/mage/cards/t/ThunderingTanadon.java b/Mage.Sets/src/mage/cards/t/ThunderingTanadon.java index 40c6b566a9..91af7f20d5 100644 --- a/Mage.Sets/src/mage/cards/t/ThunderingTanadon.java +++ b/Mage.Sets/src/mage/cards/t/ThunderingTanadon.java @@ -41,7 +41,7 @@ import mage.cards.CardSetInfo; public class ThunderingTanadon extends CardImpl { public ThunderingTanadon(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}{GP}{GP}"); + super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}{G/P}{G/P}"); this.subtype.add("Beast"); this.power = new MageInt(5); diff --git a/Mage.Sets/src/mage/cards/t/TrespassingSouleater.java b/Mage.Sets/src/mage/cards/t/TrespassingSouleater.java index a6013178d5..62a1f0dd70 100644 --- a/Mage.Sets/src/mage/cards/t/TrespassingSouleater.java +++ b/Mage.Sets/src/mage/cards/t/TrespassingSouleater.java @@ -52,7 +52,7 @@ public class TrespassingSouleater extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); - // {UP}: Trespassing Souleater can't be blocked this turn. + // {U/P}: Trespassing Souleater can't be blocked this turn. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CantBeBlockedSourceEffect(Duration.EndOfTurn), new PhyrexianManaCost(ColoredManaSymbol.U))); diff --git a/Mage.Sets/src/mage/cards/v/VaultSkirge.java b/Mage.Sets/src/mage/cards/v/VaultSkirge.java index ec08b1d2ad..a8407d5a42 100644 --- a/Mage.Sets/src/mage/cards/v/VaultSkirge.java +++ b/Mage.Sets/src/mage/cards/v/VaultSkirge.java @@ -42,7 +42,7 @@ import mage.cards.CardSetInfo; public class VaultSkirge extends CardImpl { public VaultSkirge(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{1}{BP}"); + super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{1}{B/P}"); this.subtype.add("Imp"); this.power = new MageInt(1); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/destroy/HideousEndTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/destroy/HideousEndTest.java index 1972a6ebce..99c887f4e6 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/destroy/HideousEndTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/destroy/HideousEndTest.java @@ -51,10 +51,10 @@ public class HideousEndTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerB, "Plains"); addCard(Zone.BATTLEFIELD, playerB, "Copper Myr"); // Target artifact or creature you control gains protection from artifacts or from the color of your choice until end of turn. - addCard(Zone.HAND, playerB, "Apostle's Blessing"); + addCard(Zone.HAND, playerB, "Blessed Breath"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Hideous End", "Copper Myr"); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Apostle's Blessing", "Copper Myr"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Blessed Breath", "Copper Myr"); setChoice(playerB, "Black"); setStopAt(1, PhaseStep.BEGIN_COMBAT); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/MimicVatTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/MimicVatTest.java index 01aca00419..ca5ab2ebfd 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/MimicVatTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/MimicVatTest.java @@ -88,7 +88,7 @@ public class MimicVatTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerA, "Phyrexian Vault", 1); // You may have Phyrexian Metamorph enter the battlefield as a copy of any artifact or creature on the battlefield, except it's an artifact in addition to its other types. - addCard(Zone.HAND, playerA, "Phyrexian Metamorph", 1);// Creature {3}{UP} + addCard(Zone.HAND, playerA, "Phyrexian Metamorph", 1);// Creature {3}{U/P} addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/PhyrexianMetamorphTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/PhyrexianMetamorphTest.java index 3404c3f037..14e90953a8 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/PhyrexianMetamorphTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/PhyrexianMetamorphTest.java @@ -44,7 +44,7 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerA, "Plains", 5); // You may have Phyrexian Metamorph enter the battlefield as a copy of any artifact or creature on the battlefield, except it's an artifact in addition to its other types. - addCard(Zone.HAND, playerA, "Phyrexian Metamorph"); // {3}{UP} + addCard(Zone.HAND, playerA, "Phyrexian Metamorph"); // {3}{U/P} addCard(Zone.HAND, playerA, "Cloudshift"); //Flying @@ -64,7 +64,7 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase { setStopAt(1, PhaseStep.END_TURN); execute(); - assertLife(playerA, 24); + assertLife(playerA, 22); assertLife(playerB, 20); assertGraveyardCount(playerA, "Cloudshift", 1); @@ -87,7 +87,7 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerA, "Island", 4); // You may have Phyrexian Metamorph enter the battlefield as a copy of any artifact or creature on the battlefield, except it's an artifact in addition to its other types. - addCard(Zone.HAND, playerA, "Phyrexian Metamorph"); // {3}{UP} + addCard(Zone.HAND, playerA, "Phyrexian Metamorph"); // {3}{U/P} // Flying // When Brago, King Eternal deals combat damage to a player, exile any number of target nonland permanents you control, then return those cards to the battlefield under their owner's control. @@ -109,7 +109,7 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase { setStopAt(3, PhaseStep.END_COMBAT); execute(); - assertLife(playerA, 20); + assertLife(playerA, 18); assertLife(playerB, 18); assertPermanentCount(playerA, "Ponyback Brigade", 1); @@ -128,7 +128,7 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerA, "Island", 4); // You may have Phyrexian Metamorph enter the battlefield as a copy of any artifact or creature on the battlefield, except it's an artifact in addition to its other types. - addCard(Zone.HAND, playerA, "Phyrexian Metamorph"); // {3}{UP} + addCard(Zone.HAND, playerA, "Phyrexian Metamorph"); // {3}{U/P} addCard(Zone.BATTLEFIELD, playerB, "Alloy Myr", 1); addCard(Zone.BATTLEFIELD, playerB, "Kitesail", 1); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/CostModificationTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/CostModificationTest.java index 810812f9be..0cb57e8457 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/CostModificationTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/cost/modification/CostModificationTest.java @@ -57,7 +57,7 @@ public class CostModificationTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerB, "Plains", 2); // Look at target player's hand. // Draw a card. - addCard(Zone.HAND, playerB, "Gitaxian Probe"); // Sorcery {UP} + addCard(Zone.HAND, playerB, "Gitaxian Probe"); // Sorcery {U/P} castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Gitaxian Probe", playerA); setStopAt(2, PhaseStep.BEGIN_COMBAT); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/SpellskiteTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/SpellskiteTest.java deleted file mode 100644 index acab953a30..0000000000 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/SpellskiteTest.java +++ /dev/null @@ -1,111 +0,0 @@ -package org.mage.test.cards.single; - -import mage.constants.PhaseStep; -import mage.constants.Zone; -import org.junit.Test; -import org.mage.test.serverside.base.CardTestPlayerBase; - -/** - * Created by goesta on 12/02/2017. Modified by jeffwadsworth - */ -public class SpellskiteTest extends CardTestPlayerBase { - - @Test - public void testThatSpellSkiteCantBeTargetedTwiceOrMore() { - /* According to rules, the same object can be a legal target only - once for each instances of the word “target” in the text - of a spell or ability. In this case, the target can't be changed - due to Spellskite already being a target. - */ - addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); - addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); - addCard(Zone.BATTLEFIELD, playerA, "Forest", 1); - - addCard(Zone.BATTLEFIELD, playerB, "Spellskite"); - addCard(Zone.BATTLEFIELD, playerB, "Scute Mob"); - addCard(Zone.BATTLEFIELD, playerB, "Island"); - - addCard(Zone.HAND, playerA, "Fiery Justice"); - - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fiery Justice"); - addTarget(playerA, "Scute Mob"); - setChoice(playerA, "X=1"); - addTarget(playerA, "Spellskite"); - setChoice(playerA, "X=4"); - - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{UP}: Change a target of target spell or ability to {this}.", "Fiery Justice", "Fiery Justice"); - setChoice(playerA, "Yes"); - - setStopAt(1, PhaseStep.BEGIN_COMBAT); - execute(); - - assertGraveyardCount(playerB, 2); - } - - public void testThatSplitDamageCanGetRedirected() { - /* Standard redirect test - The Spellskite should die from the 5 damage that was redirected to it - */ - addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); - addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); - addCard(Zone.BATTLEFIELD, playerA, "Forest", 1); - - addCard(Zone.BATTLEFIELD, playerB, "Spellskite");// 0/4 creature - addCard(Zone.BATTLEFIELD, playerB, "Scute Mob"); // 1/1 creauture - addCard(Zone.BATTLEFIELD, playerB, "Island"); - - addCard(Zone.HAND, playerA, "Fiery Justice"); - - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fiery Justice"); // 5 damage distributed to any number of targets - addTarget(playerA, "Scute Mob"); - setChoice(playerA, "X=5"); - - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{UP}: Change a target of target spell or ability to {this}.", "Fiery Justice", "Fiery Justice"); - setChoice(playerA, "Yes"); - - setStopAt(1, PhaseStep.BEGIN_COMBAT); - execute(); - - assertGraveyardCount(playerB, 1); - assertPermanentCount(playerB, "Scute Mob", 1); - } - - public void testThatSplitDamageGetsRedirectedFromTheCorrectChoice() { - addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); - addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); - addCard(Zone.BATTLEFIELD, playerA, "Forest", 1); - - addCard(Zone.BATTLEFIELD, playerB, "Spellskite");// 0/4 creature - addCard(Zone.BATTLEFIELD, playerB, "Memnite"); // 1/1 creauture - addCard(Zone.BATTLEFIELD, playerB, "Royal Assassin"); - addCard(Zone.BATTLEFIELD, playerB, "Blinking Spirit"); - addCard(Zone.BATTLEFIELD, playerB, "Pearled Unicorn"); - addCard(Zone.BATTLEFIELD, playerB, "Island"); - - addCard(Zone.HAND, playerA, "Fiery Justice"); - - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fiery Justice"); // 5 damage distributed to any number of targets - addTarget(playerA, "Memnite"); - setChoice(playerA, "X=1"); - addTarget(playerA, "Royal Assassin"); - setChoice(playerA, "X=1"); - addTarget(playerA, "Blinking Spirit"); - setChoice(playerA, "X=1"); - addTarget(playerA, "Pearled Unicorn"); - setChoice(playerA, "X=2");//the unicorn deserves it - - - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{UP}: Change a target of target spell or ability to {this}.", "Fiery Justice", "Fiery Justice"); - setChoice(playerA, "No"); - setChoice(playerA, "No"); - setChoice(playerA, "No"); - setChoice(playerA, "Yes"); //of course - - setStopAt(1, PhaseStep.BEGIN_COMBAT); - execute(); - - assertGraveyardCount(playerB, 3); - assertPermanentCount(playerB, "Pearled Unicorn", 1);//it lives on - assertPowerToughness(playerB, "Spellskite", 0, 2); - } -} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/BecomesTheTargetTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/BecomesTheTargetTest.java index f94f7eb687..7f90d651e3 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/BecomesTheTargetTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/BecomesTheTargetTest.java @@ -52,13 +52,13 @@ public class BecomesTheTargetTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1); - activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{WP},{T}: Tap target creature", "Silvercoat Lion"); + activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{W/P},{T}: Tap target creature", "Silvercoat Lion"); setStopAt(2, PhaseStep.BEGIN_COMBAT); execute(); assertLife(playerA, 20); - assertLife(playerB, 20); + assertLife(playerB, 18); assertPermanentCount(playerA, "Silvercoat Lion", 0); assertTapped("Silvercoat Lion", true); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/SacredGroundTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/SacredGroundTest.java index 1fa82368c5..0ac639ffa4 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/SacredGroundTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/SacredGroundTest.java @@ -157,7 +157,7 @@ public class SacredGroundTest extends CardTestPlayerBase { // Choose target card in a graveyard other than a basic land card. Search its owner's graveyard, // hand, and library for any number of cards with the same name as that card and exile them. // Then that player shuffles his or her library. - addCard(Zone.HAND, playerA, "Surgical Extraction"); // Instant {BP} + addCard(Zone.HAND, playerA, "Surgical Extraction"); // Instant {B/P} addCard(Zone.BATTLEFIELD, playerB, "Caves of Koilos", 1); /** @@ -177,7 +177,7 @@ public class SacredGroundTest extends CardTestPlayerBase { assertGraveyardCount(playerA, "Surgical Extraction", 1); assertExileCount("Caves of Koilos", 1); - assertLife(playerA, 20); + assertLife(playerA, 18); assertLife(playerB, 18); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/SpellskiteTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/SpellskiteTest.java index a2ecfa35d3..d342098352 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/SpellskiteTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/SpellskiteTest.java @@ -52,7 +52,7 @@ public class SpellskiteTest extends CardTestPlayerBase { addCard(Zone.HAND, playerA, "Lightning Bolt"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{UP}: Change a target of target spell or ability to {this}.", "Lightning Bolt"); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{U/P}: Change a target of target spell or ability to {this}.", "Lightning Bolt"); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); @@ -60,7 +60,7 @@ public class SpellskiteTest extends CardTestPlayerBase { assertGraveyardCount(playerA, "Lightning Bolt", 1); assertPermanentCount(playerA, "Spellskite", 1); - assertLife(playerA, 20); + assertLife(playerA, 18); assertLife(playerB, 20); assertPowerToughness(playerA, "Spellskite", 3, 7); @@ -90,7 +90,7 @@ public class SpellskiteTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerA, "Vedalken Shackles", 1); addCard(Zone.BATTLEFIELD, playerB, "Island", 6); - // {UP}: Change a target of target spell or ability to Spellskite. + // {U/P}: Change a target of target spell or ability to Spellskite. addCard(Zone.BATTLEFIELD, playerB, "Spellskite", 1); // {4}{U}{U} // Whenever Frost Titan becomes the target of a spell or ability an opponent controls, counter that spell or ability unless its controller pays 2. @@ -102,7 +102,7 @@ public class SpellskiteTest extends CardTestPlayerBase { castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Frost Titan"); addTarget(playerB, "Silvercoat Lion"); - activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{UP}: Change a target", "stack ability (Whenever {this} enters "); + activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{U/P}: Change a target", "stack ability (Whenever {this} enters "); setStopAt(2, PhaseStep.BEGIN_COMBAT); execute(); @@ -141,7 +141,7 @@ public class SpellskiteTest extends CardTestPlayerBase { setModeChoice(playerA, "1"); // Counter target spell setModeChoice(playerA, "2"); // return target permanent to its owner's hand - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{UP}: Change a target of target spell or ability to {this}.", "Cryptic Command", "Cryptic Command"); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{U/P}: Change a target of target spell or ability to {this}.", "Cryptic Command", "Cryptic Command"); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); @@ -154,7 +154,7 @@ public class SpellskiteTest extends CardTestPlayerBase { assertPermanentCount(playerB, "Silvercoat Lion", 1); assertLife(playerA, 20); - assertLife(playerB, 20); + assertLife(playerB, 18); } @@ -182,7 +182,7 @@ public class SpellskiteTest extends CardTestPlayerBase { setModeChoice(playerA, "2"); // return target permanent to its owner's hand setModeChoice(playerA, "3"); // tap all creatures your opponents control - activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{UP}: Change a target of target spell or ability to {this}.", "Cryptic Command"); + activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{U/P}: Change a target of target spell or ability to {this}.", "Cryptic Command"); setStopAt(2, PhaseStep.BEGIN_COMBAT); execute(); @@ -194,7 +194,7 @@ public class SpellskiteTest extends CardTestPlayerBase { assertTapped("Silvercoat Lion", true); assertLife(playerA, 20); - assertLife(playerB, 20); + assertLife(playerB, 18); } @@ -214,7 +214,7 @@ public class SpellskiteTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{UP}: Change a target of target spell or ability to {this}.", "Lightning Bolt"); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{U/P}: Change a target of target spell or ability to {this}.", "Lightning Bolt"); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); @@ -222,7 +222,7 @@ public class SpellskiteTest extends CardTestPlayerBase { assertGraveyardCount(playerA, "Lightning Bolt", 1); assertLife(playerA, 20); - assertLife(playerB, 20); + assertLife(playerB, 18); } @@ -250,4 +250,102 @@ public class SpellskiteTest extends CardTestPlayerBase { assertPowerToughness(playerB, "Spellskite", 3, 7); } + @Test + public void testThatSpellSkiteCantBeTargetedTwiceOrMore() { + /* According to rules, the same object can be a legal target only + once for each instances of the word “target” in the text + of a spell or ability. In this case, the target can't be changed + due to Spellskite already being a target. + */ + addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 1); + + addCard(Zone.BATTLEFIELD, playerB, "Spellskite"); + addCard(Zone.BATTLEFIELD, playerB, "Scute Mob"); + addCard(Zone.BATTLEFIELD, playerB, "Island"); + + addCard(Zone.HAND, playerA, "Fiery Justice"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fiery Justice"); + addTarget(playerA, "Scute Mob"); + setChoice(playerA, "X=1"); + addTarget(playerA, "Spellskite"); + setChoice(playerA, "X=4"); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{UP}: Change a target of target spell or ability to {this}.", "Fiery Justice", "Fiery Justice"); + setChoice(playerA, "Yes"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerB, 2); + } + + public void testThatSplitDamageCanGetRedirected() { + /* Standard redirect test + The Spellskite should die from the 5 damage that was redirected to it + */ + addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 1); + + addCard(Zone.BATTLEFIELD, playerB, "Spellskite");// 0/4 creature + addCard(Zone.BATTLEFIELD, playerB, "Scute Mob"); // 1/1 creauture + addCard(Zone.BATTLEFIELD, playerB, "Island"); + + addCard(Zone.HAND, playerA, "Fiery Justice"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fiery Justice"); // 5 damage distributed to any number of targets + addTarget(playerA, "Scute Mob"); + setChoice(playerA, "X=5"); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{UP}: Change a target of target spell or ability to {this}.", "Fiery Justice", "Fiery Justice"); + setChoice(playerA, "Yes"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerB, 1); + assertPermanentCount(playerB, "Scute Mob", 1); + } + + public void testThatSplitDamageGetsRedirectedFromTheCorrectChoice() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 1); + + addCard(Zone.BATTLEFIELD, playerB, "Spellskite");// 0/4 creature + addCard(Zone.BATTLEFIELD, playerB, "Memnite"); // 1/1 creauture + addCard(Zone.BATTLEFIELD, playerB, "Royal Assassin"); + addCard(Zone.BATTLEFIELD, playerB, "Blinking Spirit"); + addCard(Zone.BATTLEFIELD, playerB, "Pearled Unicorn"); + addCard(Zone.BATTLEFIELD, playerB, "Island"); + + addCard(Zone.HAND, playerA, "Fiery Justice"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fiery Justice"); // 5 damage distributed to any number of targets + addTarget(playerA, "Memnite"); + setChoice(playerA, "X=1"); + addTarget(playerA, "Royal Assassin"); + setChoice(playerA, "X=1"); + addTarget(playerA, "Blinking Spirit"); + setChoice(playerA, "X=1"); + addTarget(playerA, "Pearled Unicorn"); + setChoice(playerA, "X=2");//the unicorn deserves it + + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{UP}: Change a target of target spell or ability to {this}.", "Fiery Justice", "Fiery Justice"); + setChoice(playerA, "No"); + setChoice(playerA, "No"); + setChoice(playerA, "No"); + setChoice(playerA, "Yes"); //of course + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerB, 3); + assertPermanentCount(playerB, "Pearled Unicorn", 1);//it lives on + assertPowerToughness(playerB, "Spellskite", 0, 2); + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/delayed/PostMortemLungeTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/delayed/PostMortemLungeTest.java index d468370699..bb9dbe6143 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/delayed/PostMortemLungeTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/delayed/PostMortemLungeTest.java @@ -18,7 +18,7 @@ public class PostMortemLungeTest extends CardTestPlayerBase { public void testExilesCreatureAtEndStep() { /* - {P}{X} - Sorcery + {X}{B/P} - Sorcery Return target creature card with converted mana cost X from your graveyard to the battlefield. It gains haste. Exile it at the beginning of the next end step. */ diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/ThragtuskTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/ThragtuskTest.java index f74cdd5f74..467db2066a 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/ThragtuskTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/ThragtuskTest.java @@ -43,7 +43,7 @@ public class ThragtuskTest extends CardTestPlayerBase { /** * Test if a Thragtusk is copied by a PhyrexianMetamorph that both triggers - * cotrrect work + * correct work */ @Test public void testPhyrexianMetamorph() { @@ -69,7 +69,7 @@ public class ThragtuskTest extends CardTestPlayerBase { assertGraveyardCount(playerA, "Phyrexian Metamorph", 1); assertGraveyardCount(playerB, "Public Execution", 1); - assertLife(playerA, 25); + assertLife(playerA, 23); assertLife(playerB, 20); // Thragtusk ETB ability does not trigger if set to battlefield on test game start assertPermanentCount(playerA, "Beast", 1); @@ -116,7 +116,7 @@ public class ThragtuskTest extends CardTestPlayerBase { assertGraveyardCount(playerA, "Phyrexian Metamorph", 1); assertGraveyardCount(playerB, "Public Execution", 1); - assertLife(playerA, 25); + assertLife(playerA, 23); assertLife(playerB, 20); // Thragtusk ETB ability does not trigger if set to battlefield on test game start assertPermanentCount(playerA, "Beast", 0); diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java index 32626f779c..7cbce9ac75 100644 --- a/Mage/src/main/java/mage/abilities/AbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java @@ -31,11 +31,9 @@ import mage.MageObject; import mage.MageObjectReference; import mage.Mana; import mage.abilities.costs.*; +import mage.abilities.costs.common.PayLifeCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.costs.mana.ManaCost; -import mage.abilities.costs.mana.ManaCosts; -import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.costs.mana.VariableManaCost; +import mage.abilities.costs.mana.*; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.Effect; import mage.abilities.effects.Effects; @@ -62,6 +60,7 @@ import mage.watchers.Watcher; import org.apache.log4j.Logger; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.UUID; @@ -298,6 +297,9 @@ public abstract class AbilityImpl implements Ability { && game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.CAST_SPELL_LATE, getId(), getSourceId(), getControllerId()), this)) { return false; } + + handlePhyrexianManaCosts(game, sourceId, controller); + for (UUID modeId : this.getModes().getSelectedModes()) { this.getModes().setActiveMode(modeId); //20121001 - 601.2c @@ -503,6 +505,27 @@ public abstract class AbilityImpl implements Ability { return announceString.toString(); } + /** + * 601.2b + * If a cost that will be paid as the spell is being cast includes Phyrexian mana symbols, + * the player announces whether he or she intends to pay 2 life or the corresponding colored mana cost for each of those symbols. + */ + private void handlePhyrexianManaCosts(Game game, UUID sourceId, Player controller) { + Iterator costIterator = manaCostsToPay.iterator(); + while(costIterator.hasNext()) { + ManaCost cost = costIterator.next(); + if(cost instanceof PhyrexianManaCost) { + PhyrexianManaCost phyrexianManaCost = (PhyrexianManaCost)cost; + PayLifeCost payLifeCost = new PayLifeCost(2); + if(payLifeCost.canPay(this, sourceId, controller.getId(), game) && + controller.chooseUse(Outcome.LoseLife, "Pay 2 life instead of " + phyrexianManaCost.getBaseText() + "?", this, game)) { + costIterator.remove(); + costs.add(payLifeCost); + } + } + } + } + /** * Handles X mana costs and sets manaCostsToPay. * diff --git a/Mage/src/main/java/mage/abilities/costs/mana/PhyrexianManaCost.java b/Mage/src/main/java/mage/abilities/costs/mana/PhyrexianManaCost.java index 703f61ddff..3dfad98d51 100644 --- a/Mage/src/main/java/mage/abilities/costs/mana/PhyrexianManaCost.java +++ b/Mage/src/main/java/mage/abilities/costs/mana/PhyrexianManaCost.java @@ -50,34 +50,20 @@ public class PhyrexianManaCost extends ColoredManaCost { super(manaCost); } - @Override - public void assignPayment(Game game, Ability ability, ManaPool pool, Cost costToPay) { - assignColored(ability, game, pool, this.mana, costToPay); - } - @Override public String getText() { - return '{' + mana.toString() + "P}"; + return '{' + mana.toString() + "/P}"; + } + + public String getBaseText() { + return super.getText(); } @Override - public PhyrexianManaCost getUnpaid() { - return this; + public ColoredManaCost getUnpaid() { + return new ColoredManaCost(this); } - @Override - public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { - if (!game.getPlayer(controllerId).isLifeTotalCanChange()) { - return false; - } - return game.getPlayer(controllerId).getLife() >= 2; - } - - @Override - public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { - this.paid = game.getPlayer(controllerId).loseLife(2, game, false) == 2; - return paid; - } @Override public PhyrexianManaCost copy() { diff --git a/Mage/src/main/java/mage/abilities/effects/PayCostToAttackBlockEffectImpl.java b/Mage/src/main/java/mage/abilities/effects/PayCostToAttackBlockEffectImpl.java index 6b3c56b6fe..9eb3e16e82 100644 --- a/Mage/src/main/java/mage/abilities/effects/PayCostToAttackBlockEffectImpl.java +++ b/Mage/src/main/java/mage/abilities/effects/PayCostToAttackBlockEffectImpl.java @@ -29,8 +29,13 @@ package mage.abilities.effects; import mage.abilities.Ability; import mage.abilities.costs.Cost; +import mage.abilities.costs.Costs; +import mage.abilities.costs.CostsImpl; +import mage.abilities.costs.common.PayLifeCost; +import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCosts; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.costs.mana.PhyrexianManaCost; import mage.constants.Duration; import mage.constants.Outcome; import mage.game.Game; @@ -38,6 +43,9 @@ import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.players.Player; +import java.util.Iterator; +import java.util.List; + /** * * @author LevelX2 @@ -141,6 +149,7 @@ public abstract class PayCostToAttackBlockEffectImpl extends ReplacementEffectIm attackBlockManaTax.clearPaid(); if (attackBlockManaTax.canPay(source, source.getSourceId(), player.getId(), game) && player.chooseUse(Outcome.Neutral, chooseText, source, game)) { + handlePhyrexianManaCosts(manaCosts, player, source, game); if (attackBlockManaTax instanceof ManaCostsImpl) { if (attackBlockManaTax.payOrRollback(source, game, source.getSourceId(), event.getPlayerId())) { return false; @@ -152,6 +161,27 @@ public abstract class PayCostToAttackBlockEffectImpl extends ReplacementEffectIm return false; } + private void handlePhyrexianManaCosts(ManaCosts manaCosts, Player player, Ability source, Game game) { + Iterator manaCostIterator = manaCosts.iterator(); + Costs costs = new CostsImpl<>(); + + while(manaCostIterator.hasNext()) { + ManaCost manaCost = manaCostIterator.next(); + if(manaCost instanceof PhyrexianManaCost) { + PhyrexianManaCost phyrexianManaCost = (PhyrexianManaCost)manaCost; + PayLifeCost payLifeCost = new PayLifeCost(2); + if(payLifeCost.canPay(source, source.getSourceId(), player.getId(), game) && + player.chooseUse(Outcome.LoseLife, "Pay 2 life instead of " + phyrexianManaCost.getBaseText() + "?", source, game)) { + manaCostIterator.remove(); + costs.add(payLifeCost); + } + } + } + + costs.pay(source, game, source.getSourceId(), player.getId(), false, null); + } + + private boolean handleOtherCosts(Cost attackBlockOtherTax, GameEvent event, Ability source, Game game) { Player player = game.getPlayer(event.getPlayerId()); if (player != null) { diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index 03b5ab4d5a..e22021f729 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -2438,7 +2438,9 @@ public abstract class PlayerImpl implements Player, Serializable { if (!copy.canActivate(playerId, game)) { return false; } - game.getContinuousEffects().costModification(copy, game); + if(available != null) { + game.getContinuousEffects().costModification(copy, game); + } Card card = game.getCard(ability.getSourceId()); if (card != null) {