mirror of
https://github.com/correl/mage.git
synced 2025-03-07 20:53:18 -10:00
Fixed that the information what mana was payed to pay the mana cost of a spell or ability were not correct if "spend mana as though" abilities were involved in the payment (fixes #3604).
This commit is contained in:
parent
dc5007003b
commit
5a3243890d
8 changed files with 109 additions and 23 deletions
|
@ -25,7 +25,6 @@
|
|||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package org.mage.test.cards.abilities.enters;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
|
@ -90,9 +89,14 @@ public class GreenbeltRampagerTest extends CardTestPlayerBase {
|
|||
@Test
|
||||
public void testCastNotOwned() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 10);
|
||||
addCard(Zone.HAND, playerA, "Gonti, Lord of Luxury");
|
||||
// Deathtouch
|
||||
// When Gonti, Lord of Luxury enters the battlefield, look at the top four cards of target opponent's library, exile one of them face down,
|
||||
// then put the rest on the bottom of that library in a random order. For as long as that card remains exiled,
|
||||
// you may look at it, you may cast it, and you may spend mana as though it were mana of any type to cast it.
|
||||
addCard(Zone.HAND, playerA, "Gonti, Lord of Luxury"); // Creature {2}{B}{B}
|
||||
|
||||
addCard(Zone.LIBRARY, playerB, "Greenbelt Rampager");
|
||||
// When Greenbelt Rampager enters the battlefield, pay {E}{E}. If you can't, return Greenbelt Rampager to its owner's hand and you get {E}.
|
||||
addCard(Zone.LIBRARY, playerB, "Greenbelt Rampager"); // Creature {G} 3/4
|
||||
|
||||
skipInitShuffling();
|
||||
|
||||
|
|
|
@ -8,10 +8,38 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
|
|||
|
||||
public class MycosynthLatticeTest extends CardTestPlayerBase {
|
||||
|
||||
@Test
|
||||
public void testMycoSynthLatticeNormal() {
|
||||
// Converge - Crystalline Crawler enters the battlefield with a +1/+1 counter on it for each color of mana spent to cast it.
|
||||
// Remove a +1/+1 counter from Crystalline Crawler: Add one mana of any color to your mana pool.
|
||||
// {T}: Put a +1/+1 counter on Crystalline Crawler.
|
||||
String crawler = "Crystalline Crawler";
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
|
||||
addCard(Zone.HAND, playerA, crawler);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, crawler);
|
||||
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
|
||||
execute();
|
||||
|
||||
assertCounterCount(playerA, crawler, CounterType.P1P1, 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMycoSynthLatticeWithCrystallineCrawler(){
|
||||
public void testMycoSynthLatticeWithCrystallineCrawler() {
|
||||
// Converge - Crystalline Crawler enters the battlefield with a +1/+1 counter on it for each color of mana spent to cast it.
|
||||
// Remove a +1/+1 counter from Crystalline Crawler: Add one mana of any color to your mana pool.
|
||||
// {T}: Put a +1/+1 counter on Crystalline Crawler.
|
||||
String crawler = "Crystalline Crawler";
|
||||
|
||||
// All permanents are artifacts in addition to their other types.
|
||||
// All cards that aren't on the battlefield, spells, and permanents are colorless.
|
||||
// Players may spend mana as though it were mana of any color.
|
||||
String lattice = "Mycosynth Lattice";
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, lattice);
|
||||
|
|
|
@ -237,6 +237,38 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
|
|||
any += mana.getAny();
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases the given mana by one.
|
||||
*
|
||||
* @param manaType
|
||||
*/
|
||||
public void increase(ManaType manaType) {
|
||||
switch (manaType) {
|
||||
case BLACK:
|
||||
black++;
|
||||
break;
|
||||
case BLUE:
|
||||
blue++;
|
||||
break;
|
||||
case COLORLESS:
|
||||
colorless++;
|
||||
break;
|
||||
case GENERIC:
|
||||
generic++;
|
||||
break;
|
||||
case GREEN:
|
||||
green++;
|
||||
break;
|
||||
case RED:
|
||||
red++;
|
||||
break;
|
||||
case WHITE:
|
||||
white++;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases the Red mana by one.
|
||||
*/
|
||||
|
@ -815,11 +847,12 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns if this objects mana contains any coloured mana the same as the passed in
|
||||
* {@link Mana}'s mana.
|
||||
* Returns if this objects mana contains any coloured mana the same as the
|
||||
* passed in {@link Mana}'s mana.
|
||||
*
|
||||
* @param mana the mana to check for
|
||||
* @return true if this contains any of the same type of coloured mana that this has
|
||||
* @return true if this contains any of the same type of coloured mana that
|
||||
* this has
|
||||
*/
|
||||
public boolean containsAny(final Mana mana) {
|
||||
if (mana.black > 0 && this.black > 0) {
|
||||
|
@ -832,7 +865,7 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
|
|||
return true;
|
||||
} else if (mana.green > 0 && this.green > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,8 @@ public interface ManaCost extends Cost {
|
|||
|
||||
Mana getPayment();
|
||||
|
||||
Mana getUsedManaToPay();
|
||||
|
||||
void assignPayment(Game game, Ability ability, ManaPool pool, Cost costsToPay);
|
||||
|
||||
void setPayment(Mana mana);
|
||||
|
|
|
@ -46,18 +46,21 @@ import mage.util.ManaUtil;
|
|||
public abstract class ManaCostImpl extends CostImpl implements ManaCost {
|
||||
|
||||
protected Mana payment;
|
||||
protected Mana usedManaToPay;
|
||||
protected Mana cost;
|
||||
protected ManaOptions options;
|
||||
protected Filter sourceFilter;
|
||||
|
||||
public ManaCostImpl() {
|
||||
payment = new Mana();
|
||||
usedManaToPay = new Mana();
|
||||
options = new ManaOptions();
|
||||
}
|
||||
|
||||
public ManaCostImpl(final ManaCostImpl manaCost) {
|
||||
super(manaCost);
|
||||
this.payment = manaCost.payment.copy();
|
||||
this.usedManaToPay = manaCost.usedManaToPay.copy();
|
||||
this.cost = manaCost.cost.copy();
|
||||
this.options = manaCost.options.copy();
|
||||
if (manaCost.sourceFilter != null) {
|
||||
|
@ -70,6 +73,11 @@ public abstract class ManaCostImpl extends CostImpl implements ManaCost {
|
|||
return payment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mana getUsedManaToPay() {
|
||||
return usedManaToPay;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mana getMana() {
|
||||
return cost;
|
||||
|
@ -118,31 +126,31 @@ public abstract class ManaCostImpl extends CostImpl implements ManaCost {
|
|||
// first check special mana
|
||||
switch (mana) {
|
||||
case B:
|
||||
if (pool.pay(ManaType.BLACK, ability, sourceFilter, game, costToPay)) {
|
||||
if (pool.pay(ManaType.BLACK, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
||||
this.payment.increaseBlack();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case U:
|
||||
if (pool.pay(ManaType.BLUE, ability, sourceFilter, game, costToPay)) {
|
||||
if (pool.pay(ManaType.BLUE, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
||||
this.payment.increaseBlue();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case W:
|
||||
if (pool.pay(ManaType.WHITE, ability, sourceFilter, game, costToPay)) {
|
||||
if (pool.pay(ManaType.WHITE, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
||||
this.payment.increaseWhite();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case G:
|
||||
if (pool.pay(ManaType.GREEN, ability, sourceFilter, game, costToPay)) {
|
||||
if (pool.pay(ManaType.GREEN, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
||||
this.payment.increaseGreen();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case R:
|
||||
if (pool.pay(ManaType.RED, ability, sourceFilter, game, costToPay)) {
|
||||
if (pool.pay(ManaType.RED, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
||||
this.payment.increaseRed();
|
||||
return true;
|
||||
}
|
||||
|
@ -154,7 +162,7 @@ public abstract class ManaCostImpl extends CostImpl implements ManaCost {
|
|||
protected void assignColorless(Ability ability, Game game, ManaPool pool, int mana, Cost costToPay) {
|
||||
int conditionalCount = pool.getConditionalCount(ability, game, null, costToPay);
|
||||
while (mana > payment.count() && (pool.count() > 0 || conditionalCount > 0)) {
|
||||
if (pool.pay(ManaType.COLORLESS, ability, sourceFilter, game, costToPay)) {
|
||||
if (pool.pay(ManaType.COLORLESS, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
||||
this.payment.increaseColorless();
|
||||
}
|
||||
break;
|
||||
|
@ -164,27 +172,27 @@ public abstract class ManaCostImpl extends CostImpl implements ManaCost {
|
|||
protected boolean assignGeneric(Ability ability, Game game, ManaPool pool, int mana, Cost costToPay) {
|
||||
int conditionalCount = pool.getConditionalCount(ability, game, null, costToPay);
|
||||
while (mana > payment.count() && (pool.count() > 0 || conditionalCount > 0)) {
|
||||
if (pool.pay(ManaType.COLORLESS, ability, sourceFilter, game, costToPay)) {
|
||||
if (pool.pay(ManaType.COLORLESS, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
||||
this.payment.increaseColorless();
|
||||
continue;
|
||||
}
|
||||
if (pool.pay(ManaType.BLACK, ability, sourceFilter, game, costToPay)) {
|
||||
if (pool.pay(ManaType.BLACK, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
||||
this.payment.increaseBlack();
|
||||
continue;
|
||||
}
|
||||
if (pool.pay(ManaType.BLUE, ability, sourceFilter, game, costToPay)) {
|
||||
if (pool.pay(ManaType.BLUE, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
||||
this.payment.increaseBlue();
|
||||
continue;
|
||||
}
|
||||
if (pool.pay(ManaType.WHITE, ability, sourceFilter, game, costToPay)) {
|
||||
if (pool.pay(ManaType.WHITE, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
||||
this.payment.increaseWhite();
|
||||
continue;
|
||||
}
|
||||
if (pool.pay(ManaType.GREEN, ability, sourceFilter, game, costToPay)) {
|
||||
if (pool.pay(ManaType.GREEN, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
||||
this.payment.increaseGreen();
|
||||
continue;
|
||||
}
|
||||
if (pool.pay(ManaType.RED, ability, sourceFilter, game, costToPay)) {
|
||||
if (pool.pay(ManaType.RED, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
||||
this.payment.increaseRed();
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -120,6 +120,15 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
|
|||
return manaTotal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mana getUsedManaToPay() {
|
||||
Mana manaTotal = new Mana();
|
||||
for (ManaCost cost : this) {
|
||||
manaTotal.add(cost.getUsedManaToPay());
|
||||
}
|
||||
return manaTotal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) {
|
||||
return pay(ability, game, sourceId, controllerId, noMana, this);
|
||||
|
|
|
@ -43,7 +43,7 @@ public class ColorsOfManaSpentToCastCount implements DynamicValue {
|
|||
}
|
||||
if (spell != null) {
|
||||
// NOT the cmc of the spell on the stack
|
||||
Mana mana = spell.getSpellAbility().getManaCostsToPay().getPayment();
|
||||
Mana mana = spell.getSpellAbility().getManaCostsToPay().getUsedManaToPay();
|
||||
if (mana.getBlack() > 0) {
|
||||
count++;
|
||||
}
|
||||
|
|
|
@ -110,9 +110,10 @@ public class ManaPool implements Serializable {
|
|||
* @param filter
|
||||
* @param game
|
||||
* @param costToPay complete costs to pay (needed to check conditional mana)
|
||||
* @param usedManaToPay the information about what mana was paid
|
||||
* @return
|
||||
*/
|
||||
public boolean pay(ManaType manaType, Ability ability, Filter filter, Game game, Cost costToPay) {
|
||||
public boolean pay(ManaType manaType, Ability ability, Filter filter, Game game, Cost costToPay, Mana usedManaToPay) {
|
||||
if (!autoPayment && manaType != unlockedManaType) {
|
||||
// if manual payment and the needed mana type was not unlocked, nothing will be paid
|
||||
return false;
|
||||
|
@ -149,6 +150,7 @@ public class ManaPool implements Serializable {
|
|||
GameEvent event = new GameEvent(GameEvent.EventType.MANA_PAID, ability.getId(), mana.getSourceId(), ability.getControllerId(), 0, mana.getFlag());
|
||||
event.setData(mana.getOriginalId().toString());
|
||||
game.fireEvent(event);
|
||||
usedManaToPay.increase(mana.getFirstAvailable());
|
||||
mana.remove(usableManaType);
|
||||
if (mana.count() == 0) { // so no items with count 0 stay in list
|
||||
manaItems.remove(mana);
|
||||
|
@ -479,7 +481,7 @@ public class ManaPool implements Serializable {
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean isEmpty(){
|
||||
public boolean isEmpty() {
|
||||
return count() == 0;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue