mirror of
https://github.com/magefree/mage.git
synced 2026-01-26 21:29:17 -08:00
add PayVariableEnergyCost, fixing [PIP] HELIOS One & [MH3] Chtonian Nightmare
fix #12217
This commit is contained in:
parent
fc6c7b36e5
commit
534d1be175
6 changed files with 59 additions and 83 deletions
|
|
@ -1,14 +1,9 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.ActivateAsSorceryActivatedAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.CostAdjuster;
|
||||
import mage.abilities.costs.Costs;
|
||||
import mage.abilities.costs.CostsImpl;
|
||||
import mage.abilities.costs.common.PayEnergyCost;
|
||||
import mage.abilities.costs.common.PayVariableEnergyCost;
|
||||
import mage.abilities.costs.common.ReturnToHandFromBattlefieldSourceCost;
|
||||
import mage.abilities.costs.common.SacrificeTargetCost;
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
||||
|
|
@ -17,7 +12,6 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.target.targetadjustment.XManaValueTargetAdjuster;
|
||||
|
||||
|
|
@ -38,13 +32,12 @@ public final class ChthonianNightmare extends CardImpl {
|
|||
Ability ability = new ActivateAsSorceryActivatedAbility(
|
||||
new ReturnFromGraveyardToBattlefieldTargetEffect()
|
||||
.setText("Return target creature card with mana value X from your graveyard to the battlefield"),
|
||||
new PayEnergyCost(0).setText("Pay X {E}") // TODO: replace with proper VariableEnergyCost
|
||||
new PayVariableEnergyCost()
|
||||
);
|
||||
ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_CREATURE));
|
||||
ability.addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_CREATURE));
|
||||
ability.addCost(new ReturnToHandFromBattlefieldSourceCost());
|
||||
ability.setTargetAdjuster(new XManaValueTargetAdjuster());
|
||||
ability.setCostAdjuster(ChthonianNightmareCostAdjuster.instance); // TODO: remove
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
@ -56,29 +49,4 @@ public final class ChthonianNightmare extends CardImpl {
|
|||
public ChthonianNightmare copy() {
|
||||
return new ChthonianNightmare(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum ChthonianNightmareCostAdjuster implements CostAdjuster {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public void adjustCosts(Ability ability, Game game) {
|
||||
MageObject target = game.getObject(ability.getFirstTarget());
|
||||
if (target == null) {
|
||||
return;
|
||||
}
|
||||
int mv = target.getManaValue();
|
||||
Costs<Cost> costs = new CostsImpl<>();
|
||||
costs.addAll(ability.getCosts());
|
||||
ability.clearCosts();
|
||||
for (Cost cost : costs) {
|
||||
if (cost instanceof PayEnergyCost) {
|
||||
if (mv > 0) {
|
||||
ability.addCost(new PayEnergyCost(mv));
|
||||
}
|
||||
} else {
|
||||
ability.addCost(cost);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,9 @@
|
|||
package mage.cards.h;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.ActivateAsSorceryActivatedAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.CostAdjuster;
|
||||
import mage.abilities.costs.Costs;
|
||||
import mage.abilities.costs.CostsImpl;
|
||||
import mage.abilities.costs.common.PayEnergyCost;
|
||||
import mage.abilities.costs.common.PayVariableEnergyCost;
|
||||
import mage.abilities.costs.common.SacrificeSourceCost;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
|
|
@ -18,7 +13,6 @@ import mage.abilities.mana.ColorlessManaAbility;
|
|||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.game.Game;
|
||||
import mage.target.common.TargetNonlandPermanent;
|
||||
import mage.target.targetadjustment.XManaValueTargetAdjuster;
|
||||
|
||||
|
|
@ -49,11 +43,10 @@ public final class HELIOSOne extends CardImpl {
|
|||
new GenericManaCost(3)
|
||||
);
|
||||
ability.addCost(new TapSourceCost());
|
||||
ability.addCost(new PayEnergyCost(0).setText("Pay X {E}")); // TODO: replace with proper VariableEnergyCost
|
||||
ability.addCost(new PayVariableEnergyCost());
|
||||
ability.addCost(new SacrificeSourceCost());
|
||||
ability.addTarget(new TargetNonlandPermanent());
|
||||
ability.setTargetAdjuster(new XManaValueTargetAdjuster());
|
||||
ability.setCostAdjuster(HELIOSOneCostAdjuster.instance); // TODO: remove
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
@ -65,29 +58,4 @@ public final class HELIOSOne extends CardImpl {
|
|||
public HELIOSOne copy() {
|
||||
return new HELIOSOne(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum HELIOSOneCostAdjuster implements CostAdjuster {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public void adjustCosts(Ability ability, Game game) {
|
||||
MageObject target = game.getObject(ability.getFirstTarget());
|
||||
if (target == null) {
|
||||
return;
|
||||
}
|
||||
int mv = target.getManaValue();
|
||||
Costs<Cost> costs = new CostsImpl<>();
|
||||
costs.addAll(ability.getCosts());
|
||||
ability.clearCosts();
|
||||
for (Cost cost : costs) {
|
||||
if (cost instanceof PayEnergyCost) {
|
||||
if (mv > 0) {
|
||||
ability.addCost(new PayEnergyCost(mv));
|
||||
}
|
||||
} else {
|
||||
ability.addCost(cost);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -142,7 +142,7 @@ public final class Fallout extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Grave Titan", 346, Rarity.MYTHIC, mage.cards.g.GraveTitan.class));
|
||||
cards.add(new SetCardInfo("Guardian Project", 199, Rarity.RARE, mage.cards.g.GuardianProject.class));
|
||||
cards.add(new SetCardInfo("Gunner Conscript", 77, Rarity.UNCOMMON, mage.cards.g.GunnerConscript.class));
|
||||
// cards.add(new SetCardInfo("HELIOS One", 149, Rarity.RARE, mage.cards.h.HELIOSOne.class)); //TODO: re-add when pay X energy is fixed.
|
||||
cards.add(new SetCardInfo("HELIOS One", 149, Rarity.RARE, mage.cards.h.HELIOSOne.class));
|
||||
cards.add(new SetCardInfo("Hancock, Ghoulish Mayor", 45, Rarity.RARE, mage.cards.h.HancockGhoulishMayor.class));
|
||||
cards.add(new SetCardInfo("Hardened Scales", 200, Rarity.RARE, mage.cards.h.HardenedScales.class));
|
||||
cards.add(new SetCardInfo("Harmonize", 201, Rarity.UNCOMMON, mage.cards.h.Harmonize.class));
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ public final class ModernHorizons3 extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Ajani, Nacatl Avenger", 237, Rarity.MYTHIC, mage.cards.a.AjaniNacatlAvenger.class));
|
||||
cards.add(new SetCardInfo("Ajani, Nacatl Pariah", 237, Rarity.MYTHIC, mage.cards.a.AjaniNacatlPariah.class));
|
||||
cards.add(new SetCardInfo("Bloodstained Mire", 216, Rarity.RARE, mage.cards.b.BloodstainedMire.class));
|
||||
// cards.add(new SetCardInfo("Chthonian Nightmare", 83, Rarity.RARE, mage.cards.c.ChthonianNightmare.class)); //TODO: re-add when pay X energy is fixed.
|
||||
cards.add(new SetCardInfo("Chthonian Nightmare", 83, Rarity.RARE, mage.cards.c.ChthonianNightmare.class));
|
||||
cards.add(new SetCardInfo("Emrakul, the World Anew", 6, Rarity.MYTHIC, mage.cards.e.EmrakulTheWorldAnew.class));
|
||||
cards.add(new SetCardInfo("Flare of Cultivation", 154, Rarity.RARE, mage.cards.f.FlareOfCultivation.class));
|
||||
cards.add(new SetCardInfo("Flare of Denial", 62, Rarity.RARE, mage.cards.f.FlareOfDenial.class));
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import mage.constants.PhaseStep;
|
|||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
|
|
@ -22,7 +21,6 @@ public class HELIOSOneTest extends CardTestPlayerBase {
|
|||
*/
|
||||
private static final String helios = "HELIOS One";
|
||||
|
||||
@Ignore // needs fix
|
||||
@Test
|
||||
public void test_Target_0MV_0Energy() {
|
||||
setStrictChooseMode(true);
|
||||
|
|
@ -31,6 +29,7 @@ public class HELIOSOneTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite");
|
||||
|
||||
setChoice(playerA, "X=0");
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{3}");
|
||||
addTarget(playerA, "Memnite");
|
||||
|
||||
|
|
@ -43,7 +42,6 @@ public class HELIOSOneTest extends CardTestPlayerBase {
|
|||
assertCounterCount(playerA, CounterType.ENERGY, 0);
|
||||
}
|
||||
|
||||
@Ignore // needs fix
|
||||
@Test
|
||||
public void test_NoTarget_1MV_0Energy() {
|
||||
setStrictChooseMode(true);
|
||||
|
|
@ -52,9 +50,12 @@ public class HELIOSOneTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard");
|
||||
|
||||
// TODO: So the test suite let's you activate the ability (as it does not go to adjust targets to check them.)
|
||||
// But X=0 is not a valid choice once targets are checked (no nonland card with that MV in play).
|
||||
setChoice(playerA, "X=0");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{3}");
|
||||
addTarget(playerA, "Elite Vanguard");
|
||||
addTarget(playerA, "Elite Vanguard"); // not a valid target for X=0 energy payment
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
|
||||
|
|
@ -62,11 +63,13 @@ public class HELIOSOneTest extends CardTestPlayerBase {
|
|||
execute();
|
||||
Assert.fail("Should not be possible to activate the {3} ability without energy and without a 0 mana target");
|
||||
} catch (AssertionError e) {
|
||||
Assert.assertEquals("Can't find ability to activate command: {3}", e.getMessage());
|
||||
Assert.assertTrue(
|
||||
"X=0 is not a valid choice. Error message:\n" + e.getMessage(),
|
||||
e.getMessage().contains("Message: Announce the number of {E} to pay")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Ignore // needs fix
|
||||
@Test
|
||||
public void test_Target_1MV_1Energy() {
|
||||
setStrictChooseMode(true);
|
||||
|
|
@ -75,14 +78,13 @@ public class HELIOSOneTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard");
|
||||
|
||||
// TODO: for some reason the test suite does think the ability is playable, although it is not
|
||||
// after target adjusting + cost adjusting for the target
|
||||
// see above test for the try/catch version that fails on execute.
|
||||
//checkPlayableAbility("can't activate due to lack of energy", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "{3}", false);
|
||||
// TODO: investigate why the checkPlayableAbility doesn't go
|
||||
checkPlayableAbility("can't activate due to lack of energy", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "{3}", true); // should be false.
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {W}");
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
checkPlayableAbility("can activate with energy", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "{3}", true);
|
||||
setChoice(playerA, "X=1");
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{3}");
|
||||
addTarget(playerA, "Elite Vanguard");
|
||||
|
||||
|
|
@ -95,7 +97,6 @@ public class HELIOSOneTest extends CardTestPlayerBase {
|
|||
assertCounterCount(playerA, CounterType.ENERGY, 0);
|
||||
}
|
||||
|
||||
@Ignore // needs fix
|
||||
@Test
|
||||
public void test_Target_0MV_1Energy() {
|
||||
setStrictChooseMode(true);
|
||||
|
|
@ -107,6 +108,7 @@ public class HELIOSOneTest extends CardTestPlayerBase {
|
|||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {W}");
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||
setChoice(playerA, "X=0");
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{3}");
|
||||
addTarget(playerA, "Memnite");
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
package mage.abilities.costs.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.VariableCostImpl;
|
||||
import mage.abilities.costs.VariableCostType;
|
||||
import mage.abilities.dynamicvalue.common.SourceControllerCountersCount;
|
||||
import mage.game.Game;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public class PayVariableEnergyCost extends VariableCostImpl {
|
||||
|
||||
public PayVariableEnergyCost() {
|
||||
super(VariableCostType.NORMAL, "{E} to pay");
|
||||
this.text = "Pay " + xText + " {E}";
|
||||
}
|
||||
|
||||
protected PayVariableEnergyCost(final PayVariableEnergyCost cost) {
|
||||
super(cost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayVariableEnergyCost copy() {
|
||||
return new PayVariableEnergyCost(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cost getFixedCostsFromAnnouncedValue(int xValue) {
|
||||
return new PayEnergyCost(xValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxValue(Ability source, Game game) {
|
||||
return SourceControllerCountersCount.ENERGY.calculate(game, source, null);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue