mirror of
https://github.com/magefree/mage.git
synced 2025-12-22 11:32:00 -08:00
Improved and fixed X mana cost and pays, mana pool:
* Pay X abilities - fixed that it spends all available mana pool instead only needed; * Pay X abilities - added support of interactions with other X effects like Rosheen Meanderer's mana usage for "pay X to prevent"; * Rosheen Meanderer - fixed that it can't use mana for "you may pay X" like Flameblast Dragon's effect (#5206); * Devs: added support to use VariableManaCost to pay X in code (without generic's workaround, use ManaUtil.createManaCost to generate cost to pay);
This commit is contained in:
parent
500fc935e4
commit
437861ec20
20 changed files with 675 additions and 192 deletions
|
|
@ -1,7 +1,5 @@
|
||||||
|
|
||||||
package mage.cards.f;
|
package mage.cards.f;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.AttacksTriggeredAbility;
|
import mage.abilities.common.AttacksTriggeredAbility;
|
||||||
|
|
@ -13,20 +11,22 @@ import mage.abilities.keyword.FlyingAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.SubType;
|
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.SubType;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.common.TargetAnyTarget;
|
import mage.target.common.TargetAnyTarget;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Loki
|
* @author Loki
|
||||||
*/
|
*/
|
||||||
public final class FlameblastDragon extends CardImpl {
|
public final class FlameblastDragon extends CardImpl {
|
||||||
|
|
||||||
public FlameblastDragon(UUID ownerId, CardSetInfo setInfo) {
|
public FlameblastDragon(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{R}{R}");
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}{R}");
|
||||||
this.subtype.add(SubType.DRAGON);
|
this.subtype.add(SubType.DRAGON);
|
||||||
|
|
||||||
this.power = new MageInt(5);
|
this.power = new MageInt(5);
|
||||||
|
|
@ -34,6 +34,7 @@ public final class FlameblastDragon extends CardImpl {
|
||||||
|
|
||||||
// Flying
|
// Flying
|
||||||
this.addAbility(FlyingAbility.getInstance());
|
this.addAbility(FlyingAbility.getInstance());
|
||||||
|
|
||||||
// Whenever Flameblast Dragon attacks, you may pay {X}{R}. If you do, Flameblast Dragon deals X damage to any target.
|
// Whenever Flameblast Dragon attacks, you may pay {X}{R}. If you do, Flameblast Dragon deals X damage to any target.
|
||||||
Ability ability = new AttacksTriggeredAbility(new FlameblastDragonEffect(), false);
|
Ability ability = new AttacksTriggeredAbility(new FlameblastDragonEffect(), false);
|
||||||
ability.addTarget(new TargetAnyTarget());
|
ability.addTarget(new TargetAnyTarget());
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,12 @@ import mage.ConditionalMana;
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.Mana;
|
import mage.Mana;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.condition.Condition;
|
import mage.abilities.costs.Cost;
|
||||||
|
import mage.abilities.costs.mana.ManaCosts;
|
||||||
|
import mage.abilities.costs.mana.VariableManaCost;
|
||||||
import mage.abilities.effects.mana.BasicManaEffect;
|
import mage.abilities.effects.mana.BasicManaEffect;
|
||||||
import mage.abilities.mana.BasicManaAbility;
|
import mage.abilities.mana.BasicManaAbility;
|
||||||
|
import mage.abilities.mana.conditional.ManaCondition;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
|
|
@ -70,7 +73,7 @@ class RosheenMeandererConditionalMana extends ConditionalMana {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RosheenMeandererManaCondition implements Condition {
|
class RosheenMeandererManaCondition extends ManaCondition {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A “cost that contains {X}” may be a spell’s total cost, an activated ability’s cost, a suspend cost, or a cost you’re
|
A “cost that contains {X}” may be a spell’s total cost, an activated ability’s cost, a suspend cost, or a cost you’re
|
||||||
|
|
@ -81,7 +84,11 @@ class RosheenMeandererManaCondition implements Condition {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source, UUID originalId, Cost costToPay) {
|
||||||
return source.getManaCostsToPay().containsX();
|
if (costToPay instanceof ManaCosts) {
|
||||||
|
return !((ManaCosts) costToPay).getVariableCosts().isEmpty();
|
||||||
|
} else {
|
||||||
|
return costToPay instanceof VariableManaCost;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -183,7 +183,7 @@ public class UnboundFlourishingTest extends CardTestPlayerBase {
|
||||||
int xAnnouncedValue = 3;
|
int xAnnouncedValue = 3;
|
||||||
int xMultiplier = 2;
|
int xMultiplier = 2;
|
||||||
VariableManaCost cost = new VariableManaCost(xInstancesCount);
|
VariableManaCost cost = new VariableManaCost(xInstancesCount);
|
||||||
cost.setAmount(xAnnouncedValue * xMultiplier, xAnnouncedValue * xInstancesCount);
|
cost.setAmount(xAnnouncedValue * xMultiplier, xAnnouncedValue * xInstancesCount, false);
|
||||||
|
|
||||||
Assert.assertEquals("instances count", xInstancesCount, cost.getXInstancesCount());
|
Assert.assertEquals("instances count", xInstancesCount, cost.getXInstancesCount());
|
||||||
Assert.assertEquals("boosted X value", xAnnouncedValue * xMultiplier, cost.getAmount());
|
Assert.assertEquals("boosted X value", xAnnouncedValue * xMultiplier, cost.getAmount());
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,377 @@
|
||||||
|
package org.mage.test.cards.mana;
|
||||||
|
|
||||||
|
import mage.Mana;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
|
||||||
|
import mage.abilities.effects.common.CounterUnlessPaysEffect;
|
||||||
|
import mage.abilities.effects.common.DamageTargetEffect;
|
||||||
|
import mage.abilities.effects.mana.AddConditionalManaEffect;
|
||||||
|
import mage.abilities.mana.SimpleManaAbility;
|
||||||
|
import mage.abilities.mana.builder.common.InstantOrSorcerySpellManaBuilder;
|
||||||
|
import mage.abilities.mana.builder.common.SimpleActivatedAbilityManaBuilder;
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.target.TargetSpell;
|
||||||
|
import mage.target.common.TargetAnyTarget;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author JayDi85
|
||||||
|
*/
|
||||||
|
public class ManaPoolTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_OneMana_OneSpell() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||||
|
addCard(Zone.HAND, playerA, "Lightning Bolt"); // {R}
|
||||||
|
|
||||||
|
// make mana
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
checkManaPool("mana", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 1);
|
||||||
|
|
||||||
|
// use for spell
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||||
|
|
||||||
|
checkLife("after", 1, PhaseStep.END_TURN, playerB, 20 - 3);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_MultipleMana_OneSpell() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||||
|
addCard(Zone.HAND, playerA, "Precision Bolt"); // {2}{R}
|
||||||
|
|
||||||
|
// make mana
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
checkManaPool("mana", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 3);
|
||||||
|
|
||||||
|
// use for spell
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Precision Bolt", playerB);
|
||||||
|
|
||||||
|
checkLife("after", 1, PhaseStep.END_TURN, playerB, 20 - 3);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_ConditionalMana_OneSpell() {
|
||||||
|
// +1: Add {R}{R}{R}. Spend this mana only to cast instant or sorcery spells.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Jaya Ballard");
|
||||||
|
addCard(Zone.HAND, playerA, "Precision Bolt"); // {2}{R}
|
||||||
|
|
||||||
|
// make mana
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+1: Add {R}{R}{R}");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkManaPool("mana", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 3);
|
||||||
|
|
||||||
|
// use for spell
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Precision Bolt", playerB);
|
||||||
|
|
||||||
|
checkLife("after", 1, PhaseStep.END_TURN, playerB, 20 - 3);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_ConditionalMana_MultipleSpells() {
|
||||||
|
// +1: Add {R}{R}{R}. Spend this mana only to cast instant or sorcery spells.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Jaya Ballard");
|
||||||
|
addCard(Zone.HAND, playerA, "Lightning Bolt", 2); // {R}
|
||||||
|
|
||||||
|
// make mana
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+1: Add {R}{R}{R}");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkManaPool("mana", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 3);
|
||||||
|
|
||||||
|
// use for spell
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkManaPool("mana", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 1);
|
||||||
|
|
||||||
|
checkLife("after", 1, PhaseStep.END_TURN, playerB, 20 - 3 * 2);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_MultipleMana_OneXSpell() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
|
||||||
|
addCard(Zone.HAND, playerA, "Volcanic Geyser"); // {X}{R}{R}
|
||||||
|
|
||||||
|
// make mana
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
checkManaPool("mana", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 4);
|
||||||
|
|
||||||
|
// use for spell
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Volcanic Geyser", playerB);
|
||||||
|
setChoice(playerA, "X=2");
|
||||||
|
|
||||||
|
checkLife("after", 1, PhaseStep.END_TURN, playerB, 20 - 2);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_MultipleMana_MultipleXSpell() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4 * 2);
|
||||||
|
addCard(Zone.HAND, playerA, "Volcanic Geyser", 2); // {X}{R}{R}
|
||||||
|
|
||||||
|
// make mana
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
//
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
checkManaPool("mana", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 4 * 2);
|
||||||
|
|
||||||
|
// use for spell
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Volcanic Geyser", playerB);
|
||||||
|
setChoice(playerA, "X=2");
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Volcanic Geyser", playerB);
|
||||||
|
setChoice(playerA, "X=2");
|
||||||
|
|
||||||
|
checkLife("after", 1, PhaseStep.END_TURN, playerB, 20 - 2 * 2);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_ConditionalMana_OneXSpell() {
|
||||||
|
addCustomCardWithAbility("add 10", playerA, new SimpleActivatedAbility(Zone.ALL,
|
||||||
|
new AddConditionalManaEffect(Mana.RedMana(10), new InstantOrSorcerySpellManaBuilder()),
|
||||||
|
new ManaCostsImpl("")));
|
||||||
|
addCard(Zone.HAND, playerA, "Volcanic Geyser"); // {X}{R}{R}
|
||||||
|
|
||||||
|
// make mana
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Add {R}");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkManaPool("mana", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 10);
|
||||||
|
|
||||||
|
// use for spell
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Volcanic Geyser", playerB);
|
||||||
|
setChoice(playerA, "X=1");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkManaPool("mana", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 10 - 3);
|
||||||
|
|
||||||
|
checkLife("after", 1, PhaseStep.END_TURN, playerB, 20 - 1);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_ConditionalMana_MultipleXSpell() {
|
||||||
|
addCustomCardWithAbility("add 10", playerA, new SimpleActivatedAbility(Zone.ALL,
|
||||||
|
new AddConditionalManaEffect(Mana.RedMana(10), new InstantOrSorcerySpellManaBuilder()),
|
||||||
|
new ManaCostsImpl("")));
|
||||||
|
addCard(Zone.HAND, playerA, "Volcanic Geyser", 2); // {X}{R}{R}
|
||||||
|
|
||||||
|
// make mana
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Add {R}");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkManaPool("mana", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 10);
|
||||||
|
|
||||||
|
// use for spell 1
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Volcanic Geyser", playerB);
|
||||||
|
setChoice(playerA, "X=1");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkManaPool("mana", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 10 - 3);
|
||||||
|
|
||||||
|
// use for spell 2
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Volcanic Geyser", playerB);
|
||||||
|
setChoice(playerA, "X=1");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkManaPool("mana", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 10 - 3 * 2);
|
||||||
|
|
||||||
|
checkLife("after", 1, PhaseStep.END_TURN, playerB, 20 - 1 * 2);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_MultipleMana_OneXAbility() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
|
||||||
|
//
|
||||||
|
Ability ability = new SimpleActivatedAbility(Zone.ALL, new DamageTargetEffect(ManacostVariableValue.instance), new ManaCostsImpl("{X}"));
|
||||||
|
ability.addTarget(new TargetAnyTarget());
|
||||||
|
addCustomCardWithAbility("damage X", playerA, ability);
|
||||||
|
|
||||||
|
// make mana
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
checkManaPool("mana", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 4);
|
||||||
|
|
||||||
|
// use for ability
|
||||||
|
showAvaileableAbilities("before ability", 1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{X}:", playerB);
|
||||||
|
setChoice(playerA, "X=3");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkManaPool("mana", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 4 - 3);
|
||||||
|
|
||||||
|
checkLife("after", 1, PhaseStep.END_TURN, playerB, 20 - 3);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_ConditionalMana_OneXAbility() {
|
||||||
|
addCustomCardWithAbility("add 10", playerA, new SimpleActivatedAbility(Zone.ALL,
|
||||||
|
new AddConditionalManaEffect(Mana.RedMana(10), new SimpleActivatedAbilityManaBuilder()),
|
||||||
|
new ManaCostsImpl("")));
|
||||||
|
//
|
||||||
|
Ability ability = new SimpleActivatedAbility(Zone.ALL, new DamageTargetEffect(ManacostVariableValue.instance), new ManaCostsImpl("{X}"));
|
||||||
|
ability.addTarget(new TargetAnyTarget());
|
||||||
|
addCustomCardWithAbility("damage X", playerA, ability);
|
||||||
|
|
||||||
|
// make mana
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Add {R}");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkManaPool("mana", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 10);
|
||||||
|
|
||||||
|
// use for ability
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{X}:", playerB);
|
||||||
|
setChoice(playerA, "X=3");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkManaPool("mana", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 10 - 3);
|
||||||
|
|
||||||
|
checkLife("after", 1, PhaseStep.END_TURN, playerB, 20 - 3);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_MultipleMana_OneXPart() {
|
||||||
|
addCard(Zone.HAND, playerA, "Lightning Bolt"); // {R}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1 + 3 + 1);
|
||||||
|
//
|
||||||
|
Ability ability = new SimpleActivatedAbility(Zone.ALL, new DamageTargetEffect(ManacostVariableValue.instance), new ManaCostsImpl(""));
|
||||||
|
ability.addTarget(new TargetAnyTarget());
|
||||||
|
addCustomCardWithAbility("damage X", playerA, ability);
|
||||||
|
//
|
||||||
|
// {X}: Counter target spell
|
||||||
|
ability = new SimpleActivatedAbility(Zone.ALL, new CounterUnlessPaysEffect(ManacostVariableValue.instance), new ManaCostsImpl("{X}"));
|
||||||
|
ability.addTarget(new TargetSpell());
|
||||||
|
addCustomCardWithAbility("counter until pay X", playerB, ability);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Island", 3);
|
||||||
|
|
||||||
|
// make mana for spell
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
checkManaPool("mana spell", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 1);
|
||||||
|
// cast spell
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||||
|
// make mana for pay X to prevent
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}"); // one must be saved in pool
|
||||||
|
checkManaPool("mana prevent", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 4);
|
||||||
|
|
||||||
|
// counter by X=3
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{X}: Counter");
|
||||||
|
setChoice(playerB, "X=3");
|
||||||
|
addTarget(playerB, "Lightning Bolt");
|
||||||
|
// pay to prevent
|
||||||
|
setChoice(playerA, "Yes"); // pay 3 to prevent counter
|
||||||
|
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkManaPool("mana after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 4 - 3);
|
||||||
|
|
||||||
|
checkLife("after", 1, PhaseStep.END_TURN, playerB, 20 - 3);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_ConditionalMana_OneXPart() {
|
||||||
|
addCard(Zone.HAND, playerA, "Lightning Bolt"); // {R}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||||
|
//
|
||||||
|
addCustomCardWithAbility("add 10", playerA, new SimpleManaAbility(Zone.ALL,
|
||||||
|
new AddConditionalManaEffect(Mana.RedMana(10), new SimpleActivatedAbilityManaBuilder()),
|
||||||
|
new ManaCostsImpl("")));
|
||||||
|
//
|
||||||
|
Ability ability = new SimpleActivatedAbility(Zone.ALL, new DamageTargetEffect(ManacostVariableValue.instance), new ManaCostsImpl(""));
|
||||||
|
ability.addTarget(new TargetAnyTarget());
|
||||||
|
addCustomCardWithAbility("damage X", playerA, ability);
|
||||||
|
//
|
||||||
|
// {X}: Counter target spell
|
||||||
|
ability = new SimpleActivatedAbility(Zone.ALL, new CounterUnlessPaysEffect(ManacostVariableValue.instance), new ManaCostsImpl("{X}"));
|
||||||
|
ability.addTarget(new TargetSpell());
|
||||||
|
addCustomCardWithAbility("counter until pay X", playerB, ability);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Island", 3);
|
||||||
|
|
||||||
|
// make mana for spell
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||||
|
checkManaPool("mana spell", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 1);
|
||||||
|
// cast spell
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||||
|
// make mana for pay X to prevent
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Add {R}");
|
||||||
|
checkManaPool("mana prevent", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 10);
|
||||||
|
|
||||||
|
// counter by X=3
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{X}: Counter");
|
||||||
|
setChoice(playerB, "X=3");
|
||||||
|
addTarget(playerB, "Lightning Bolt");
|
||||||
|
// pay to prevent
|
||||||
|
setChoice(playerA, "Yes"); // pay 3 to prevent counter
|
||||||
|
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkManaPool("mana after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "R", 10 + 1 - 1 - 3);
|
||||||
|
|
||||||
|
checkLife("after", 1, PhaseStep.END_TURN, playerB, 20 - 3);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -93,4 +93,92 @@ public class RosheenMeandererManaXTest extends CardTestPlayerBase {
|
||||||
assertAllCommandsUsed();
|
assertAllCommandsUsed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/magefree/mage/issues/5206
|
||||||
|
|
||||||
|
// Flameblast Dragon {4}{R}{R}
|
||||||
|
// 5/5
|
||||||
|
// Flying
|
||||||
|
// Whenever Flameblast Dragon attacks, you may pay {X}{R}. If you do, Flameblast Dragon deals X damage to any target.
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_SimpleDragon() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Flameblast Dragon");
|
||||||
|
|
||||||
|
// attack (-5)
|
||||||
|
attack(1, playerA, "Flameblast Dragon", playerB);
|
||||||
|
|
||||||
|
// with extra damage (-3)
|
||||||
|
setChoice(playerA, "Yes");
|
||||||
|
setChoice(playerA, "X=3");
|
||||||
|
addTarget(playerA, playerB);
|
||||||
|
|
||||||
|
checkLife("after", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, 20 - 5 - 3);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_PayXForDragonAbility() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Flameblast Dragon");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Rosheen Meanderer");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||||
|
|
||||||
|
// make 4 mana for X pay
|
||||||
|
activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "{T}: Add {C}");
|
||||||
|
checkManaPool("mana", 1, PhaseStep.DECLARE_ATTACKERS, playerA, "C", 4);
|
||||||
|
|
||||||
|
// attack (-5)
|
||||||
|
attack(1, playerA, "Flameblast Dragon", playerB);
|
||||||
|
|
||||||
|
// with extra damage (-3)
|
||||||
|
setChoice(playerA, "Yes");
|
||||||
|
setChoice(playerA, "X=3"); // need to pay {3}{R}
|
||||||
|
addTarget(playerA, playerB);
|
||||||
|
|
||||||
|
checkLife("after", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, 20 - 5 - 3);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Condescend {X}{U}
|
||||||
|
// Counter target spell unless its controller pays {X}. Scry 2.
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_PayXForCondescendPrevent() {
|
||||||
|
addCard(Zone.HAND, playerB, "Condescend");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Island", 3);
|
||||||
|
//
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Rosheen Meanderer");
|
||||||
|
//
|
||||||
|
addCard(Zone.HAND, playerA, "Lightning Bolt");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||||
|
|
||||||
|
// cast bolt
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||||
|
// counter with condescend
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Condescend");
|
||||||
|
setChoice(playerB, "X=2");
|
||||||
|
addTarget(playerB, "Lightning Bolt");
|
||||||
|
// make 4 mana for X pay
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {C}");
|
||||||
|
checkManaPool("mana", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "C", 4);
|
||||||
|
// pay to prevent
|
||||||
|
setChoice(playerA, "Yes"); // pay 2 to prevent counter
|
||||||
|
|
||||||
|
checkLife("after", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, 20 - 3);
|
||||||
|
checkHandCardCount("after", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", 0);
|
||||||
|
checkHandCardCount("after", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Condescend", 0);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -256,7 +256,7 @@ public abstract class AbilityImpl implements Ability {
|
||||||
VariableManaCost xCosts = new VariableManaCost();
|
VariableManaCost xCosts = new VariableManaCost();
|
||||||
// no x events - rules from Unbound Flourishing:
|
// no x events - rules from Unbound Flourishing:
|
||||||
// - Spells with additional costs that include X won't be affected by Unbound Flourishing. X must be in the spell's mana cost.
|
// - Spells with additional costs that include X won't be affected by Unbound Flourishing. X must be in the spell's mana cost.
|
||||||
xCosts.setAmount(xValue, xValue);
|
xCosts.setAmount(xValue, xValue, false);
|
||||||
this.getManaCostsToPay().add(xCosts);
|
this.getManaCostsToPay().add(xCosts);
|
||||||
} else {
|
} else {
|
||||||
this.getManaCostsToPay().clear();
|
this.getManaCostsToPay().clear();
|
||||||
|
|
@ -525,7 +525,7 @@ public abstract class AbilityImpl implements Ability {
|
||||||
// set the xcosts to paid
|
// set the xcosts to paid
|
||||||
// no x events - rules from Unbound Flourishing:
|
// no x events - rules from Unbound Flourishing:
|
||||||
// - Spells with additional costs that include X won't be affected by Unbound Flourishing. X must be in the spell's mana cost.
|
// - Spells with additional costs that include X won't be affected by Unbound Flourishing. X must be in the spell's mana cost.
|
||||||
variableCost.setAmount(xValue, xValue);
|
variableCost.setAmount(xValue, xValue, false);
|
||||||
((Cost) variableCost).setPaid();
|
((Cost) variableCost).setPaid();
|
||||||
String message = controller.getLogName() + " announces a value of " + xValue + " (" + variableCost.getActionText() + ')';
|
String message = controller.getLogName() + " announces a value of " + xValue + " (" + variableCost.getActionText() + ')';
|
||||||
announceString.append(message);
|
announceString.append(message);
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,9 @@ public interface VariableCost {
|
||||||
*
|
*
|
||||||
* @param xValue - value of X
|
* @param xValue - value of X
|
||||||
* @param xPay - total value of pays for X (X * xMultiplier * xInstancesCount)
|
* @param xPay - total value of pays for X (X * xMultiplier * xInstancesCount)
|
||||||
|
* @param isPayed - is that was real payed or just value setup
|
||||||
*/
|
*/
|
||||||
void setAmount(int xValue, int xPay);
|
void setAmount(int xValue, int xPay, boolean isPayed);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the action text (e.g. "creature cards to exile from your hand", "life to pay")
|
* returns the action text (e.g. "creature cards to exile from your hand", "life to pay")
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ public abstract class VariableCostImpl implements Cost, VariableCost {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAmount(int xValue, int xPay) {
|
public void setAmount(int xValue, int xPay, boolean isPayed) {
|
||||||
amountPaid = xPay;
|
amountPaid = xPay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ public class ExileFromHandCost extends CostImpl {
|
||||||
VariableManaCost vmc = new VariableManaCost();
|
VariableManaCost vmc = new VariableManaCost();
|
||||||
// no x events - rules from Unbound Flourishing:
|
// no x events - rules from Unbound Flourishing:
|
||||||
// - Spells with additional costs that include X won't be affected by Unbound Flourishing. X must be in the spell's mana cost.
|
// - Spells with additional costs that include X won't be affected by Unbound Flourishing. X must be in the spell's mana cost.
|
||||||
vmc.setAmount(cmc, cmc);
|
vmc.setAmount(cmc, cmc, false);
|
||||||
vmc.setPaid();
|
vmc.setPaid();
|
||||||
ability.getManaCostsToPay().add(vmc);
|
ability.getManaCostsToPay().add(vmc);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package mage.abilities.costs.mana;
|
package mage.abilities.costs.mana;
|
||||||
|
|
||||||
import mage.Mana;
|
import mage.Mana;
|
||||||
|
|
@ -42,7 +41,7 @@ public class GenericManaCost extends ManaCostImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void assignPayment(Game game, Ability ability, ManaPool pool, Cost costsToPay) {
|
public void assignPayment(Game game, Ability ability, ManaPool pool, Cost costsToPay) {
|
||||||
this.assignGeneric(ability, game, pool, mana, costsToPay);
|
this.assignGeneric(ability, game, pool, mana, null, costsToPay);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,5 @@
|
||||||
|
|
||||||
package mage.abilities.costs.mana;
|
package mage.abilities.costs.mana;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.Mana;
|
import mage.Mana;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
|
|
@ -12,11 +8,16 @@ import mage.abilities.mana.ManaOptions;
|
||||||
import mage.constants.ColoredManaSymbol;
|
import mage.constants.ColoredManaSymbol;
|
||||||
import mage.constants.ManaType;
|
import mage.constants.ManaType;
|
||||||
import mage.filter.Filter;
|
import mage.filter.Filter;
|
||||||
|
import mage.filter.FilterMana;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.players.ManaPool;
|
import mage.players.ManaPool;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.util.ManaUtil;
|
import mage.util.ManaUtil;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public abstract class ManaCostImpl extends CostImpl implements ManaCost {
|
public abstract class ManaCostImpl extends CostImpl implements ManaCost {
|
||||||
|
|
||||||
protected Mana payment;
|
protected Mana payment;
|
||||||
|
|
@ -143,33 +144,49 @@ public abstract class ManaCostImpl extends CostImpl implements ManaCost {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean assignGeneric(Ability ability, Game game, ManaPool pool, int mana, Cost costToPay) {
|
protected boolean assignGeneric(Ability ability, Game game, ManaPool pool, int mana, FilterMana filterMana, Cost costToPay) {
|
||||||
int conditionalCount = pool.getConditionalCount(ability, game, null, costToPay);
|
int conditionalCount = pool.getConditionalCount(ability, game, filterMana, costToPay);
|
||||||
while (mana > payment.count() && (pool.count() > 0 || conditionalCount > 0)) {
|
while (mana > payment.count() && (pool.count() > 0 || conditionalCount > 0)) {
|
||||||
if (pool.pay(ManaType.COLORLESS, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
// try to use different mana to pay (conditional mana will used in pool.pay)
|
||||||
|
// filterMana can be null, uses for spells like "spend only black mana on X"
|
||||||
|
|
||||||
|
// {C}
|
||||||
|
if ((filterMana == null || filterMana.isColorless()) && pool.pay(ManaType.COLORLESS, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
||||||
this.payment.increaseColorless();
|
this.payment.increaseColorless();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (pool.pay(ManaType.BLACK, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
|
||||||
|
// {B}
|
||||||
|
if ((filterMana == null || filterMana.isBlack()) && pool.pay(ManaType.BLACK, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
||||||
this.payment.increaseBlack();
|
this.payment.increaseBlack();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (pool.pay(ManaType.BLUE, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
|
||||||
|
// {U}
|
||||||
|
if ((filterMana == null || filterMana.isBlue()) && pool.pay(ManaType.BLUE, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
||||||
this.payment.increaseBlue();
|
this.payment.increaseBlue();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (pool.pay(ManaType.WHITE, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
|
||||||
|
// {W}
|
||||||
|
if ((filterMana == null || filterMana.isWhite()) && pool.pay(ManaType.WHITE, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
||||||
this.payment.increaseWhite();
|
this.payment.increaseWhite();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (pool.pay(ManaType.GREEN, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
|
||||||
|
// {G}
|
||||||
|
if ((filterMana == null || filterMana.isGreen()) && pool.pay(ManaType.GREEN, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
||||||
this.payment.increaseGreen();
|
this.payment.increaseGreen();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (pool.pay(ManaType.RED, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
|
||||||
|
// {R}
|
||||||
|
if ((filterMana == null || filterMana.isRed()) && pool.pay(ManaType.RED, ability, sourceFilter, game, costToPay, usedManaToPay)) {
|
||||||
this.payment.increaseRed();
|
this.payment.increaseRed();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nothing to pay
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return mana > payment.count();
|
return mana > payment.count();
|
||||||
|
|
@ -208,14 +225,14 @@ public abstract class ManaCostImpl extends CostImpl implements ManaCost {
|
||||||
}
|
}
|
||||||
Player player = game.getPlayer(controllerId);
|
Player player = game.getPlayer(controllerId);
|
||||||
if (!player.getManaPool().isForcedToPay()) {
|
if (!player.getManaPool().isForcedToPay()) {
|
||||||
assignPayment(game, ability, player.getManaPool(), costToPay);
|
assignPayment(game, ability, player.getManaPool(), costToPay != null ? costToPay : this);
|
||||||
}
|
}
|
||||||
game.getState().getSpecialActions().removeManaActions();
|
game.getState().getSpecialActions().removeManaActions();
|
||||||
while (!isPaid()) {
|
while (!isPaid()) {
|
||||||
ManaCost unpaid = this.getUnpaid();
|
ManaCost unpaid = this.getUnpaid();
|
||||||
String promptText = ManaUtil.addSpecialManaPayAbilities(ability, game, unpaid);
|
String promptText = ManaUtil.addSpecialManaPayAbilities(ability, game, unpaid);
|
||||||
if (player.playMana(ability, unpaid, promptText, game)) {
|
if (player.playMana(ability, unpaid, promptText, game)) {
|
||||||
assignPayment(game, ability, player.getManaPool(), costToPay);
|
assignPayment(game, ability, player.getManaPool(), costToPay != null ? costToPay : this);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -232,7 +232,7 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
|
||||||
public void setX(int xValue, int xPay) {
|
public void setX(int xValue, int xPay) {
|
||||||
List<VariableCost> variableCosts = getVariableCosts();
|
List<VariableCost> variableCosts = getVariableCosts();
|
||||||
if (!variableCosts.isEmpty()) {
|
if (!variableCosts.isEmpty()) {
|
||||||
variableCosts.get(0).setAmount(xValue, xPay);
|
variableCosts.get(0).setAmount(xValue, xPay, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
|
|
||||||
package mage.abilities.costs.mana;
|
package mage.abilities.costs.mana;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import mage.Mana;
|
import mage.Mana;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
|
|
@ -10,6 +7,9 @@ import mage.constants.ColoredManaSymbol;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.players.ManaPool;
|
import mage.players.ManaPool;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class MonoHybridManaCost extends ManaCostImpl {
|
public class MonoHybridManaCost extends ManaCostImpl {
|
||||||
|
|
||||||
private final ColoredManaSymbol mana;
|
private final ColoredManaSymbol mana;
|
||||||
|
|
@ -45,7 +45,7 @@ public class MonoHybridManaCost extends ManaCostImpl {
|
||||||
@Override
|
@Override
|
||||||
public void assignPayment(Game game, Ability ability, ManaPool pool, Cost costToPay) {
|
public void assignPayment(Game game, Ability ability, ManaPool pool, Cost costToPay) {
|
||||||
if (!assignColored(ability, game, pool, mana, costToPay)) {
|
if (!assignColored(ability, game, pool, mana, costToPay)) {
|
||||||
assignGeneric(ability, game, pool, mana2, costToPay);
|
assignGeneric(ability, game, pool, mana2, null, costToPay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package mage.abilities.costs.mana;
|
package mage.abilities.costs.mana;
|
||||||
|
|
||||||
import mage.Mana;
|
import mage.Mana;
|
||||||
|
|
@ -36,7 +35,7 @@ public class SnowManaCost extends ManaCostImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void assignPayment(Game game, Ability ability, ManaPool pool, Cost costToPay) {
|
public void assignPayment(Game game, Ability ability, ManaPool pool, Cost costToPay) {
|
||||||
this.assignGeneric(ability, game, pool, 1, costToPay);
|
this.assignGeneric(ability, game, pool, 1, null, costToPay);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -10,13 +10,20 @@ import mage.game.Game;
|
||||||
import mage.players.ManaPool;
|
import mage.players.ManaPool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com, JayDi85
|
||||||
*/
|
*/
|
||||||
public class VariableManaCost extends ManaCostImpl implements VariableCost {
|
public final class VariableManaCost extends ManaCostImpl implements VariableCost {
|
||||||
|
|
||||||
protected int xInstancesCount; // number of {X}
|
// variable mana cost usage on 2019-06-20:
|
||||||
|
// 1. as X value in spell/ability cast (announce X, set VariableManaCost as paid and add generic mana to pay instead)
|
||||||
|
// 2. as X value in direct pay (X already announced, cost is unpaid, need direct pay)
|
||||||
|
|
||||||
|
protected int xInstancesCount; // number of {X} instances in cost like {X} or {X}{X}
|
||||||
protected int xValue = 0; // final X value after announce and replace events
|
protected int xValue = 0; // final X value after announce and replace events
|
||||||
protected FilterMana filter;
|
protected int xPay = 0; // final/total need pay after announce and replace events (example: {X}{X}, X=3, xPay = 6)
|
||||||
|
protected boolean wasAnnounced = false;
|
||||||
|
|
||||||
|
protected FilterMana filter; // mana filter that can be used for that cost
|
||||||
protected int minX = 0;
|
protected int minX = 0;
|
||||||
protected int maxX = Integer.MAX_VALUE;
|
protected int maxX = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
|
@ -34,6 +41,8 @@ public class VariableManaCost extends ManaCostImpl implements VariableCost {
|
||||||
super(manaCost);
|
super(manaCost);
|
||||||
this.xInstancesCount = manaCost.xInstancesCount;
|
this.xInstancesCount = manaCost.xInstancesCount;
|
||||||
this.xValue = manaCost.xValue;
|
this.xValue = manaCost.xValue;
|
||||||
|
this.xPay = manaCost.xPay;
|
||||||
|
this.wasAnnounced = manaCost.wasAnnounced;
|
||||||
if (manaCost.filter != null) {
|
if (manaCost.filter != null) {
|
||||||
this.filter = manaCost.filter.copy();
|
this.filter = manaCost.filter.copy();
|
||||||
}
|
}
|
||||||
|
|
@ -48,9 +57,8 @@ public class VariableManaCost extends ManaCostImpl implements VariableCost {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void assignPayment(Game game, Ability ability, ManaPool pool, Cost costToPay) {
|
public void assignPayment(Game game, Ability ability, ManaPool pool, Cost costToPay) {
|
||||||
payment.add(pool.getMana(filter));
|
// X mana cost always pays as generic mana
|
||||||
payment.add(pool.getAllConditionalMana(ability, game, filter));
|
this.assignGeneric(ability, game, pool, xPay, filter, costToPay);
|
||||||
pool.payX(ability, game, filter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -66,6 +74,14 @@ public class VariableManaCost extends ManaCostImpl implements VariableCost {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPaid() {
|
||||||
|
if (!wasAnnounced) return false;
|
||||||
|
if (paid) return true;
|
||||||
|
|
||||||
|
return this.isColorlessPaid(xPay);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VariableManaCost getUnpaid() {
|
public VariableManaCost getUnpaid() {
|
||||||
return this;
|
return this;
|
||||||
|
|
@ -74,19 +90,23 @@ public class VariableManaCost extends ManaCostImpl implements VariableCost {
|
||||||
@Override
|
@Override
|
||||||
public int getAmount() {
|
public int getAmount() {
|
||||||
// must return X value
|
// must return X value
|
||||||
//return payment.count() / multiplier;
|
|
||||||
return this.xValue;
|
return this.xValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAmount(int xValue, int xPay) {
|
public void setAmount(int xValue, int xPay, boolean isPayed) {
|
||||||
|
// xPay is total pay value (X * instances)
|
||||||
this.xValue = xValue;
|
this.xValue = xValue;
|
||||||
|
this.xPay = xPay;
|
||||||
|
if (isPayed) {
|
||||||
payment.setGeneric(xPay);
|
payment.setGeneric(xPay);
|
||||||
}
|
}
|
||||||
|
this.wasAnnounced = true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean testPay(Mana testMana) {
|
public boolean testPay(Mana testMana) {
|
||||||
return true;
|
return true; // TODO: need rework to generic mana style?
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -121,27 +141,27 @@ public class VariableManaCost extends ManaCostImpl implements VariableCost {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int announceXValue(Ability source, Game game) {
|
public int announceXValue(Ability source, Game game) {
|
||||||
throw new UnsupportedOperationException("Not supported."); //To change body of generated methods, choose Tools | Templates.
|
throw new UnsupportedOperationException("Not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Cost getFixedCostsFromAnnouncedValue(int xValue) {
|
public Cost getFixedCostsFromAnnouncedValue(int xValue) {
|
||||||
throw new UnsupportedOperationException("Not supported."); //To change body of generated methods, choose Tools | Templates.
|
throw new UnsupportedOperationException("Not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getActionText() {
|
public String getActionText() {
|
||||||
throw new UnsupportedOperationException("Not supported."); //To change body of generated methods, choose Tools | Templates.
|
throw new UnsupportedOperationException("Not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMinValue(Ability source, Game game) {
|
public int getMinValue(Ability source, Game game) {
|
||||||
throw new UnsupportedOperationException("Not supported."); //To change body of generated methods, choose Tools | Templates.
|
throw new UnsupportedOperationException("Not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMaxValue(Ability source, Game game) {
|
public int getMaxValue(Ability source, Game game) {
|
||||||
throw new UnsupportedOperationException("Not supported."); //To change body of generated methods, choose Tools | Templates.
|
throw new UnsupportedOperationException("Not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public FilterMana getFilter() {
|
public FilterMana getFilter() {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
|
|
||||||
package mage.abilities.effects.common;
|
package mage.abilities.effects.common;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.Mode;
|
import mage.abilities.Mode;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.mana.GenericManaCost;
|
|
||||||
import mage.abilities.costs.mana.ManaCost;
|
import mage.abilities.costs.mana.ManaCost;
|
||||||
import mage.abilities.dynamicvalue.DynamicValue;
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
|
@ -12,9 +10,9 @@ import mage.constants.Outcome;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.stack.StackObject;
|
import mage.game.stack.StackObject;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
import mage.util.ManaUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public class CounterUnlessPaysEffect extends OneShotEffect {
|
public class CounterUnlessPaysEffect extends OneShotEffect {
|
||||||
|
|
@ -54,23 +52,27 @@ public class CounterUnlessPaysEffect extends OneShotEffect {
|
||||||
Player player = game.getPlayer(spell.getControllerId());
|
Player player = game.getPlayer(spell.getControllerId());
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
Cost costToPay;
|
Cost costToPay;
|
||||||
|
String costValueMessage;
|
||||||
if (cost != null) {
|
if (cost != null) {
|
||||||
costToPay = cost.copy();
|
costToPay = cost.copy();
|
||||||
|
costValueMessage = costToPay.getText();
|
||||||
} else {
|
} else {
|
||||||
costToPay = new GenericManaCost(genericMana.calculate(game, source, this));
|
costValueMessage = "{" + genericMana.calculate(game, source, this) + "}";
|
||||||
|
costToPay = ManaUtil.createManaCost(genericMana, game, source, this);
|
||||||
}
|
}
|
||||||
String message;
|
String message;
|
||||||
if (costToPay instanceof ManaCost) {
|
if (costToPay instanceof ManaCost) {
|
||||||
message = "Would you like to pay " + costToPay.getText() + " to prevent counter effect?";
|
message = "Would you like to pay " + costValueMessage + " to prevent counter effect?";
|
||||||
} else {
|
} else {
|
||||||
message = costToPay.getText() + " to prevent counter effect?";
|
message = costValueMessage + " to prevent counter effect?";
|
||||||
}
|
}
|
||||||
|
|
||||||
costToPay.clearPaid();
|
costToPay.clearPaid();
|
||||||
if (!(player.chooseUse(Outcome.Benefit, message, source, game) && costToPay.pay(source, game, spell.getSourceId(), spell.getControllerId(), false, null))) {
|
if (!(player.chooseUse(Outcome.Benefit, message, source, game) && costToPay.pay(source, game, spell.getSourceId(), spell.getControllerId(), false, null))) {
|
||||||
game.informPlayers(player.getLogName() + " chooses not to pay " + costToPay.getText() + " to prevent the counter effect");
|
game.informPlayers(player.getLogName() + " chooses not to pay " + costValueMessage + " to prevent the counter effect");
|
||||||
return game.getStack().counter(spell.getId(), source.getSourceId(), game);
|
return game.getStack().counter(spell.getId(), source.getSourceId(), game);
|
||||||
}
|
}
|
||||||
game.informPlayers(player.getLogName() + " chooses to pay " + costToPay.getText() + " to prevent the counter effect");
|
game.informPlayers(player.getLogName() + " chooses to pay " + costValueMessage + " to prevent the counter effect");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,5 @@
|
||||||
/*
|
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package mage.abilities.mana.builder.common;
|
package mage.abilities.mana.builder.common;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.ConditionalMana;
|
import mage.ConditionalMana;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.Mana;
|
import mage.Mana;
|
||||||
|
|
@ -17,8 +11,9 @@ import mage.abilities.mana.builder.ConditionalManaBuilder;
|
||||||
import mage.abilities.mana.conditional.ManaCondition;
|
import mage.abilities.mana.conditional.ManaCondition;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
*/
|
*/
|
||||||
public class InstantOrSorcerySpellManaBuilder extends ConditionalManaBuilder {
|
public class InstantOrSorcerySpellManaBuilder extends ConditionalManaBuilder {
|
||||||
|
|
@ -49,9 +44,7 @@ class InstantOrSorceryCastManaCondition extends ManaCondition implements Conditi
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
if (source instanceof SpellAbility) {
|
if (source instanceof SpellAbility) {
|
||||||
MageObject object = game.getObject(source.getSourceId());
|
MageObject object = game.getObject(source.getSourceId());
|
||||||
if (object != null && (object.isInstant() || object.isSorcery())) {
|
return object != null && (object.isInstant() || object.isSorcery());
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
package mage.abilities.mana.builder.common;
|
||||||
|
|
||||||
|
import mage.ConditionalMana;
|
||||||
|
import mage.Mana;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
import mage.abilities.condition.Condition;
|
||||||
|
import mage.abilities.costs.Cost;
|
||||||
|
import mage.abilities.mana.builder.ConditionalManaBuilder;
|
||||||
|
import mage.abilities.mana.conditional.ManaCondition;
|
||||||
|
import mage.game.Game;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* testing class
|
||||||
|
*
|
||||||
|
* @author JayDi85
|
||||||
|
*/
|
||||||
|
public class SimpleActivatedAbilityManaBuilder extends ConditionalManaBuilder {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConditionalMana build(Object... options) {
|
||||||
|
return new SimpleActivatedAbilityConditionalMana(this.mana);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRule() {
|
||||||
|
return "Spend this mana only to activate simple abilities";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SimpleActivatedAbilityConditionalMana extends ConditionalMana {
|
||||||
|
|
||||||
|
public SimpleActivatedAbilityConditionalMana(Mana mana) {
|
||||||
|
super(mana);
|
||||||
|
staticText = "Spend this mana only to activate simple abilities";
|
||||||
|
addCondition(new SimpleActivatedAbilityManaCondition());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SimpleActivatedAbilityManaCondition extends ManaCondition implements Condition {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
return source instanceof SimpleActivatedAbility;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source, UUID originalId, Cost costsToPay) {
|
||||||
|
return apply(game, source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,12 +1,5 @@
|
||||||
package mage.players;
|
package mage.players;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.ConditionalMana;
|
import mage.ConditionalMana;
|
||||||
import mage.Mana;
|
import mage.Mana;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
|
|
@ -22,8 +15,10 @@ import mage.game.events.GameEvent.EventType;
|
||||||
import mage.game.events.ManaEvent;
|
import mage.game.events.ManaEvent;
|
||||||
import mage.game.stack.Spell;
|
import mage.game.stack.Spell;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public class ManaPool implements Serializable {
|
public class ManaPool implements Serializable {
|
||||||
|
|
@ -84,7 +79,6 @@ public class ManaPool implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @param manaType the mana type that should be paid
|
* @param manaType the mana type that should be paid
|
||||||
* @param ability
|
* @param ability
|
||||||
* @param filter
|
* @param filter
|
||||||
|
|
@ -258,86 +252,6 @@ public class ManaPool implements Serializable {
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int payX(Ability ability, Game game) {
|
|
||||||
int total = 0;
|
|
||||||
Iterator<ManaPoolItem> it = manaItems.iterator();
|
|
||||||
while (it.hasNext()) {
|
|
||||||
ManaPoolItem item = it.next();
|
|
||||||
if (item.isConditional()) {
|
|
||||||
ConditionalMana cm = item.getConditionalMana();
|
|
||||||
if (cm.apply(ability, game, cm.getManaProducerId(), null)) {
|
|
||||||
total += item.count();
|
|
||||||
it.remove();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
total += item.count();
|
|
||||||
it.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* remove all mana from pool that applies and that matches filter
|
|
||||||
*
|
|
||||||
* @param ability
|
|
||||||
* @param game
|
|
||||||
* @param filter
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public int payX(Ability ability, Game game, FilterMana filter) {
|
|
||||||
if (filter == null) {
|
|
||||||
return payX(ability, game);
|
|
||||||
}
|
|
||||||
int total = 0;
|
|
||||||
Iterator<ManaPoolItem> it = manaItems.iterator();
|
|
||||||
while (it.hasNext()) {
|
|
||||||
ManaPoolItem item = it.next();
|
|
||||||
if (item.isConditional()) {
|
|
||||||
ConditionalMana c = item.getConditionalMana();
|
|
||||||
if (c.apply(ability, game, c.getManaProducerId(), null)) {
|
|
||||||
int count = c.count(filter);
|
|
||||||
if (count > 0) {
|
|
||||||
total += count;
|
|
||||||
c.removeAll(filter);
|
|
||||||
if (c.count() == 0) {
|
|
||||||
it.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (filter.isBlack()) {
|
|
||||||
total += item.getBlack();
|
|
||||||
item.removeBlack();
|
|
||||||
}
|
|
||||||
if (filter.isBlue()) {
|
|
||||||
total += item.getBlue();
|
|
||||||
item.removeBlue();
|
|
||||||
}
|
|
||||||
if (filter.isWhite()) {
|
|
||||||
total += item.getWhite();
|
|
||||||
item.removeWhite();
|
|
||||||
}
|
|
||||||
if (filter.isRed()) {
|
|
||||||
total += item.getRed();
|
|
||||||
item.removeRed();
|
|
||||||
}
|
|
||||||
if (filter.isGreen()) {
|
|
||||||
total += item.getGreen();
|
|
||||||
item.removeGreen();
|
|
||||||
}
|
|
||||||
if (filter.isGeneric()) {
|
|
||||||
total += item.getColorless();
|
|
||||||
item.removeColorless();
|
|
||||||
}
|
|
||||||
if (item.count() == 0) {
|
|
||||||
it.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Mana getMana() {
|
public Mana getMana() {
|
||||||
Mana m = new Mana();
|
Mana m = new Mana();
|
||||||
for (ManaPoolItem item : manaItems) {
|
for (ManaPoolItem item : manaItems) {
|
||||||
|
|
@ -376,12 +290,6 @@ public class ManaPool implements Serializable {
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Mana getAllConditionalMana(Ability ability, Game game, FilterMana filter) {
|
|
||||||
Mana m = new Mana();
|
|
||||||
m.setGeneric(getConditionalCount(ability, game, filter, null));
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addMana(Mana manaToAdd, Game game, Ability source) {
|
public void addMana(Mana manaToAdd, Game game, Ability source) {
|
||||||
addMana(manaToAdd, game, source, false);
|
addMana(manaToAdd, game, source, false);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,10 @@ import mage.MageObject;
|
||||||
import mage.Mana;
|
import mage.Mana;
|
||||||
import mage.ManaSymbol;
|
import mage.ManaSymbol;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.mana.AlternateManaPaymentAbility;
|
import mage.abilities.costs.mana.*;
|
||||||
import mage.abilities.costs.mana.ManaCost;
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
import mage.abilities.costs.mana.ManaSymbols;
|
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
|
||||||
|
import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.mana.*;
|
import mage.abilities.mana.*;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.choices.Choice;
|
import mage.choices.Choice;
|
||||||
|
|
@ -494,4 +495,21 @@ public final class ManaUtil {
|
||||||
destColors.setGreen(true);
|
destColors.setGreen(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ManaCost createManaCost(int manaValue) {
|
||||||
|
return new GenericManaCost(manaValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ManaCost createManaCost(DynamicValue manaValue, Game game, Ability sourceAbility, Effect effect) {
|
||||||
|
int costValue = manaValue.calculate(game, sourceAbility, effect);
|
||||||
|
if (manaValue instanceof ManacostVariableValue) {
|
||||||
|
// variable (X must be final value after all events and effects)
|
||||||
|
VariableManaCost xCost = new VariableManaCost();
|
||||||
|
xCost.setAmount(costValue, costValue, false);
|
||||||
|
return xCost;
|
||||||
|
} else {
|
||||||
|
// static/generic
|
||||||
|
return new GenericManaCost(costValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue