diff --git a/Mage.Sets/src/mage/cards/p/PestilentSouleater.java b/Mage.Sets/src/mage/cards/p/PestilentSouleater.java index 7f631d8a1a4..760f8eec877 100644 --- a/Mage.Sets/src/mage/cards/p/PestilentSouleater.java +++ b/Mage.Sets/src/mage/cards/p/PestilentSouleater.java @@ -26,6 +26,7 @@ public final class PestilentSouleater extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(3); + // {B/P}: Pestilent Souleater gains infect until end of turn. ({B/P} can be paid with either {B} or 2 life. A creature with infect deals damage to creatures in the form of -1/-1 counters and to players in the form of poison counters.) this.addAbility(new SimpleActivatedAbility(new GainAbilitySourceEffect( InfectAbility.getInstance(), Duration.EndOfTurn ), new ManaCostsImpl<>("{B/P}"))); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/mana/phyrexian/PhyrexianManaTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/mana/phyrexian/PhyrexianManaTest.java index a26183aeb6c..3ae7b1e65ea 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/mana/phyrexian/PhyrexianManaTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/mana/phyrexian/PhyrexianManaTest.java @@ -28,27 +28,27 @@ public class PhyrexianManaTest extends CardTestPlayerBase { // can be played only through life pay Assert.assertTrue(life == 20 && hand == 1 || life == 18 && hand == 0); } - + @Test public void testKrrikOnlyUsableByController() { setStrictChooseMode(true); - + // ({B/P} can be paid with either {B} or 2 life.) // Lifelink // For each {B} in a cost, you may pay 2 life rather than pay that mana. // Whenever you cast a black spell, put a +1/+1 counter on K'rrik, Son of Yawgmoth. addCard(Zone.BATTLEFIELD, playerA, "K'rrik, Son of Yawgmoth"); addCard(Zone.HAND, playerA, "Banehound"); - + // Lifelink, haste addCard(Zone.HAND, playerB, "Banehound"); // Creature {B} 1/1 - checkPlayableAbility("pay 2 life for Banehound", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Banehound", true); - + checkPlayableAbility("pay 2 life for Banehound", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Banehound", true); + setChoice(playerA, true); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Banehound"); - checkPlayableAbility("no Mana for Banehound", 2, PhaseStep.PRECOMBAT_MAIN, playerB, "Cast Banehound", false); + checkPlayableAbility("no Mana for Banehound", 2, PhaseStep.PRECOMBAT_MAIN, playerB, "Cast Banehound", false); setStopAt(2, PhaseStep.END_TURN); execute(); @@ -66,7 +66,7 @@ public class PhyrexianManaTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerA, "K'rrik, Son of Yawgmoth"); addCard(Zone.HAND, playerA, "Banehound"); addCard(Zone.HAND, playerA, "Crypt Ghast"); - + addCard(Zone.BATTLEFIELD, playerB, "Swamp", 1); setChoice(playerA, true); //yes to pay 2 life to cast Crypt Ghast @@ -83,13 +83,13 @@ public class PhyrexianManaTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Banehound", 1); assertPermanentCount(playerA, "Crypt Ghast", 1); } - + @Test public void testKrrikActivatedAbility() { addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); addCard(Zone.BATTLEFIELD, playerA, "K'rrik, Son of Yawgmoth"); addCard(Zone.BATTLEFIELD, playerA, "Frozen Shade"); - + addCard(Zone.BATTLEFIELD, playerB, "Swamp", 1); setChoice(playerA, true); //yes to pay 2 life to activate Frozen Shade's +1/+1 ability @@ -104,22 +104,36 @@ public class PhyrexianManaTest extends CardTestPlayerBase { @Test public void testKrrikTrinispherePostPay() { + // Source: https://www.mtgsalvation.com/forums/magic-fundamentals/magic-rulings/812965-krrik-and-extort#c17 + // Summary rules: + // - announce Phyrexian cost from Dismember + // - apply cost modification from Trinisphere + // - apply payment method from K'rrik + // Detailed rules: + // K'rrik's ability applies at the time you attempt to pay the cost after Trinisphere cares about it; + // Phyrexian mana applies much earlier to the point where Trinisphere *does* care what the cost actually is. + // 118.13a only applies at the time the choice is made on how to pay for that symbol. You choose to pay for + // it with black mana thus getting around Trinisphere. Then, in step 601.2h is where K'rrik applies because he + // changes how you pay for those 2 black mana symbols you chose to pay mana for. It is similar to Delve and + // Convoke getting around Trinisphere for the same reason; you choose to pay mana up front but later in the + // process, when you actually pay for the symbols, you choose a different method of payment. + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); addCard(Zone.BATTLEFIELD, playerA, "K'rrik, Son of Yawgmoth"); addCard(Zone.BATTLEFIELD, playerA, "Trinisphere"); addCard(Zone.HAND, playerA, "Dismember"); - + addCard(Zone.BATTLEFIELD, playerB, "Swamp", 1); addCard(Zone.BATTLEFIELD, playerB, "Banehound"); - - setChoice(playerA, false); //don't pay 2 life for Dismember's Phyrexian cost - setChoice(playerA, false); //don't pay 2 life for Dismember's Phyrexian cost - setChoice(playerA, true); //yes to pay 2 life for Dismember's {B} cost via K'rrik - setChoice(playerA, true); //yes to pay 2 life for Dismember's {B} cost via K'rrik - + //Dismember costs {1} now + life paid. Normally this would be {3} + life paid with true Phyrexian mana and Trinisphere active. castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dismember", "Banehound"); - + setChoice(playerA, false); //don't pay 2 life for Dismember's Phyrexian cost + setChoice(playerA, false); //don't pay 2 life for Dismember's Phyrexian cost + setChoice(playerA, true); //yes to pay 2 life for Dismember's {B} cost via K'rrik + setChoice(playerA, true); //yes to pay 2 life for Dismember's {B} cost via K'rrik + + setStrictChooseMode(true); setStopAt(1, PhaseStep.END_TURN); execute(); @@ -130,35 +144,35 @@ public class PhyrexianManaTest extends CardTestPlayerBase { assertGraveyardCount(playerB, "Banehound", 1); } - @Test + @Test public void testPlayerCanCastBanehoundWithoutAvailableBlackMana() { setStrictChooseMode(true); - + // ({B/P} can be paid with either {B} or 2 life.) // Lifelink // For each {B} in a cost, you may pay 2 life rather than pay that mana. // Whenever you cast a black spell, put a +1/+1 counter on K'rrik, Son of Yawgmoth. addCard(Zone.BATTLEFIELD, playerA, "K'rrik, Son of Yawgmoth"); // Creature {4}{B/P}{B/P}{B/P} 2/2 addCard(Zone.HAND, playerA, "Banehound"); - + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Banehound"); setChoice(playerA, true); // Pay 2 life for {B} setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); - //PlayerA pays life + //PlayerA pays life assertLife(playerA, 18); assertLife(playerB, 20); - - + + assertPermanentCount(playerA, "Banehound", 1); - } - - @Test + } + + @Test public void testPlayerEffectNotUsableIfKrrikNotOnBattlefield() { setStrictChooseMode(true); - + // addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); // ({B/P} can be paid with either {B} or 2 life.) // Lifelink @@ -166,24 +180,24 @@ public class PhyrexianManaTest extends CardTestPlayerBase { // Whenever you cast a black spell, put a +1/+1 counter on K'rrik, Son of Yawgmoth. addCard(Zone.BATTLEFIELD, playerA, "K'rrik, Son of Yawgmoth"); // Creature {4}{B/P}{B/P}{B/P} 2/2 addCard(Zone.HAND, playerA, "Banehound"); - + addCard(Zone.HAND, playerB, "Lightning Bolt", 1); addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1); - + castSpell(1, PhaseStep.UPKEEP, playerB, "Lightning Bolt", "K'rrik, Son of Yawgmoth"); - - checkPlayableAbility("no Mana for Banehound", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Banehound", false); + + checkPlayableAbility("no Mana for Banehound", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Banehound", false); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); - assertGraveyardCount(playerB, "Lightning Bolt", 1); + assertGraveyardCount(playerB, "Lightning Bolt", 1); assertGraveyardCount(playerA, "K'rrik, Son of Yawgmoth", 1); - + assertHandCount(playerA, "Banehound", 1); //PlayerA pays life assertLife(playerA, 20); assertLife(playerB, 20); - - } + + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/rules/AlternativeCostRuleTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/rules/AlternativeCostRuleTest.java index de236dbb887..e5c7dd6a3de 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/rules/AlternativeCostRuleTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/rules/AlternativeCostRuleTest.java @@ -19,7 +19,7 @@ public class AlternativeCostRuleTest extends CardTestPlayerBase { setStrictChooseMode(true); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); - + Card firewildBorderpost = playerA.getGraveyard().getCards(currentGame).iterator().next(); boolean found = false; for (String rule : firewildBorderpost.getRules(currentGame)) { @@ -31,6 +31,28 @@ public class AlternativeCostRuleTest extends CardTestPlayerBase { Assert.assertTrue("Couldn't find rule text for alternative cost on a card: " + firewildBorderpost.getName(), found); } + @Test + public void test_PayLife() { + // You may pay 1 life and exile a black card from your hand rather than pay this spell’s mana cost. + // Distribute two -2/-1 counters among one or two target creatures. + addCard(Zone.HAND, playerA, "Contagion"); // {3}{B}{B} + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5); + addCard(Zone.HAND, playerA, "Arrogant Vampire", 1); + addCard(Zone.BATTLEFIELD, playerA, "Ancient Bronze Dragon"); // 7/7 + + // cast alternative + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Contagion"); + setChoice(playerA, "Cast with alternative cost: Pay 1 life"); + addTargetAmount(playerA, "Ancient Bronze Dragon", 2); + setChoice(playerA, "Arrogant Vampire"); // to pay discard cost + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + setStrictChooseMode(true); + execute(); + + assertPowerToughness(playerA, "Ancient Bronze Dragon", 7 - 2 * 2, 7 - 1 * 2); // from x1 boost + } + @Test public void test_AlternativeCostSourceAbility_OneCardMustNotAffectAnother() { // You may pay {W}{U}{B}{R}{G} rather than pay Bringer of the Black Dawn's mana cost. diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/dmc/VerrakWarpedSengirTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/dmc/VerrakWarpedSengirTest.java new file mode 100644 index 00000000000..1df34463bf4 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/dmc/VerrakWarpedSengirTest.java @@ -0,0 +1,119 @@ +package org.mage.test.cards.single.dmc; + +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.PayVariableLifeCost; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.keyword.InfectAbility; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author JayDi85 + */ +public class VerrakWarpedSengirTest extends CardTestPlayerBase { + + @Test + public void test_CopyOnPayLife_DirectCost() { + // Whenever you activate an ability that isn’t a mana ability, if life was paid to activate it, + // you may pay that much life again. If you do, copy that ability. You may choose new targets for the copy. + addCard(Zone.BATTLEFIELD, playerA, "Verrak, Warped Sengir"); + // + // {1}{B}, Pay 2 life: Draw a card. + addCard(Zone.BATTLEFIELD, playerA, "Arguel's Blood Fast"); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); + + checkHandCount("before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, 0); + + // activate and copy it + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}{B}, Pay 2 life"); + setChoice(playerA, true); // pay for copy + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + setStrictChooseMode(true); + execute(); + + assertHandCount(playerA, 1 + 1); // from x2 draws + assertLife(playerA, 20 - 2 - 2); // from x2 life pays + } + + @Test + public void test_CopyOnPayLife_VariableCost() { + // there are no real cards with X life in activated ability, so generate it here + addCustomCardWithAbility("test", playerA, new SimpleActivatedAbility( + new GainLifeEffect(10), new PayVariableLifeCost() + )); + + // Whenever you activate an ability that isn’t a mana ability, if life was paid to activate it, + // you may pay that much life again. If you do, copy that ability. You may choose new targets for the copy. + addCard(Zone.BATTLEFIELD, playerA, "Verrak, Warped Sengir"); + + // activate and copy it + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pay X life: You gain 10 life"); + setChoice(playerA, "X=3"); + setChoice(playerA, true); // pay for copy + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + setStrictChooseMode(true); + execute(); + + assertLife(playerA, 20 - 2 * 3 + 2 * 10); // x2: -3 for cost, +10 for resolve + } + + @Test + public void test_CopyOnPayLife_PhyrexianCost() { + // Whenever you activate an ability that isn’t a mana ability, if life was paid to activate it, + // you may pay that much life again. If you do, copy that ability. You may choose new targets for the copy. + addCard(Zone.BATTLEFIELD, playerA, "Verrak, Warped Sengir"); + // + // {B/P}: Pestilent Souleater gains infect until end of turn. + // ({B/P} can be paid with either {B} or 2 life. A creature with infect deals damage to creatures in the + // form of -1/-1 counters and to players in the form of poison counters.) + addCard(Zone.BATTLEFIELD, playerA, "Pestilent Souleater"); + + checkAbility("before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pestilent Souleater", InfectAbility.class, false); + + // activate and copy it + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{B/P}:"); + setChoice(playerA, true); // pay 2 life instead B + setChoice(playerA, true); // pay for copy + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + checkAbility("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pestilent Souleater", InfectAbility.class, true); + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + setStrictChooseMode(true); + execute(); + + assertLife(playerA, 20 - 2 * 2); // x2 pays + } + + @Test + public void test_CopyOnPayLife_PaymentModification() { + // bug: https://github.com/magefree/mage/issues/10119 + + // Whenever you activate an ability that isn’t a mana ability, if life was paid to activate it, + // you may pay that much life again. If you do, copy that ability. You may choose new targets for the copy. + addCard(Zone.BATTLEFIELD, playerA, "Verrak, Warped Sengir"); + // + // For each {B} in a cost, you may pay 2 life rather than pay that mana. + addCard(Zone.BATTLEFIELD, playerA, "K'rrik, Son of Yawgmoth"); + // + // {4}{B}: Each opponent loses 2 life and you gain 2 life. xxx + addCard(Zone.BATTLEFIELD, playerA, "Kami of Jealous Thirst"); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + + // activate and copy it + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{4}{B}: Each opponent"); + setChoice(playerA, true); // pay 2 life instead B + setChoice(playerA, true); // pay for copy + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + setStrictChooseMode(true); + execute(); + + assertLife(playerA, 20 - 2 * 2 + 2 * 2); // x2 pays, x2 gains + assertLife(playerB, 20 - 2 * 2); // x2 lose + } +} diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java index 3acf3dcff25..0830467cbdb 100644 --- a/Mage/src/main/java/mage/abilities/AbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java @@ -2,11 +2,11 @@ package mage.abilities; import mage.MageIdentifier; import mage.MageObject; +import mage.Mana; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.condition.Condition; import mage.abilities.costs.*; import mage.abilities.costs.common.PayLifeCost; -import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCosts; import mage.abilities.costs.mana.ManaCostsImpl; @@ -24,6 +24,7 @@ import mage.choices.Choice; import mage.choices.ChoiceHintType; import mage.choices.ChoiceImpl; import mage.constants.*; +import mage.filter.FilterMana; import mage.game.Game; import mage.game.command.Dungeon; import mage.game.command.Emblem; @@ -329,7 +330,10 @@ public abstract class AbilityImpl implements Ability { VariableManaCost variableManaCost = handleManaXCosts(game, noMana, controller); String announceString = handleOtherXCosts(game, controller); - handlePhyrexianManaCosts(game, controller); + // 601.2b If a cost that will be paid as the spell is being cast includes + // Phyrexian mana symbols, the player announces whether they intend to pay 2 + // life or the corresponding colored mana cost for each of those symbols. + AbilityImpl.handlePhyrexianCosts(game, this, this, this.getManaCostsToPay()); // 20241022 - 601.2b // Not yet included in 601.2b but this is where it will be @@ -632,24 +636,75 @@ public abstract class AbilityImpl implements Ability { } /** - * 601.2b If a cost that will be paid as the spell is being cast includes - * Phyrexian mana symbols, the player announces whether they intend to pay 2 - * life or the corresponding colored mana cost for each of those symbols. + * Prepare Phyrexian costs (choose life to pay instead mana) + * Must be called on cast announce before any cost modifications + * + * @param abilityToPay paying ability (will receive life cost) + * @param manaCostsToPay paying cost (will remove P and replace it by mana or nothing) */ - private void handlePhyrexianManaCosts(Game game, Player controller) { - Iterator costIterator = getManaCostsToPay().iterator(); + public static void handlePhyrexianCosts(Game game, Ability source, Ability abilityToPay, ManaCosts manaCostsToPay) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return; + } + + Iterator costIterator = manaCostsToPay.iterator(); while (costIterator.hasNext()) { ManaCost cost = costIterator.next(); - if (!cost.isPhyrexian()) { continue; } PayLifeCost payLifeCost = new PayLifeCost(2); - if (payLifeCost.canPay(this, this, controller.getId(), game) - && controller.chooseUse(Outcome.LoseLife, "Pay 2 life instead of " + cost.getText().replace("/P", "") + '?', this, game)) { + if (payLifeCost.canPay(abilityToPay, source, controller.getId(), game) + && controller.chooseUse(Outcome.LoseLife, "Pay 2 life instead of " + cost.getText().replace("/P", "") + + " (phyrexian cost)?", source, game)) { costIterator.remove(); - addCost(payLifeCost); - getManaCostsToPay().incrPhyrexianPaid(); + abilityToPay.addCost(payLifeCost); + manaCostsToPay.incrPhyrexianPaid(); // mark it as real phyrexian pay, e.g. for planeswalkers with Compleated ability + } + } + } + + /** + * Prepare and pay Phyrexian style effects like replace mana by life + * Must be called after original Phyrexian mana processing and after cost modifications, e.g. on payment + * + * @param abilityToPay paying ability (will receive life cost) + * @param manaCostsToPay paying cost (will replace mana by nothing) + */ + public static void handlePhyrexianLikeEffects(Game game, Ability source, Ability abilityToPay, ManaCosts manaCostsToPay) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return; + } + + // If a cost contains a mana symbol that may be paid in multiple ways, such as {B/R}, {B/P}, or {2/B}, + // you choose how you'll pay it before you do so. If you choose to pay {B} this way, K'rrik's ability allows + // you to pay life rather than pay that mana. + // (2019-08-23) + FilterMana phyrexianColors = controller.getPhyrexianColors(); + if (controller.getPhyrexianColors() == null) { + return; + } + Iterator costIterator = manaCostsToPay.iterator(); + while (costIterator.hasNext()) { + ManaCost cost = costIterator.next(); + Mana mana = cost.getMana(); + if ((!phyrexianColors.isWhite() || mana.getWhite() <= 0) + && (!phyrexianColors.isBlue() || mana.getBlue() <= 0) + && (!phyrexianColors.isBlack() || mana.getBlack() <= 0) + && (!phyrexianColors.isRed() || mana.getRed() <= 0) + && (!phyrexianColors.isGreen() || mana.getGreen() <= 0)) { + continue; + } + PayLifeCost payLifeCost = new PayLifeCost(2); + if (payLifeCost.canPay(abilityToPay, source, controller.getId(), game) + && controller.chooseUse(Outcome.LoseLife, "Pay 2 life instead of " + cost.getText().replace("/P", "") + + " (pay life cost)?", source, game)) { + if (payLifeCost.pay(abilityToPay, game, source, controller.getId(), false, null)) { + costIterator.remove(); + abilityToPay.addCost(payLifeCost); + } } } } diff --git a/Mage/src/main/java/mage/abilities/costs/mana/ManaCostImpl.java b/Mage/src/main/java/mage/abilities/costs/mana/ManaCostImpl.java index 3b2d1aa87b1..2244f6f8123 100644 --- a/Mage/src/main/java/mage/abilities/costs/mana/ManaCostImpl.java +++ b/Mage/src/main/java/mage/abilities/costs/mana/ManaCostImpl.java @@ -2,6 +2,7 @@ package mage.abilities.costs.mana; import mage.Mana; import mage.abilities.Ability; +import mage.abilities.AbilityImpl; import mage.abilities.costs.Cost; import mage.abilities.costs.CostImpl; import mage.abilities.mana.ManaOptions; @@ -254,6 +255,13 @@ public abstract class ManaCostImpl extends CostImpl implements ManaCost { return true; } Player player = game.getPlayer(controllerId); + if (player == null) { + return false; + } + + // TODO: is it require Phyrexian stile effects here for single payment? + //AbilityImpl.preparePhyrexianCost(game, source, player, ability, this); + if (!player.getManaPool().isForcedToPay()) { assignPayment(game, ability, player.getManaPool(), costToPay != null ? costToPay : this); } diff --git a/Mage/src/main/java/mage/abilities/costs/mana/ManaCostsImpl.java b/Mage/src/main/java/mage/abilities/costs/mana/ManaCostsImpl.java index f3c33c02a60..118379ccef8 100644 --- a/Mage/src/main/java/mage/abilities/costs/mana/ManaCostsImpl.java +++ b/Mage/src/main/java/mage/abilities/costs/mana/ManaCostsImpl.java @@ -2,6 +2,7 @@ package mage.abilities.costs.mana; import mage.Mana; import mage.abilities.Ability; +import mage.abilities.AbilityImpl; import mage.abilities.costs.*; import mage.abilities.costs.common.PayLifeCost; import mage.abilities.mana.ManaOptions; @@ -127,17 +128,17 @@ public class ManaCostsImpl extends ArrayList implements M return false; } - handleLikePhyrexianManaCosts(player, ability, game); // e.g. K'rrik, Son of Yawgmoth + AbilityImpl.handlePhyrexianLikeEffects(game, source, ability, this); if (!player.getManaPool().isForcedToPay()) { - assignPayment(game, ability, player.getManaPool(), this); + assignPayment(game, ability, player.getManaPool(), costToPay != null ? costToPay : this); } game.getState().getSpecialActions().removeManaActions(); while (player.canRespond() && !isPaid()) { ManaCost unpaid = this.getUnpaid(); String promptText = ManaUtil.addSpecialManaPayAbilities(ability, game, unpaid); if (player.playMana(ability, unpaid, promptText, game)) { - assignPayment(game, ability, player.getManaPool(), this); + assignPayment(game, ability, player.getManaPool(), costToPay != null ? costToPay : this); } else { return false; } @@ -195,40 +196,6 @@ public class ManaCostsImpl extends ArrayList implements M tempCosts.pay(source, game, source, payingPlayer.getId(), false, null); } - - private void handleLikePhyrexianManaCosts(Player player, Ability source, Game game) { - if (this.isEmpty()) { - return; // nothing to be done without any mana costs. prevents NRE from occurring here - } - FilterMana phyrexianColors = player.getPhyrexianColors(); - if (player.getPhyrexianColors() == null) { - return; - } - Costs tempCosts = new CostsImpl<>(); - - Iterator manaCostIterator = this.iterator(); - while (manaCostIterator.hasNext()) { - ManaCost manaCost = manaCostIterator.next(); - Mana mana = manaCost.getMana(); - - /* find which color mana is in the cost and set it in the temp Phyrexian cost */ - if ((!phyrexianColors.isWhite() || mana.getWhite() <= 0) - && (!phyrexianColors.isBlue() || mana.getBlue() <= 0) - && (!phyrexianColors.isBlack() || mana.getBlack() <= 0) - && (!phyrexianColors.isRed() || mana.getRed() <= 0) - && (!phyrexianColors.isGreen() || mana.getGreen() <= 0)) { - continue; - } - PayLifeCost payLifeCost = new PayLifeCost(2); - if (payLifeCost.canPay(source, source, player.getId(), game) - && player.chooseUse(Outcome.LoseLife, "Pay 2 life (using an active ability) instead of " + manaCost.getMana() + '?', source, game)) { - manaCostIterator.remove(); - tempCosts.add(payLifeCost); - } - } - tempCosts.pay(source, game, source, player.getId(), false, null); - } - @Override public ManaCosts getUnpaid() { ManaCosts unpaid = new ManaCostsImpl<>(); diff --git a/Mage/src/main/java/mage/players/Player.java b/Mage/src/main/java/mage/players/Player.java index 97ca015e5c1..257f6443dc7 100644 --- a/Mage/src/main/java/mage/players/Player.java +++ b/Mage/src/main/java/mage/players/Player.java @@ -1229,8 +1229,6 @@ public interface Player extends MageItem, Copyable { /** * Mana colors the player can pay instead with 2 life - * - * @return */ FilterMana getPhyrexianColors();