mirror of
https://github.com/correl/mage.git
synced 2024-12-25 03:00:15 +00:00
* Fixed a problem with flashback ability and variable non mana costs (related to #2436).
This commit is contained in:
parent
a49f79cfc3
commit
15c1c7f8c0
4 changed files with 31 additions and 32 deletions
|
@ -40,17 +40,18 @@ public class ChaliceOfTheVoidTest extends CardTestPlayerBase {
|
|||
|
||||
/**
|
||||
* Theres a Chalice of the Void with 1 counter in play under my control.
|
||||
* Then I cast second chalice with x=1. For spells on the stack the cmc is the base CMC + X value * {X} in casting costs on top right of card.
|
||||
* So cmc should be 2 in this case, it shouldnt be countered.
|
||||
* Then I cast second chalice with x=1. For spells on the stack the cmc is
|
||||
* the base CMC + X value * {X} in casting costs on top right of card. So
|
||||
* cmc should be 2 in this case, it shouldnt be countered.
|
||||
* http://boardgames.stackexchange.com/questions/7327/what-is-the-converted-mana-cost-of-a-spell-with-x-when-cast-with-the-miracle-m
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testX1CountsFor2CMC() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4);
|
||||
// Chalice of the Void enters the battlefield with X charge counters on it.
|
||||
// Whenever a player casts a spell with converted mana cost equal to the number of charge counters on Chalice of the Void, counter that spell.
|
||||
addCard(Zone.HAND, playerA, "Chalice of the Void", 2);
|
||||
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Chalice of the Void");
|
||||
setChoice(playerA, "X=1");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Chalice of the Void");
|
||||
|
@ -62,10 +63,10 @@ public class ChaliceOfTheVoidTest extends CardTestPlayerBase {
|
|||
assertPermanentCount(playerA, "Chalice of the Void", 2);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
If X=1 the cmc of Chalice on the stack is 2. So it can't be countered by Mental Misstep
|
||||
*/
|
||||
*/
|
||||
@Test
|
||||
public void testCantBeCounteredByMentalMisstep() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||
|
@ -94,6 +95,8 @@ public class ChaliceOfTheVoidTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||
addCard(Zone.HAND, playerA, "Chalice of the Void", 1);
|
||||
|
||||
// Conflagrate deals X damage divided as you choose among any number of target creatures and/or players.
|
||||
// Flashback-{R}{R}, Discard X cards.
|
||||
addCard(Zone.GRAVEYARD, playerB, "Conflagrate", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 2);
|
||||
addCard(Zone.HAND, playerB, "Mountain", 1);
|
||||
|
@ -101,7 +104,6 @@ public class ChaliceOfTheVoidTest extends CardTestPlayerBase {
|
|||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Chalice of the Void");
|
||||
setChoice(playerA, "X=1");
|
||||
|
||||
|
||||
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Flashback {R}{R}");
|
||||
setChoice(playerB, "X=1");
|
||||
addTarget(playerB, playerA);
|
||||
|
@ -109,13 +111,12 @@ public class ChaliceOfTheVoidTest extends CardTestPlayerBase {
|
|||
setStopAt(2, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertLife(playerA, 19);
|
||||
assertLife(playerB, 20);
|
||||
|
||||
assertExileCount(playerB, "Conflagrate", 1);
|
||||
//TODO: Apparently there are two mountains in the graveyard at the end of the test now.
|
||||
//assertGraveyardCount(playerB, "Mountain", 1);
|
||||
assertGraveyardCount(playerB, "Mountain", 1);
|
||||
|
||||
assertLife(playerA, 19);
|
||||
assertLife(playerB, 20);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
*/
|
||||
package mage.abilities;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectReference;
|
||||
import mage.Mana;
|
||||
|
@ -59,11 +63,6 @@ import mage.util.ThreadLocalStringBuilder;
|
|||
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;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
|
@ -489,7 +488,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
protected String handleOtherXCosts(Game game, Player controller) {
|
||||
StringBuilder announceString = new StringBuilder();
|
||||
for (VariableCost variableCost : this.costs.getVariableCosts()) {
|
||||
if (!(variableCost instanceof VariableManaCost)) {
|
||||
if (!(variableCost instanceof VariableManaCost) && !((Cost) variableCost).isPaid()) {
|
||||
int xValue = variableCost.announceXValue(this, game);
|
||||
Cost fixedCost = variableCost.getFixedCostsFromAnnouncedValue(xValue);
|
||||
if (fixedCost != null) {
|
||||
|
@ -506,19 +505,20 @@ 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 he or she intends to pay 2 life or the corresponding colored mana cost for each of those symbols.
|
||||
* 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()) {
|
||||
while (costIterator.hasNext()) {
|
||||
ManaCost cost = costIterator.next();
|
||||
if(cost instanceof PhyrexianManaCost) {
|
||||
PhyrexianManaCost phyrexianManaCost = (PhyrexianManaCost)cost;
|
||||
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)) {
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ package mage.abilities.costs;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.keyword.FlashbackAbility;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
|
@ -170,7 +171,7 @@ public abstract class VariableCostImpl implements Cost, VariableCost {
|
|||
Player controller = game.getPlayer(source.getControllerId());
|
||||
StackObject stackObject = game.getStack().getStackObject(source.getId());
|
||||
if (controller != null
|
||||
&& stackObject != null) {
|
||||
&& (source instanceof FlashbackAbility || stackObject != null)) {
|
||||
xValue = controller.announceXCost(getMinValue(source, game), getMaxValue(source, game),
|
||||
"Announce the number of " + actionText, game, source, this);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.abilities.costs.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
|
@ -40,7 +39,6 @@ import mage.target.common.TargetCardInHand;
|
|||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
public class DiscardXTargetCost extends VariableCostImpl {
|
||||
|
||||
protected FilterCard filter;
|
||||
|
@ -50,9 +48,8 @@ public class DiscardXTargetCost extends VariableCostImpl {
|
|||
}
|
||||
|
||||
public DiscardXTargetCost(FilterCard filter, boolean additionalCostText) {
|
||||
super(new StringBuilder(filter.getMessage()).append(" to discard").toString());
|
||||
this.text = new StringBuilder(additionalCostText ? "As an additional cost to cast {source}, discard ":"Discard ")
|
||||
.append(xText).append(' ').append(filter.getMessage()).toString();
|
||||
super(filter.getMessage() + " to discard");
|
||||
this.text = (additionalCostText ? "As an additional cost to cast {source}, discard " : "Discard ") + xText + ' ' + filter.getMessage();
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue