Merge pull request #2948 from ImperatorPrime/phyrexian-mana-fix

Phyrexian mana now correctly a payment choice.
This commit is contained in:
Nathaniel Brandes 2017-03-08 20:03:01 -08:00 committed by GitHub
commit ef29fab8ea
47 changed files with 234 additions and 222 deletions

View file

@ -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) {

View file

@ -823,9 +823,6 @@ public class HumanPlayer extends PlayerImpl {
protected boolean playManaHandling(Ability abilityToCast, ManaCost unpaid, String promptText, Game game) {
updateGameStatePriority("playMana", game);
Map<String, Serializable> 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<ManaCost> costs = (ManaCostsImpl<ManaCost>) 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());

View file

@ -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));

View file

@ -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));

View file

@ -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);

View file

@ -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));

View file

@ -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);
// <i>({WP} can be paid with either {W} or 2 life.)</i>
// <i>({W/P} can be paid with either {W} or 2 life.)</i>
this.addAbility(DefenderAbility.getInstance());
// When Cathedral Membrane dies during combat, it deals 6 damage to each creature it blocked this combat.

View file

@ -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));

View file

@ -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.

View file

@ -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());

View file

@ -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());

View file

@ -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);
}

View file

@ -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) {

View file

@ -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()));

View file

@ -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());

View file

@ -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);

View file

@ -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));

View file

@ -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) {

View file

@ -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());

View file

@ -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");

View file

@ -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);

View file

@ -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);

View file

@ -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());

View file

@ -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());

View file

@ -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());
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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);

View file

@ -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.

View file

@ -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());

View file

@ -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);

View file

@ -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)));

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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);
}
}

View file

@ -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.
*/

View file

@ -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);

View file

@ -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<ManaCost> 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.
*

View file

@ -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() {

View file

@ -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<ManaCost> manaCosts, Player player, Ability source, Game game) {
Iterator<ManaCost> manaCostIterator = manaCosts.iterator();
Costs<PayLifeCost> 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) {

View file

@ -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) {