mirror of
https://github.com/correl/mage.git
synced 2024-11-28 19:19:55 +00:00
* Additional costs - added support of X costs on free cast (example: Kicker X, see Thieving Skydiver and Etali, Primal Storm combo);
* As an additional cost discard X cards - fixed wrong text (example: Channeled Force, Firestorm);
This commit is contained in:
parent
d62cf17422
commit
53aababd44
65 changed files with 483 additions and 417 deletions
|
@ -1,12 +1,12 @@
|
||||||
package mage.cards.a;
|
package mage.cards.a;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.VariableCost;
|
import mage.abilities.costs.VariableCost;
|
||||||
import mage.abilities.costs.VariableCostImpl;
|
import mage.abilities.costs.VariableCostImpl;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.abilities.costs.common.TapSourceCost;
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
import mage.abilities.costs.common.TapTargetCost;
|
import mage.abilities.costs.common.TapTargetCost;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
@ -15,11 +15,7 @@ import mage.abilities.effects.common.DestroyTargetEffect;
|
||||||
import mage.abilities.keyword.VigilanceAbility;
|
import mage.abilities.keyword.VigilanceAbility;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.*;
|
||||||
import mage.constants.ComparisonType;
|
|
||||||
import mage.constants.SubType;
|
|
||||||
import mage.constants.SuperType;
|
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
import mage.filter.predicate.mageobject.PowerPredicate;
|
import mage.filter.predicate.mageobject.PowerPredicate;
|
||||||
|
@ -30,8 +26,9 @@ import mage.target.common.TargetControlledPermanent;
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
import mage.target.targetadjustment.TargetAdjuster;
|
import mage.target.targetadjustment.TargetAdjuster;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author jack-the-BOSS
|
* @author jack-the-BOSS
|
||||||
*/
|
*/
|
||||||
public final class AryelKnightOfWindgrace extends CardImpl {
|
public final class AryelKnightOfWindgrace extends CardImpl {
|
||||||
|
@ -83,7 +80,7 @@ class AryelTapXTargetCost extends VariableCostImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public AryelTapXTargetCost() {
|
public AryelTapXTargetCost() {
|
||||||
super("controlled untapped Knights you would like to tap");
|
super(VariableCostType.NORMAL, "controlled untapped Knights you would like to tap");
|
||||||
this.text = "Tap X untapped Knights you control";
|
this.text = "Tap X untapped Knights you control";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
|
|
||||||
package mage.cards.b;
|
package mage.cards.b;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.ObjectColor;
|
import mage.ObjectColor;
|
||||||
import mage.abilities.costs.AlternativeCostSourceAbility;
|
import mage.abilities.costs.AlternativeCostSourceAbility;
|
||||||
import mage.abilities.costs.common.ExileFromHandCost;
|
import mage.abilities.costs.common.ExileFromHandCost;
|
||||||
|
@ -20,14 +18,15 @@ import mage.filter.predicate.mageobject.ColorPredicate;
|
||||||
import mage.target.common.TargetCardInHand;
|
import mage.target.common.TargetCardInHand;
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
*/
|
*/
|
||||||
public final class BlazingShoal extends CardImpl {
|
public final class BlazingShoal extends CardImpl {
|
||||||
|
|
||||||
public BlazingShoal(UUID ownerId, CardSetInfo setInfo) {
|
public BlazingShoal(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{R}{R}");
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{R}{R}");
|
||||||
this.subtype.add(SubType.ARCANE);
|
this.subtype.add(SubType.ARCANE);
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,7 +34,7 @@ public final class BlazingShoal extends CardImpl {
|
||||||
FilterOwnedCard filter = new FilterOwnedCard("a red card with mana value X from your hand");
|
FilterOwnedCard filter = new FilterOwnedCard("a red card with mana value X from your hand");
|
||||||
filter.add(new ColorPredicate(ObjectColor.RED));
|
filter.add(new ColorPredicate(ObjectColor.RED));
|
||||||
filter.add(Predicates.not(new CardIdPredicate(this.getId()))); // the exile cost can never be paid with the card itself
|
filter.add(Predicates.not(new CardIdPredicate(this.getId()))); // the exile cost can never be paid with the card itself
|
||||||
this.addAbility(new AlternativeCostSourceAbility(new ExileFromHandCost(new TargetCardInHand(filter),true)));
|
this.addAbility(new AlternativeCostSourceAbility(new ExileFromHandCost(new TargetCardInHand(filter), true)));
|
||||||
|
|
||||||
// Target creature gets +X/+0 until end of turn.
|
// Target creature gets +X/+0 until end of turn.
|
||||||
this.getSpellAbility().addEffect(new BoostTargetEffect(ExileFromHandCostCardConvertedMana.instance, StaticValue.get(0), Duration.EndOfTurn));
|
this.getSpellAbility().addEffect(new BoostTargetEffect(ExileFromHandCostCardConvertedMana.instance, StaticValue.get(0), Duration.EndOfTurn));
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package mage.cards.c;
|
package mage.cards.c;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.EntersBattlefieldAbility;
|
import mage.abilities.common.EntersBattlefieldAbility;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.VariableCostImpl;
|
import mage.abilities.costs.VariableCostImpl;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.abilities.costs.common.RemoveCountersSourceCost;
|
import mage.abilities.costs.common.RemoveCountersSourceCost;
|
||||||
import mage.abilities.costs.common.TapSourceCost;
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
@ -26,8 +26,9 @@ import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.target.common.TargetAnyTarget;
|
import mage.target.common.TargetAnyTarget;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author jmharmon
|
* @author jmharmon
|
||||||
*/
|
*/
|
||||||
public final class ChamberSentry extends CardImpl {
|
public final class ChamberSentry extends CardImpl {
|
||||||
|
@ -69,7 +70,7 @@ public final class ChamberSentry extends CardImpl {
|
||||||
class ChamberSentryRemoveVariableCountersSourceCost extends VariableCostImpl {
|
class ChamberSentryRemoveVariableCountersSourceCost extends VariableCostImpl {
|
||||||
|
|
||||||
protected int minimalCountersToPay = 0;
|
protected int minimalCountersToPay = 0;
|
||||||
private String counterName;
|
private final String counterName;
|
||||||
|
|
||||||
public ChamberSentryRemoveVariableCountersSourceCost(Counter counter) {
|
public ChamberSentryRemoveVariableCountersSourceCost(Counter counter) {
|
||||||
this(counter, 0);
|
this(counter, 0);
|
||||||
|
@ -84,7 +85,7 @@ class ChamberSentryRemoveVariableCountersSourceCost extends VariableCostImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChamberSentryRemoveVariableCountersSourceCost(Counter counter, int minimalCountersToPay, String text) {
|
public ChamberSentryRemoveVariableCountersSourceCost(Counter counter, int minimalCountersToPay, String text) {
|
||||||
super(counter.getName() + " counters to remove");
|
super(VariableCostType.NORMAL, counter.getName() + " counters to remove");
|
||||||
this.minimalCountersToPay = minimalCountersToPay;
|
this.minimalCountersToPay = minimalCountersToPay;
|
||||||
this.counterName = counter.getName();
|
this.counterName = counter.getName();
|
||||||
if (text == null || text.isEmpty()) {
|
if (text == null || text.isEmpty()) {
|
||||||
|
|
|
@ -25,7 +25,7 @@ public final class ChanneledForce extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}{R}");
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}{R}");
|
||||||
|
|
||||||
// As an additional cost to cast this spell, discard X cards.
|
// As an additional cost to cast this spell, discard X cards.
|
||||||
this.getSpellAbility().addCost(new DiscardXTargetCost(StaticFilters.FILTER_CARD_CARDS, false));
|
this.getSpellAbility().addCost(new DiscardXTargetCost(StaticFilters.FILTER_CARD_CARDS, true));
|
||||||
|
|
||||||
// Target player draws X cards. Channeled Force deals X damage to up to one target creature or planeswalker.
|
// Target player draws X cards. Channeled Force deals X damage to up to one target creature or planeswalker.
|
||||||
this.getSpellAbility().addEffect(new ChanneledForceEffect());
|
this.getSpellAbility().addEffect(new ChanneledForceEffect());
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
|
|
||||||
package mage.cards.c;
|
package mage.cards.c;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
@ -18,8 +16,9 @@ import mage.constants.Zone;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
import mage.filter.common.FilterControlledLandPermanent;
|
import mage.filter.common.FilterControlledLandPermanent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author Rene - bugisemail at gmail.com
|
* @author Rene - bugisemail at gmail.com
|
||||||
*/
|
*/
|
||||||
public final class CopperLeafAngel extends CardImpl {
|
public final class CopperLeafAngel extends CardImpl {
|
||||||
|
@ -35,8 +34,8 @@ public final class CopperLeafAngel extends CardImpl {
|
||||||
this.addAbility(FlyingAbility.getInstance());
|
this.addAbility(FlyingAbility.getInstance());
|
||||||
|
|
||||||
// {tap}, Sacrifice X lands: Put X +1/+1 counters on Copper-Leaf Angel.
|
// {tap}, Sacrifice X lands: Put X +1/+1 counters on Copper-Leaf Angel.
|
||||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance(),GetXValue.instance, false), new TapSourceCost());
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance(), GetXValue.instance, false), new TapSourceCost());
|
||||||
ability.addCost(new SacrificeXTargetCost(new FilterControlledLandPermanent("lands"), false));
|
ability.addCost(new SacrificeXTargetCost(new FilterControlledLandPermanent("lands")));
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ 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.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
import mage.util.ManaUtil;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ -79,7 +80,7 @@ class CrystalShardEffect extends OneShotEffect {
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Cost cost = new GenericManaCost(1);
|
Cost cost = ManaUtil.createManaCost(1, false);
|
||||||
String message = "Pay {1}? (Otherwise " + targetCreature.getName() + " will be returned to its owner's hand)";
|
String message = "Pay {1}? (Otherwise " + targetCreature.getName() + " will be returned to its owner's hand)";
|
||||||
if (player.chooseUse(Outcome.Benefit, message, source, game)) {
|
if (player.chooseUse(Outcome.Benefit, message, source, game)) {
|
||||||
cost.pay(source, game, source, targetCreature.getControllerId(), false, null);
|
cost.pay(source, game, source, targetCreature.getControllerId(), false, null);
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
|
|
||||||
package mage.cards.d;
|
package mage.cards.d;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.VariableCostImpl;
|
import mage.abilities.costs.VariableCostImpl;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.abilities.costs.common.DiscardTargetCost;
|
import mage.abilities.costs.common.DiscardTargetCost;
|
||||||
import mage.abilities.dynamicvalue.common.GetXValue;
|
import mage.abilities.dynamicvalue.common.GetXValue;
|
||||||
import mage.abilities.effects.common.DamageAllEffect;
|
import mage.abilities.effects.common.DamageAllEffect;
|
||||||
|
@ -19,14 +18,15 @@ import mage.game.Game;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.common.TargetCardInHand;
|
import mage.target.common.TargetCardInHand;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author emerald000
|
* @author emerald000
|
||||||
*/
|
*/
|
||||||
public final class DevastatingDreams extends CardImpl {
|
public final class DevastatingDreams extends CardImpl {
|
||||||
|
|
||||||
public DevastatingDreams(UUID ownerId, CardSetInfo setInfo) {
|
public DevastatingDreams(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{R}{R}");
|
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{R}{R}");
|
||||||
|
|
||||||
// As an additional cost to cast Devastating Dreams, discard X cards at random.
|
// As an additional cost to cast Devastating Dreams, discard X cards at random.
|
||||||
this.getSpellAbility().addCost(new DevastatingDreamsAdditionalCost());
|
this.getSpellAbility().addCost(new DevastatingDreamsAdditionalCost());
|
||||||
|
@ -51,7 +51,7 @@ public final class DevastatingDreams extends CardImpl {
|
||||||
class DevastatingDreamsAdditionalCost extends VariableCostImpl {
|
class DevastatingDreamsAdditionalCost extends VariableCostImpl {
|
||||||
|
|
||||||
DevastatingDreamsAdditionalCost() {
|
DevastatingDreamsAdditionalCost() {
|
||||||
super("cards to discard randomly");
|
super(VariableCostType.ADDITIONAL, "cards to discard randomly");
|
||||||
this.text = "as an additional cost to cast this spell, discard X cards at random";
|
this.text = "as an additional cost to cast this spell, discard X cards at random";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import mage.abilities.Ability;
|
||||||
import mage.abilities.common.ActivateIfConditionActivatedAbility;
|
import mage.abilities.common.ActivateIfConditionActivatedAbility;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.condition.common.MyTurnCondition;
|
import mage.abilities.condition.common.MyTurnCondition;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.abilities.costs.common.TapSourceCost;
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
import mage.abilities.costs.mana.GenericManaCost;
|
import mage.abilities.costs.mana.GenericManaCost;
|
||||||
import mage.abilities.costs.mana.VariableManaCost;
|
import mage.abilities.costs.mana.VariableManaCost;
|
||||||
|
@ -47,7 +48,7 @@ public final class EverythingamajigC extends CardImpl {
|
||||||
|
|
||||||
// Chimeric Staff
|
// Chimeric Staff
|
||||||
// X: Everythingamajig becomes an X/X Construct artifact creature until end of turn.
|
// X: Everythingamajig becomes an X/X Construct artifact creature until end of turn.
|
||||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ChimericStaffEffect(), new VariableManaCost()));
|
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ChimericStaffEffect(), new VariableManaCost(VariableCostType.NORMAL)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private EverythingamajigC(final EverythingamajigC card) {
|
private EverythingamajigC(final EverythingamajigC card) {
|
||||||
|
|
|
@ -63,7 +63,7 @@ public final class ExtusOriqOverlord extends ModalDoubleFacesCard {
|
||||||
// Awaken the Blood Avatar
|
// Awaken the Blood Avatar
|
||||||
// Sorcery
|
// Sorcery
|
||||||
// As an additional cost to cast this spell, you may sacrifice any number of creatures. This spell costs {2} less to cast for each creature sacrificed this way.
|
// As an additional cost to cast this spell, you may sacrifice any number of creatures. This spell costs {2} less to cast for each creature sacrificed this way.
|
||||||
Cost cost = new SacrificeXTargetCost(StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT);
|
Cost cost = new SacrificeXTargetCost(StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT, true);
|
||||||
cost.setText("As an additional cost to cast this spell, you may sacrifice any number of creatures. " +
|
cost.setText("As an additional cost to cast this spell, you may sacrifice any number of creatures. " +
|
||||||
"This spell costs {2} less to cast for each creature sacrificed this way");
|
"This spell costs {2} less to cast for each creature sacrificed this way");
|
||||||
this.getRightHalfCard().getSpellAbility().addCost(cost);
|
this.getRightHalfCard().getSpellAbility().addCost(cost);
|
||||||
|
|
|
@ -27,7 +27,7 @@ public final class Firestorm extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}");
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}");
|
||||||
|
|
||||||
// As an additional cost to cast Firestorm, discard X cards.
|
// As an additional cost to cast Firestorm, discard X cards.
|
||||||
this.getSpellAbility().addCost(new DiscardXTargetCost(new FilterCard("cards"), false));
|
this.getSpellAbility().addCost(new DiscardXTargetCost(new FilterCard("cards"), true));
|
||||||
|
|
||||||
// Firestorm deals X damage to each of X target creatures and/or players.
|
// Firestorm deals X damage to each of X target creatures and/or players.
|
||||||
this.getSpellAbility().addEffect(new FirestormEffect());
|
this.getSpellAbility().addEffect(new FirestormEffect());
|
||||||
|
|
|
@ -5,6 +5,7 @@ import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.VariableCostImpl;
|
import mage.abilities.costs.VariableCostImpl;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.abilities.costs.common.TapSourceCost;
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
import mage.abilities.costs.common.TapTargetCost;
|
import mage.abilities.costs.common.TapTargetCost;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
@ -114,7 +115,7 @@ class GlacianPowerstoneEngineerCost extends VariableCostImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
GlacianPowerstoneEngineerCost() {
|
GlacianPowerstoneEngineerCost() {
|
||||||
super("controlled untapped artifacts you would like to tap");
|
super(VariableCostType.NORMAL, "controlled untapped artifacts you would like to tap");
|
||||||
this.text = "Tap X untapped artifacts you control";
|
this.text = "Tap X untapped artifacts you control";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package mage.cards.h;
|
package mage.cards.h;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.abilities.costs.common.ExileXFromYourGraveCost;
|
import mage.abilities.costs.common.ExileXFromYourGraveCost;
|
||||||
import mage.abilities.dynamicvalue.common.GetXValue;
|
import mage.abilities.dynamicvalue.common.GetXValue;
|
||||||
import mage.abilities.effects.common.DamageTargetEffect;
|
import mage.abilities.effects.common.DamageTargetEffect;
|
||||||
|
@ -10,8 +9,9 @@ import mage.constants.CardType;
|
||||||
import mage.filter.StaticFilters;
|
import mage.filter.StaticFilters;
|
||||||
import mage.target.common.TargetPlayerOrPlaneswalker;
|
import mage.target.common.TargetPlayerOrPlaneswalker;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author markedagain
|
* @author markedagain
|
||||||
*/
|
*/
|
||||||
public final class HauntingMisery extends CardImpl {
|
public final class HauntingMisery extends CardImpl {
|
||||||
|
@ -21,6 +21,7 @@ public final class HauntingMisery extends CardImpl {
|
||||||
|
|
||||||
// As an additional cost to cast Haunting Misery, exile X creature cards from your graveyard.
|
// As an additional cost to cast Haunting Misery, exile X creature cards from your graveyard.
|
||||||
this.getSpellAbility().addCost(new ExileXFromYourGraveCost(StaticFilters.FILTER_CARD_CREATURE));
|
this.getSpellAbility().addCost(new ExileXFromYourGraveCost(StaticFilters.FILTER_CARD_CREATURE));
|
||||||
|
|
||||||
// Haunting Misery deals X damage to target player.
|
// Haunting Misery deals X damage to target player.
|
||||||
this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker());
|
this.getSpellAbility().addTarget(new TargetPlayerOrPlaneswalker());
|
||||||
this.getSpellAbility().addEffect(new DamageTargetEffect(GetXValue.instance));
|
this.getSpellAbility().addEffect(new DamageTargetEffect(GetXValue.instance));
|
||||||
|
|
|
@ -2,6 +2,7 @@ package mage.cards.h;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.abilities.costs.common.TapSourceCost;
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
import mage.abilities.costs.mana.VariableManaCost;
|
import mage.abilities.costs.mana.VariableManaCost;
|
||||||
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
|
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
|
||||||
|
@ -28,7 +29,7 @@ public final class HelmOfObedience extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
|
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
|
||||||
|
|
||||||
// {X}, {T}: Target opponent puts cards from the top of their library into their graveyard until a creature card or X cards are put into that graveyard this way, whichever comes first. If a creature card is put into that graveyard this way, sacrifice Helm of Obedience and put that card onto the battlefield under your control. X can't be 0.
|
// {X}, {T}: Target opponent puts cards from the top of their library into their graveyard until a creature card or X cards are put into that graveyard this way, whichever comes first. If a creature card is put into that graveyard this way, sacrifice Helm of Obedience and put that card onto the battlefield under your control. X can't be 0.
|
||||||
VariableManaCost xCosts = new VariableManaCost();
|
VariableManaCost xCosts = new VariableManaCost(VariableCostType.NORMAL);
|
||||||
xCosts.setMinX(1);
|
xCosts.setMinX(1);
|
||||||
Ability ability = new SimpleActivatedAbility(new HelmOfObedienceEffect(), xCosts);
|
Ability ability = new SimpleActivatedAbility(new HelmOfObedienceEffect(), xCosts);
|
||||||
ability.addCost(new TapSourceCost());
|
ability.addCost(new TapSourceCost());
|
||||||
|
|
|
@ -4,6 +4,7 @@ import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.CostImpl;
|
import mage.abilities.costs.CostImpl;
|
||||||
import mage.abilities.costs.VariableCostImpl;
|
import mage.abilities.costs.VariableCostImpl;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.abilities.dynamicvalue.common.GetXValue;
|
import mage.abilities.dynamicvalue.common.GetXValue;
|
||||||
import mage.abilities.effects.common.DamageMultiEffect;
|
import mage.abilities.effects.common.DamageMultiEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
|
@ -33,7 +34,7 @@ public final class InfernalHarvest extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}");
|
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}");
|
||||||
|
|
||||||
// As an additional cost to cast Infernal Harvest, return X Swamps you control to their owner's hand.
|
// As an additional cost to cast Infernal Harvest, return X Swamps you control to their owner's hand.
|
||||||
this.getSpellAbility().addCost(new InfernalHarvestVariableCost());
|
this.getSpellAbility().addCost(new InfernalHarvestAdditionalCost());
|
||||||
|
|
||||||
// Infernal Harvest deals X damage divided as you choose among any number of target creatures.
|
// Infernal Harvest deals X damage divided as you choose among any number of target creatures.
|
||||||
this.getSpellAbility().addEffect(new DamageMultiEffect(GetXValue.instance));
|
this.getSpellAbility().addEffect(new DamageMultiEffect(GetXValue.instance));
|
||||||
|
@ -50,22 +51,22 @@ public final class InfernalHarvest extends CardImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class InfernalHarvestVariableCost extends VariableCostImpl {
|
class InfernalHarvestAdditionalCost extends VariableCostImpl {
|
||||||
|
|
||||||
private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.SWAMP);
|
private static final FilterControlledPermanent filter = new FilterControlledPermanent(SubType.SWAMP);
|
||||||
|
|
||||||
InfernalHarvestVariableCost() {
|
InfernalHarvestAdditionalCost() {
|
||||||
super("Swamps to return");
|
super(VariableCostType.ADDITIONAL, "Swamps to return");
|
||||||
this.text = "return " + xText + " Swamps you control to their owner's hand";
|
this.text = "return " + xText + " Swamps you control to their owner's hand";
|
||||||
}
|
}
|
||||||
|
|
||||||
private InfernalHarvestVariableCost(final InfernalHarvestVariableCost cost) {
|
private InfernalHarvestAdditionalCost(final InfernalHarvestAdditionalCost cost) {
|
||||||
super(cost);
|
super(cost);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InfernalHarvestVariableCost copy() {
|
public InfernalHarvestAdditionalCost copy() {
|
||||||
return new InfernalHarvestVariableCost(this);
|
return new InfernalHarvestAdditionalCost(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,19 +1,11 @@
|
||||||
|
|
||||||
package mage.cards.i;
|
package mage.cards.i;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.common.DiscardXTargetCost;
|
||||||
import mage.abilities.costs.VariableCostImpl;
|
|
||||||
import mage.abilities.costs.common.DiscardTargetCost;
|
|
||||||
import mage.abilities.dynamicvalue.common.GetXValue;
|
import mage.abilities.dynamicvalue.common.GetXValue;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.cards.Card;
|
import mage.cards.*;
|
||||||
import mage.cards.CardImpl;
|
|
||||||
import mage.cards.CardSetInfo;
|
|
||||||
import mage.cards.Cards;
|
|
||||||
import mage.cards.CardsImpl;
|
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
|
@ -21,20 +13,20 @@ import mage.filter.FilterCard;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.TargetCard;
|
import mage.target.TargetCard;
|
||||||
import mage.target.common.TargetCardInHand;
|
|
||||||
import mage.target.common.TargetCardInLibrary;
|
import mage.target.common.TargetCardInLibrary;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author spjspj
|
* @author spjspj
|
||||||
*/
|
*/
|
||||||
public final class InsidiousDreams extends CardImpl {
|
public final class InsidiousDreams extends CardImpl {
|
||||||
|
|
||||||
public InsidiousDreams(UUID ownerId, CardSetInfo setInfo) {
|
public InsidiousDreams(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{B}");
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{B}");
|
||||||
|
|
||||||
// As an additional cost to cast Insidious Dreams, discard X cards.
|
// As an additional cost to cast Insidious Dreams, discard X cards.
|
||||||
this.getSpellAbility().addCost(new InsidiousDreamsAdditionalCost());
|
this.getSpellAbility().addCost(new DiscardXTargetCost(new FilterCard("cards"), true));
|
||||||
|
|
||||||
// Search your library for X cards. Then shuffle your library and put those cards on top of it in any order.
|
// Search your library for X cards. Then shuffle your library and put those cards on top of it in any order.
|
||||||
this.getSpellAbility().addEffect(new InsidiousDreamsEffect());
|
this.getSpellAbility().addEffect(new InsidiousDreamsEffect());
|
||||||
|
@ -108,35 +100,3 @@ class InsidiousDreamsEffect extends OneShotEffect {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class InsidiousDreamsAdditionalCost extends VariableCostImpl {
|
|
||||||
|
|
||||||
InsidiousDreamsAdditionalCost() {
|
|
||||||
super("cards to discard");
|
|
||||||
this.text = "discard X cards";
|
|
||||||
}
|
|
||||||
|
|
||||||
InsidiousDreamsAdditionalCost(final InsidiousDreamsAdditionalCost cost) {
|
|
||||||
super(cost);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InsidiousDreamsAdditionalCost copy() {
|
|
||||||
return new InsidiousDreamsAdditionalCost(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMaxValue(Ability source, Game game) {
|
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
|
||||||
if (controller != null) {
|
|
||||||
return controller.getHand().size();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Cost getFixedCostsFromAnnouncedValue(int xValue) {
|
|
||||||
TargetCardInHand target = new TargetCardInHand(xValue, new FilterCard());
|
|
||||||
return new DiscardTargetCost(target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package mage.cards.l;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.VariableCostImpl;
|
import mage.abilities.costs.VariableCostImpl;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.abilities.dynamicvalue.DynamicValue;
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
import mage.abilities.dynamicvalue.common.GetXValue;
|
import mage.abilities.dynamicvalue.common.GetXValue;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
|
@ -27,7 +28,7 @@ public final class LiquidFire extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{R}{R}");
|
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{R}{R}");
|
||||||
|
|
||||||
// As an additional cost to cast Liquid Fire, choose a number between 0 and 5.
|
// As an additional cost to cast Liquid Fire, choose a number between 0 and 5.
|
||||||
this.getSpellAbility().addCost(new LiquidFireCost());
|
this.getSpellAbility().addCost(new LiquidFireAdditionalCost());
|
||||||
// Liquid Fire deals X damage to target creature and 5 minus X damage to that creature's controller, where X is the chosen number.
|
// Liquid Fire deals X damage to target creature and 5 minus X damage to that creature's controller, where X is the chosen number.
|
||||||
DynamicValue choiceValue = GetXValue.instance;
|
DynamicValue choiceValue = GetXValue.instance;
|
||||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
||||||
|
@ -79,30 +80,31 @@ public final class LiquidFire extends CardImpl {
|
||||||
return new LiquidFireEffect(this);
|
return new LiquidFireEffect(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static class LiquidFireCost extends VariableCostImpl {
|
class LiquidFireAdditionalCost extends VariableCostImpl {
|
||||||
public LiquidFireCost() {
|
|
||||||
super("Choose a Number");
|
|
||||||
this.text = "as an additional cost to cast this spell, choose a number between 0 and 5";
|
|
||||||
}
|
|
||||||
|
|
||||||
public LiquidFireCost(final LiquidFireCost cost) {
|
public LiquidFireAdditionalCost() {
|
||||||
super(cost);
|
super(VariableCostType.ADDITIONAL, "Choose a Number");
|
||||||
}
|
this.text = "as an additional cost to cast this spell, choose a number between 0 and 5";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
public LiquidFireAdditionalCost(final LiquidFireAdditionalCost cost) {
|
||||||
public Cost copy() {
|
super(cost);
|
||||||
return new LiquidFireCost(this);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Cost getFixedCostsFromAnnouncedValue(int xValue) {
|
public Cost copy() {
|
||||||
return null;
|
return new LiquidFireAdditionalCost(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMaxValue(Ability source, Game game) {
|
public Cost getFixedCostsFromAnnouncedValue(int xValue) {
|
||||||
return 5;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxValue(Ability source, Game game) {
|
||||||
|
return 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,6 +7,7 @@ import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.VariableCost;
|
import mage.abilities.costs.VariableCost;
|
||||||
import mage.abilities.costs.VariableCostImpl;
|
import mage.abilities.costs.VariableCostImpl;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.abilities.costs.common.RevealTargetFromHandCost;
|
import mage.abilities.costs.common.RevealTargetFromHandCost;
|
||||||
import mage.abilities.costs.common.SacrificeSourceCost;
|
import mage.abilities.costs.common.SacrificeSourceCost;
|
||||||
import mage.abilities.costs.mana.GenericManaCost;
|
import mage.abilities.costs.mana.GenericManaCost;
|
||||||
|
@ -84,7 +85,7 @@ class RevealVariableBlackCardsFromHandCost extends VariableCostImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
RevealVariableBlackCardsFromHandCost() {
|
RevealVariableBlackCardsFromHandCost() {
|
||||||
super("black cards to reveal");
|
super(VariableCostType.NORMAL, "black cards to reveal");
|
||||||
this.text = "Reveal " + xText + " black cards from {this}";
|
this.text = "Reveal " + xText + " black cards from {this}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,20 @@
|
||||||
|
|
||||||
package mage.cards.m;
|
package mage.cards.m;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.VariableCostImpl;
|
import mage.abilities.costs.VariableCostImpl;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.abilities.costs.common.TapSourceCost;
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
import mage.abilities.costs.common.TapTargetCost;
|
import mage.abilities.costs.common.TapTargetCost;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.cards.Card;
|
import mage.cards.*;
|
||||||
import mage.cards.CardImpl;
|
|
||||||
import mage.cards.CardSetInfo;
|
|
||||||
import mage.cards.Cards;
|
|
||||||
import mage.cards.CardsImpl;
|
|
||||||
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.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.filter.FilterCard;
|
import mage.filter.FilterCard;
|
||||||
import mage.filter.common.FilterControlledArtifactPermanent;
|
import mage.filter.common.FilterControlledArtifactPermanent;
|
||||||
|
@ -29,8 +24,9 @@ import mage.players.Player;
|
||||||
import mage.target.TargetCard;
|
import mage.target.TargetCard;
|
||||||
import mage.target.common.TargetControlledPermanent;
|
import mage.target.common.TargetControlledPermanent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
*/
|
*/
|
||||||
public final class MerchantsDockhand extends CardImpl {
|
public final class MerchantsDockhand extends CardImpl {
|
||||||
|
@ -118,7 +114,7 @@ class TapXTargetCost extends VariableCostImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TapXTargetCost() {
|
public TapXTargetCost() {
|
||||||
super("controlled untapped artifacts you would like to tap");
|
super(VariableCostType.NORMAL, "controlled untapped artifacts you would like to tap");
|
||||||
this.text = "Tap X untapped artifacts you control";
|
this.text = "Tap X untapped artifacts you control";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import mage.MageInt;
|
||||||
import mage.MageObjectReference;
|
import mage.MageObjectReference;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.abilities.costs.mana.VariableManaCost;
|
import mage.abilities.costs.mana.VariableManaCost;
|
||||||
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
|
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
|
||||||
import mage.abilities.effects.ContinuousEffectImpl;
|
import mage.abilities.effects.ContinuousEffectImpl;
|
||||||
|
@ -38,7 +39,7 @@ public final class MirrorEntity extends CardImpl {
|
||||||
Ability ability = new SimpleActivatedAbility(new SetPowerToughnessAllEffect(
|
Ability ability = new SimpleActivatedAbility(new SetPowerToughnessAllEffect(
|
||||||
ManacostVariableValue.REGULAR, ManacostVariableValue.REGULAR,
|
ManacostVariableValue.REGULAR, ManacostVariableValue.REGULAR,
|
||||||
Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURES, true
|
Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURES, true
|
||||||
).setText("Until end of turn, creatures you control have base power and toughness X/X"), new VariableManaCost());
|
).setText("Until end of turn, creatures you control have base power and toughness X/X"), new VariableManaCost(VariableCostType.NORMAL));
|
||||||
ability.addEffect(new MirrorEntityEffect());
|
ability.addEffect(new MirrorEntityEffect());
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
|
|
||||||
package mage.cards.n;
|
package mage.cards.n;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.Cost;
|
|
||||||
import mage.abilities.costs.VariableCost;
|
import mage.abilities.costs.VariableCost;
|
||||||
import mage.abilities.costs.VariableCostImpl;
|
import mage.abilities.costs.common.DiscardXTargetCost;
|
||||||
import mage.abilities.costs.common.DiscardTargetCost;
|
|
||||||
import mage.abilities.dynamicvalue.common.DiscardCostCardManaValue;
|
import mage.abilities.dynamicvalue.common.DiscardCostCardManaValue;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.effects.common.DamageTargetEffect;
|
import mage.abilities.effects.common.DamageTargetEffect;
|
||||||
|
@ -15,8 +12,6 @@ import mage.constants.CardType;
|
||||||
import mage.filter.FilterCard;
|
import mage.filter.FilterCard;
|
||||||
import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent;
|
import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.players.Player;
|
|
||||||
import mage.target.common.TargetCardInHand;
|
|
||||||
import mage.target.common.TargetCreatureOrPlaneswalker;
|
import mage.target.common.TargetCreatureOrPlaneswalker;
|
||||||
import mage.target.targetadjustment.TargetAdjuster;
|
import mage.target.targetadjustment.TargetAdjuster;
|
||||||
|
|
||||||
|
@ -31,7 +26,7 @@ public final class NahirisWrath extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}");
|
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}");
|
||||||
|
|
||||||
// As an additional cost to cast Nahiri's Wrath, discard X cards.
|
// As an additional cost to cast Nahiri's Wrath, discard X cards.
|
||||||
this.getSpellAbility().addCost(new NahirisWrathAdditionalCost());
|
this.getSpellAbility().addCost(new DiscardXTargetCost(new FilterCard("cards"), true));
|
||||||
|
|
||||||
// Nahiri's Wrath deals damage equal to the total converted mana cost of the discarded cards to each of up to X target creatures and/or planeswalkers.
|
// Nahiri's Wrath deals damage equal to the total converted mana cost of the discarded cards to each of up to X target creatures and/or planeswalkers.
|
||||||
Effect effect = new DamageTargetEffect(DiscardCostCardManaValue.instance);
|
Effect effect = new DamageTargetEffect(DiscardCostCardManaValue.instance);
|
||||||
|
@ -58,7 +53,7 @@ enum NahirisWrathAdjuster implements TargetAdjuster {
|
||||||
ability.getTargets().clear();
|
ability.getTargets().clear();
|
||||||
int numTargets = 0;
|
int numTargets = 0;
|
||||||
for (VariableCost cost : ability.getCosts().getVariableCosts()) {
|
for (VariableCost cost : ability.getCosts().getVariableCosts()) {
|
||||||
if (cost instanceof NahirisWrathAdditionalCost) {
|
if (cost instanceof DiscardXTargetCost) {
|
||||||
numTargets = cost.getAmount();
|
numTargets = cost.getAmount();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -68,35 +63,3 @@ enum NahirisWrathAdjuster implements TargetAdjuster {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NahirisWrathAdditionalCost extends VariableCostImpl {
|
|
||||||
|
|
||||||
NahirisWrathAdditionalCost() {
|
|
||||||
super("cards to discard");
|
|
||||||
this.text = "discard X cards";
|
|
||||||
}
|
|
||||||
|
|
||||||
NahirisWrathAdditionalCost(final NahirisWrathAdditionalCost cost) {
|
|
||||||
super(cost);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NahirisWrathAdditionalCost copy() {
|
|
||||||
return new NahirisWrathAdditionalCost(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMaxValue(Ability source, Game game) {
|
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
|
||||||
if (controller != null) {
|
|
||||||
return controller.getHand().size();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Cost getFixedCostsFromAnnouncedValue(int xValue) {
|
|
||||||
TargetCardInHand target = new TargetCardInHand(xValue, new FilterCard("cards to discard"));
|
|
||||||
return new DiscardTargetCost(target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ public final class NostalgicDreams extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{G}{G}");
|
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{G}{G}");
|
||||||
|
|
||||||
// As an additional cost to cast Nostalgic Dreams, discard X cards.
|
// As an additional cost to cast Nostalgic Dreams, discard X cards.
|
||||||
this.getSpellAbility().addCost(new DiscardXTargetCost(new FilterCard("cards"), false));
|
this.getSpellAbility().addCost(new DiscardXTargetCost(new FilterCard("cards"), true));
|
||||||
|
|
||||||
// Return X target cards from your graveyard to your hand.
|
// Return X target cards from your graveyard to your hand.
|
||||||
Effect effect = new ReturnFromGraveyardToHandTargetEffect();
|
Effect effect = new ReturnFromGraveyardToHandTargetEffect();
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
|
|
||||||
package mage.cards.p;
|
package mage.cards.p;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.MageInt;
|
import mage.MageInt;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
@ -12,16 +10,17 @@ import mage.abilities.dynamicvalue.common.GetXValue;
|
||||||
import mage.abilities.dynamicvalue.common.SignInversionDynamicValue;
|
import mage.abilities.dynamicvalue.common.SignInversionDynamicValue;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||||
import mage.constants.SubType;
|
|
||||||
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.Duration;
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.SubType;
|
||||||
import mage.filter.FilterCard;
|
import mage.filter.FilterCard;
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author jeffwadsworth
|
* @author jeffwadsworth
|
||||||
*/
|
*/
|
||||||
public final class Painbringer extends CardImpl {
|
public final class Painbringer extends CardImpl {
|
||||||
|
@ -34,7 +33,7 @@ public final class Painbringer extends CardImpl {
|
||||||
this.power = new MageInt(1);
|
this.power = new MageInt(1);
|
||||||
this.toughness = new MageInt(1);
|
this.toughness = new MageInt(1);
|
||||||
|
|
||||||
// {tap}, Exile any number of cards from your graveyard: Target creature gets -X/-X until end of turn, where X is the number of cards exiled this way.
|
// {T}, Exile any number of cards from your graveyard: Target creature gets -X/-X until end of turn, where X is the number of cards exiled this way.
|
||||||
DynamicValue X = new SignInversionDynamicValue(GetXValue.instance);
|
DynamicValue X = new SignInversionDynamicValue(GetXValue.instance);
|
||||||
Effect effect = new BoostTargetEffect(X, X, Duration.EndOfTurn);
|
Effect effect = new BoostTargetEffect(X, X, Duration.EndOfTurn);
|
||||||
effect.setText("Target creature gets -X/-X until end of turn, where X is the number of cards exiled this way");
|
effect.setText("Target creature gets -X/-X until end of turn, where X is the number of cards exiled this way");
|
||||||
|
|
|
@ -4,6 +4,7 @@ import mage.ApprovingObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.abilities.costs.common.TapSourceCost;
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
import mage.abilities.costs.mana.VariableManaCost;
|
import mage.abilities.costs.mana.VariableManaCost;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
@ -30,7 +31,7 @@ public final class PanopticMirror extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}");
|
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}");
|
||||||
|
|
||||||
// Imprint - {X}, {tap}: You may exile an instant or sorcery card with converted mana cost X from your hand.
|
// Imprint - {X}, {tap}: You may exile an instant or sorcery card with converted mana cost X from your hand.
|
||||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PanopticMirrorExileEffect(), new VariableManaCost());
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PanopticMirrorExileEffect(), new VariableManaCost(VariableCostType.NORMAL));
|
||||||
ability.addCost(new TapSourceCost());
|
ability.addCost(new TapSourceCost());
|
||||||
this.addAbility(ability.setAbilityWord(AbilityWord.IMPRINT));
|
this.addAbility(ability.setAbilityWord(AbilityWord.IMPRINT));
|
||||||
// At the beginning of your upkeep, you may copy a card exiled with Panoptic Mirror. If you do, you may cast the copy without paying its mana cost.
|
// At the beginning of your upkeep, you may copy a card exiled with Panoptic Mirror. If you do, you may cast the copy without paying its mana cost.
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package mage.cards.p;
|
package mage.cards.p;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.abilities.costs.common.SacrificeSourceCost;
|
import mage.abilities.costs.common.SacrificeSourceCost;
|
||||||
import mage.abilities.costs.mana.VariableManaCost;
|
import mage.abilities.costs.mana.VariableManaCost;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
@ -18,6 +18,8 @@ import mage.filter.predicate.Predicates;
|
||||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Plopman
|
* @author Plopman
|
||||||
*/
|
*/
|
||||||
|
@ -27,7 +29,7 @@ public final class PerniciousDeed extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}{G}");
|
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}{G}");
|
||||||
|
|
||||||
// {X}, Sacrifice Pernicious Deed: Destroy each artifact, creature, and enchantment with converted mana cost X or less.
|
// {X}, Sacrifice Pernicious Deed: Destroy each artifact, creature, and enchantment with converted mana cost X or less.
|
||||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PerniciousDeedEffect(), new VariableManaCost());
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PerniciousDeedEffect(), new VariableManaCost(VariableCostType.NORMAL));
|
||||||
ability.addCost(new SacrificeSourceCost());
|
ability.addCost(new SacrificeSourceCost());
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ public final class RestlessDreams extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{B}");
|
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{B}");
|
||||||
|
|
||||||
// As an additional cost to cast Restless Dreams, discard X cards.
|
// As an additional cost to cast Restless Dreams, discard X cards.
|
||||||
this.getSpellAbility().addCost(new DiscardXTargetCost(StaticFilters.FILTER_CARD_CARDS, false));
|
this.getSpellAbility().addCost(new DiscardXTargetCost(StaticFilters.FILTER_CARD_CARDS, true));
|
||||||
|
|
||||||
// Return X target creature cards from your graveyard to your hand.
|
// Return X target creature cards from your graveyard to your hand.
|
||||||
Effect effect = new ReturnFromGraveyardToHandTargetEffect();
|
Effect effect = new ReturnFromGraveyardToHandTargetEffect();
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
|
|
||||||
package mage.cards.r;
|
package mage.cards.r;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.common.RemoveVariableCountersTargetCost;
|
import mage.abilities.costs.common.RemoveVariableCountersTargetCost;
|
||||||
|
@ -19,8 +17,9 @@ import mage.counters.CounterType;
|
||||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
*/
|
*/
|
||||||
public final class RetributionOfTheAncients extends CardImpl {
|
public final class RetributionOfTheAncients extends CardImpl {
|
||||||
|
@ -32,12 +31,11 @@ public final class RetributionOfTheAncients extends CardImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public RetributionOfTheAncients(UUID ownerId, CardSetInfo setInfo) {
|
public RetributionOfTheAncients(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{B}");
|
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{B}");
|
||||||
|
|
||||||
|
|
||||||
DynamicValue xValue = new SignInversionDynamicValue(GetXValue.instance);
|
|
||||||
// {B}, Remove X +1/+1 counters from among creatures you control: Target creature gets -X/-X until end of turn.
|
// {B}, Remove X +1/+1 counters from among creatures you control: Target creature gets -X/-X until end of turn.
|
||||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(xValue,xValue,Duration.EndOfTurn, true), new ManaCostsImpl("{B}"));
|
DynamicValue xValue = new SignInversionDynamicValue(GetXValue.instance);
|
||||||
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(xValue, xValue, Duration.EndOfTurn, true), new ManaCostsImpl("{B}"));
|
||||||
ability.addCost(new RemoveVariableCountersTargetCost(filter, CounterType.P1P1, "X", 0));
|
ability.addCost(new RemoveVariableCountersTargetCost(filter, CounterType.P1P1, "X", 0));
|
||||||
ability.addTarget(new TargetCreaturePermanent());
|
ability.addTarget(new TargetCreaturePermanent());
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
|
|
||||||
|
|
||||||
package mage.cards.s;
|
package mage.cards.s;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.abilities.costs.common.TapSourceCost;
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
import mage.abilities.costs.mana.VariableManaCost;
|
import mage.abilities.costs.mana.VariableManaCost;
|
||||||
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
|
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
|
||||||
|
@ -15,17 +13,18 @@ import mage.constants.CardType;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.target.TargetPlayer;
|
import mage.target.TargetPlayer;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author Loki
|
* @author Loki
|
||||||
*/
|
*/
|
||||||
public final class SandsOfDelirium extends CardImpl {
|
public final class SandsOfDelirium extends CardImpl {
|
||||||
|
|
||||||
public SandsOfDelirium(UUID ownerId, CardSetInfo setInfo) {
|
public SandsOfDelirium(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}");
|
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
|
||||||
|
|
||||||
// {X}, {tap}: Target player puts the top X cards of their library into their graveyard.
|
// {X}, {tap}: Target player puts the top X cards of their library into their graveyard.
|
||||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PutLibraryIntoGraveTargetEffect(ManacostVariableValue.REGULAR), new VariableManaCost());
|
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PutLibraryIntoGraveTargetEffect(ManacostVariableValue.REGULAR), new VariableManaCost(VariableCostType.NORMAL));
|
||||||
ability.addCost(new TapSourceCost());
|
ability.addCost(new TapSourceCost());
|
||||||
ability.addTarget(new TargetPlayer());
|
ability.addTarget(new TargetPlayer());
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
|
|
||||||
package mage.cards.s;
|
package mage.cards.s;
|
||||||
|
|
||||||
import java.util.UUID;
|
import mage.abilities.costs.common.DiscardXTargetCost;
|
||||||
import mage.abilities.Ability;
|
|
||||||
import mage.abilities.costs.Cost;
|
|
||||||
import mage.abilities.costs.VariableCostImpl;
|
|
||||||
import mage.abilities.costs.common.DiscardTargetCost;
|
|
||||||
import mage.abilities.dynamicvalue.common.GetXValue;
|
import mage.abilities.dynamicvalue.common.GetXValue;
|
||||||
import mage.abilities.effects.common.DamageEverythingEffect;
|
import mage.abilities.effects.common.DamageEverythingEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
|
@ -13,21 +8,19 @@ import mage.cards.CardSetInfo;
|
||||||
import mage.constants.CardType;
|
import mage.constants.CardType;
|
||||||
import mage.filter.FilterCard;
|
import mage.filter.FilterCard;
|
||||||
import mage.filter.common.FilterCreaturePermanent;
|
import mage.filter.common.FilterCreaturePermanent;
|
||||||
import mage.game.Game;
|
|
||||||
import mage.players.Player;
|
import java.util.UUID;
|
||||||
import mage.target.common.TargetCardInHand;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author fireshoes
|
* @author fireshoes
|
||||||
*/
|
*/
|
||||||
public final class SickeningDreams extends CardImpl {
|
public final class SickeningDreams extends CardImpl {
|
||||||
|
|
||||||
public SickeningDreams(UUID ownerId, CardSetInfo setInfo) {
|
public SickeningDreams(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{B}");
|
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}");
|
||||||
|
|
||||||
// As an additional cost to cast Sickening Dreams, discard X cards.
|
// As an additional cost to cast Sickening Dreams, discard X cards.
|
||||||
this.getSpellAbility().addCost(new SickeningDreamsAdditionalCost());
|
this.getSpellAbility().addCost(new DiscardXTargetCost(new FilterCard("cards"), true));
|
||||||
|
|
||||||
// Sickening Dreams deals X damage to each creature and each player.
|
// Sickening Dreams deals X damage to each creature and each player.
|
||||||
this.getSpellAbility().addEffect(new DamageEverythingEffect(GetXValue.instance, new FilterCreaturePermanent()));
|
this.getSpellAbility().addEffect(new DamageEverythingEffect(GetXValue.instance, new FilterCreaturePermanent()));
|
||||||
|
@ -42,35 +35,3 @@ public final class SickeningDreams extends CardImpl {
|
||||||
return new SickeningDreams(this);
|
return new SickeningDreams(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SickeningDreamsAdditionalCost extends VariableCostImpl {
|
|
||||||
|
|
||||||
SickeningDreamsAdditionalCost() {
|
|
||||||
super("cards to discard");
|
|
||||||
this.text = "discard X cards";
|
|
||||||
}
|
|
||||||
|
|
||||||
SickeningDreamsAdditionalCost(final SickeningDreamsAdditionalCost cost) {
|
|
||||||
super(cost);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SickeningDreamsAdditionalCost copy() {
|
|
||||||
return new SickeningDreamsAdditionalCost(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMaxValue(Ability source, Game game) {
|
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
|
||||||
if (controller != null) {
|
|
||||||
return controller.getHand().size();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Cost getFixedCostsFromAnnouncedValue(int xValue) {
|
|
||||||
TargetCardInHand target = new TargetCardInHand(xValue, new FilterCard());
|
|
||||||
return new DiscardTargetCost(target);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,5 @@
|
||||||
|
|
||||||
package mage.cards.s;
|
package mage.cards.s;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.Mana;
|
import mage.Mana;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
@ -21,10 +19,10 @@ import mage.constants.Zone;
|
||||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||||
import mage.game.permanent.token.GoatToken;
|
import mage.game.permanent.token.GoatToken;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author jeffwadsworth
|
* @author jeffwadsworth
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public final class SpringjackPasture extends CardImpl {
|
public final class SpringjackPasture extends CardImpl {
|
||||||
|
|
||||||
|
@ -35,7 +33,7 @@ public final class SpringjackPasture extends CardImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SpringjackPasture(UUID ownerId, CardSetInfo setInfo) {
|
public SpringjackPasture(UUID ownerId, CardSetInfo setInfo) {
|
||||||
super(ownerId,setInfo,new CardType[]{CardType.LAND},"");
|
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
|
||||||
|
|
||||||
// {tap}: Add {C}.
|
// {tap}: Add {C}.
|
||||||
this.addAbility(new ColorlessManaAbility());
|
this.addAbility(new ColorlessManaAbility());
|
||||||
|
@ -45,9 +43,9 @@ public final class SpringjackPasture extends CardImpl {
|
||||||
ability.addCost(new TapSourceCost());
|
ability.addCost(new TapSourceCost());
|
||||||
this.addAbility(ability);
|
this.addAbility(ability);
|
||||||
|
|
||||||
// {tap}, Sacrifice X Goats: Add X mana of any one color. You gain X life.
|
// {T}, Sacrifice X Goats: Add X mana of any one color. You gain X life.
|
||||||
ability = new DynamicManaAbility(
|
ability = new DynamicManaAbility(
|
||||||
new Mana(0, 0, 0, 0,0, 0,1,0),
|
new Mana(0, 0, 0, 0, 0, 0, 1, 0),
|
||||||
GetXValue.instance,
|
GetXValue.instance,
|
||||||
new TapSourceCost(),
|
new TapSourceCost(),
|
||||||
"Add X mana of any one color",
|
"Add X mana of any one color",
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
|
|
||||||
package mage.cards.t;
|
package mage.cards.t;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.TriggeredAbilityImpl;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.VariableCostImpl;
|
import mage.abilities.costs.VariableCostImpl;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.abilities.costs.common.RemoveCountersSourceCost;
|
import mage.abilities.costs.common.RemoveCountersSourceCost;
|
||||||
import mage.abilities.costs.common.TapSourceCost;
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
@ -25,8 +24,9 @@ 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 jerekwilson
|
* @author jerekwilson
|
||||||
*/
|
*/
|
||||||
public final class TalonOfPain extends CardImpl {
|
public final class TalonOfPain extends CardImpl {
|
||||||
|
@ -89,19 +89,17 @@ public final class TalonOfPain extends CardImpl {
|
||||||
if (controller.hasOpponent(event.getTargetId(), game)) {
|
if (controller.hasOpponent(event.getTargetId(), game)) {
|
||||||
// a source you control other than Talon of Pain
|
// a source you control other than Talon of Pain
|
||||||
UUID sourceControllerId = game.getControllerId(event.getSourceId());
|
UUID sourceControllerId = game.getControllerId(event.getSourceId());
|
||||||
if (sourceControllerId != null
|
// return true so the effect will fire and a charge counter will be added
|
||||||
|
return sourceControllerId != null
|
||||||
&& sourceControllerId.equals(this.getControllerId())
|
&& sourceControllerId.equals(this.getControllerId())
|
||||||
&& !this.getSourceId().equals(event.getSourceId())) {
|
&& !this.getSourceId().equals(event.getSourceId());
|
||||||
// return true so the effect will fire and a charge counter will be added
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTriggerPhrase() {
|
public String getTriggerPhrase() {
|
||||||
return "Whenever a source you control other than {this} deals damage to an opponent, " ;
|
return "Whenever a source you control other than {this} deals damage to an opponent, ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,7 +107,7 @@ public final class TalonOfPain extends CardImpl {
|
||||||
class TalonOfPainRemoveVariableCountersSourceCost extends VariableCostImpl {
|
class TalonOfPainRemoveVariableCountersSourceCost extends VariableCostImpl {
|
||||||
|
|
||||||
protected int minimalCountersToPay = 0;
|
protected int minimalCountersToPay = 0;
|
||||||
private String counterName;
|
private final String counterName;
|
||||||
|
|
||||||
public TalonOfPainRemoveVariableCountersSourceCost(Counter counter) {
|
public TalonOfPainRemoveVariableCountersSourceCost(Counter counter) {
|
||||||
this(counter, 0);
|
this(counter, 0);
|
||||||
|
@ -124,7 +122,7 @@ class TalonOfPainRemoveVariableCountersSourceCost extends VariableCostImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TalonOfPainRemoveVariableCountersSourceCost(Counter counter, int minimalCountersToPay, String text) {
|
public TalonOfPainRemoveVariableCountersSourceCost(Counter counter, int minimalCountersToPay, String text) {
|
||||||
super(counter.getName() + " counters to remove");
|
super(VariableCostType.NORMAL, counter.getName() + " counters to remove");
|
||||||
this.minimalCountersToPay = minimalCountersToPay;
|
this.minimalCountersToPay = minimalCountersToPay;
|
||||||
this.counterName = counter.getName();
|
this.counterName = counter.getName();
|
||||||
if (text == null || text.isEmpty()) {
|
if (text == null || text.isEmpty()) {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package mage.cards.t;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.abilities.costs.mana.VariableManaCost;
|
import mage.abilities.costs.mana.VariableManaCost;
|
||||||
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
|
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
|
||||||
import mage.abilities.effects.ContinuousEffectImpl;
|
import mage.abilities.effects.ContinuousEffectImpl;
|
||||||
|
@ -27,7 +28,7 @@ public final class TestamentOfFaith extends CardImpl {
|
||||||
// {X}: Testament of Faith becomes an X/X Wall creature with defender in addition to its other types until end of turn.
|
// {X}: Testament of Faith becomes an X/X Wall creature with defender in addition to its other types until end of turn.
|
||||||
Ability ability = new SimpleActivatedAbility(new SetPowerToughnessSourceEffect(
|
Ability ability = new SimpleActivatedAbility(new SetPowerToughnessSourceEffect(
|
||||||
ManacostVariableValue.REGULAR, Duration.EndOfTurn, SubLayer.SetPT_7b
|
ManacostVariableValue.REGULAR, Duration.EndOfTurn, SubLayer.SetPT_7b
|
||||||
).setText("{this} becomes an X/X"), new VariableManaCost());
|
).setText("{this} becomes an X/X"), new VariableManaCost(VariableCostType.NORMAL));
|
||||||
ability.addEffect(new TestamentOfFaithEffect());
|
ability.addEffect(new TestamentOfFaithEffect());
|
||||||
ability.addEffect(new GainAbilitySourceEffect(
|
ability.addEffect(new GainAbilitySourceEffect(
|
||||||
DefenderAbility.getInstance(), Duration.EndOfTurn
|
DefenderAbility.getInstance(), Duration.EndOfTurn
|
||||||
|
|
|
@ -38,7 +38,7 @@ public final class ThievingSkydiver extends CardImpl {
|
||||||
|
|
||||||
// Kicker {X}. X can't be 0.
|
// Kicker {X}. X can't be 0.
|
||||||
KickerAbility kickerAbility = new KickerAbility("{X}");
|
KickerAbility kickerAbility = new KickerAbility("{X}");
|
||||||
kickerAbility.getKickerCosts().stream().forEach(cost -> {
|
kickerAbility.getKickerCosts().forEach(cost -> {
|
||||||
cost.setMinimumCost(1);
|
cost.setMinimumCost(1);
|
||||||
cost.setReminderText(". X can't be 0.");
|
cost.setReminderText(". X can't be 0.");
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,6 +2,7 @@ package mage.cards.t;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.abilities.costs.common.TapSourceCost;
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
import mage.abilities.costs.mana.VariableManaCost;
|
import mage.abilities.costs.mana.VariableManaCost;
|
||||||
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
|
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
|
||||||
|
@ -21,7 +22,6 @@ import mage.target.common.TargetOpponent;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author noahg
|
* @author noahg
|
||||||
*/
|
*/
|
||||||
public final class ThoughtDissector extends CardImpl {
|
public final class ThoughtDissector extends CardImpl {
|
||||||
|
@ -31,7 +31,7 @@ public final class ThoughtDissector extends CardImpl {
|
||||||
|
|
||||||
|
|
||||||
// {X}, {tap}: Target opponent reveals cards from the top of their library until an artifact card or X cards are revealed, whichever comes first. If an artifact card is revealed this way, put it onto the battlefield under your control and sacrifice Thought Dissector. Put the rest of the revealed cards into that player's graveyard.
|
// {X}, {tap}: Target opponent reveals cards from the top of their library until an artifact card or X cards are revealed, whichever comes first. If an artifact card is revealed this way, put it onto the battlefield under your control and sacrifice Thought Dissector. Put the rest of the revealed cards into that player's graveyard.
|
||||||
SimpleActivatedAbility abilitiy = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ThoughtDissectorEffect(), new VariableManaCost());
|
SimpleActivatedAbility abilitiy = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ThoughtDissectorEffect(), new VariableManaCost(VariableCostType.NORMAL));
|
||||||
abilitiy.addCost(new TapSourceCost());
|
abilitiy.addCost(new TapSourceCost());
|
||||||
abilitiy.addTarget(new TargetOpponent());
|
abilitiy.addTarget(new TargetOpponent());
|
||||||
this.addAbility(abilitiy);
|
this.addAbility(abilitiy);
|
||||||
|
@ -82,7 +82,7 @@ class ThoughtDissectorEffect extends OneShotEffect {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
numberOfCard++;
|
numberOfCard++;
|
||||||
if (numberOfCard > max){
|
if (numberOfCard > max) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
nonArtifacts.add(card);
|
nonArtifacts.add(card);
|
||||||
|
|
|
@ -26,7 +26,7 @@ public final class TurbulentDreams extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{U}{U}");
|
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{U}{U}");
|
||||||
|
|
||||||
// As an additional cost to cast Turbulent Dreams, discard X cards.
|
// As an additional cost to cast Turbulent Dreams, discard X cards.
|
||||||
this.getSpellAbility().addCost(new DiscardXTargetCost(StaticFilters.FILTER_CARD_CARDS, false));
|
this.getSpellAbility().addCost(new DiscardXTargetCost(StaticFilters.FILTER_CARD_CARDS, true));
|
||||||
|
|
||||||
// Return X target nonland permanents to their owners' hands.
|
// Return X target nonland permanents to their owners' hands.
|
||||||
Effect effect = new ReturnToHandTargetEffect();
|
Effect effect = new ReturnToHandTargetEffect();
|
||||||
|
|
|
@ -25,7 +25,7 @@ public final class VengefulDreams extends CardImpl {
|
||||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}{W}");
|
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}{W}");
|
||||||
|
|
||||||
// As an additional cost to cast Vengeful Dreams, discard X cards.
|
// As an additional cost to cast Vengeful Dreams, discard X cards.
|
||||||
this.getSpellAbility().addCost(new DiscardXTargetCost(new FilterCard("cards"), false));
|
this.getSpellAbility().addCost(new DiscardXTargetCost(new FilterCard("cards"), true));
|
||||||
|
|
||||||
// Exile X target attacking creatures.
|
// Exile X target attacking creatures.
|
||||||
Effect effect = new ExileTargetEffect();
|
Effect effect = new ExileTargetEffect();
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package mage.cards.v;
|
package mage.cards.v;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
|
@ -27,7 +26,7 @@ public final class ViciousBetrayal extends CardImpl {
|
||||||
|
|
||||||
|
|
||||||
// As an additional cost to cast Vicious Betrayal, sacrifice any number of creatures.
|
// As an additional cost to cast Vicious Betrayal, sacrifice any number of creatures.
|
||||||
this.getSpellAbility().addCost(new SacrificeXTargetCost(new FilterControlledCreaturePermanent()));
|
this.getSpellAbility().addCost(new SacrificeXTargetCost(new FilterControlledCreaturePermanent(), true));
|
||||||
// Target creature gets +2/+2 until end of turn for each creature sacrificed this way.
|
// Target creature gets +2/+2 until end of turn for each creature sacrificed this way.
|
||||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
||||||
this.getSpellAbility().addEffect(new BoostTargetEffect(GetXValue.instance, GetXValue.instance, Duration.EndOfTurn));
|
this.getSpellAbility().addEffect(new BoostTargetEffect(GetXValue.instance, GetXValue.instance, Duration.EndOfTurn));
|
||||||
|
|
|
@ -3,7 +3,6 @@ package mage.cards.w;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SpellCastOpponentTriggeredAbility;
|
import mage.abilities.common.SpellCastOpponentTriggeredAbility;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.mana.GenericManaCost;
|
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.cards.*;
|
import mage.cards.*;
|
||||||
import mage.constants.*;
|
import mage.constants.*;
|
||||||
|
@ -15,6 +14,7 @@ import mage.game.stack.Spell;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.TargetCard;
|
import mage.target.TargetCard;
|
||||||
import mage.target.common.TargetCardInLibrary;
|
import mage.target.common.TargetCardInLibrary;
|
||||||
|
import mage.util.ManaUtil;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -85,7 +85,7 @@ class WanderingArchaicEffect extends OneShotEffect {
|
||||||
if (controller == null || opponent == null || spell == null) {
|
if (controller == null || opponent == null || spell == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Cost cost = new GenericManaCost(2);
|
Cost cost = ManaUtil.createManaCost(2, false);
|
||||||
if (cost.canPay(source, source, opponent.getId(), game)
|
if (cost.canPay(source, source, opponent.getId(), game)
|
||||||
&& opponent.chooseUse(outcome, "Pay {2}?", source, game)
|
&& opponent.chooseUse(outcome, "Pay {2}?", source, game)
|
||||||
&& cost.pay(source, game, source, opponent.getId(), false)) {
|
&& cost.pay(source, game, source, opponent.getId(), false)) {
|
||||||
|
|
|
@ -2,7 +2,6 @@ package mage.cards.w;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.mana.GenericManaCost;
|
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
|
@ -10,6 +9,8 @@ import mage.constants.CardType;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
import mage.util.ManaUtil;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ -65,10 +66,10 @@ class WhirlwindDenialEffect extends OneShotEffect {
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Cost cost = new GenericManaCost(4);
|
Cost cost = ManaUtil.createManaCost(4, false);
|
||||||
if (cost.canPay(source, source, stackObject.getControllerId(), game)
|
if (cost.canPay(source, source, stackObject.getControllerId(), game)
|
||||||
&& player.chooseUse(outcome, "Pay {4} to prevent "
|
&& player.chooseUse(outcome, "Pay {4} to prevent "
|
||||||
+ stackObject.getIdName() + " from being countered?", source, game)
|
+ stackObject.getIdName() + " from being countered?", source, game)
|
||||||
&& cost.pay(source, game, source, stackObject.getControllerId(), false)) {
|
&& cost.pay(source, game, source, stackObject.getControllerId(), false)) {
|
||||||
game.informPlayers("The cost was paid by "
|
game.informPlayers("The cost was paid by "
|
||||||
+ player.getLogName()
|
+ player.getLogName()
|
||||||
|
|
|
@ -651,4 +651,68 @@ public class KickerTest extends CardTestPlayerBase {
|
||||||
assertGraveyardCount(playerA, "Marsh Casualties", 1);
|
assertGraveyardCount(playerA, "Marsh Casualties", 1);
|
||||||
assertPowerToughness(playerB, "Centaur Courser", 1, 1);
|
assertPowerToughness(playerB, "Centaur Courser", 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_FreeCast_Normal() {
|
||||||
|
skipInitShuffling();
|
||||||
|
|
||||||
|
// Kicker {2}
|
||||||
|
// If Ardent Soldier was kicked, it enters the battlefield with a +1/+1 counter on it.
|
||||||
|
addCard(Zone.LIBRARY, playerA, "Ardent Soldier", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2); // for kicker cost
|
||||||
|
//
|
||||||
|
// Whenever Etali, Primal Storm attacks, exile the top card of each player's library,
|
||||||
|
// then you may cast any number of nonland cards exiled this way without paying their mana costs.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Etali, Primal Storm", 1);
|
||||||
|
|
||||||
|
checkPlayableAbility("before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Ardent Soldier", false);
|
||||||
|
|
||||||
|
// attack and prepare free cast, use kicker
|
||||||
|
attack(1, playerA, "Etali, Primal Storm", playerB);
|
||||||
|
setChoice(playerA, true); // cast for free
|
||||||
|
setChoice(playerA, "Ardent Soldier"); // cast for free
|
||||||
|
setChoice(playerA, true); // use kicker
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
|
||||||
|
assertCounterCount(playerA, "Ardent Soldier", CounterType.P1P1, 1); // from kicker
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_FreeCast_MinXValueMustWork() {
|
||||||
|
// bug:
|
||||||
|
// Can cast Thieving Skydiver with kicker's X = 0 on Etali, Primal Storm
|
||||||
|
skipInitShuffling();
|
||||||
|
|
||||||
|
// Kicker {X}. X can't be 0.
|
||||||
|
// When Thieving Skydiver enters the battlefield, if it was kicked, gain control of target artifact with
|
||||||
|
// converted mana cost X or less. If that artifact is an Equipment, attach it to Thieving Skydiver.
|
||||||
|
addCard(Zone.LIBRARY, playerA, "Thieving Skydiver", 1); // {1}{U}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Brain in a Jar", 1); // {2}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2); // for kicker cost
|
||||||
|
//
|
||||||
|
// Whenever Etali, Primal Storm attacks, exile the top card of each player's library,
|
||||||
|
// then you may cast any number of nonland cards exiled this way without paying their mana costs.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Etali, Primal Storm", 1);
|
||||||
|
|
||||||
|
checkPlayableAbility("before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Thieving Skydiver", false);
|
||||||
|
|
||||||
|
// attack and prepare free cast
|
||||||
|
attack(1, playerA, "Etali, Primal Storm", playerB);
|
||||||
|
setChoice(playerA, true); // cast for free
|
||||||
|
setChoice(playerA, "Thieving Skydiver"); // cast for free
|
||||||
|
setChoice(playerA, true); // use kicker
|
||||||
|
setChoiceAmount(playerA, 2); // X=2 for Kicker X
|
||||||
|
addTarget(playerA, "Brain in a Jar"); // kicker's target (take control of artifact)
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Brain in a Jar", 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.mage.test.cards.continuous;
|
package org.mage.test.cards.continuous;
|
||||||
|
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.abilities.costs.mana.VariableManaCost;
|
import mage.abilities.costs.mana.VariableManaCost;
|
||||||
import mage.constants.PhaseStep;
|
import mage.constants.PhaseStep;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
|
@ -182,7 +183,7 @@ public class UnboundFlourishingTest extends CardTestPlayerBase {
|
||||||
int xInstancesCount = 2;
|
int xInstancesCount = 2;
|
||||||
int xAnnouncedValue = 3;
|
int xAnnouncedValue = 3;
|
||||||
int xMultiplier = 2;
|
int xMultiplier = 2;
|
||||||
VariableManaCost cost = new VariableManaCost(xInstancesCount);
|
VariableManaCost cost = new VariableManaCost(VariableCostType.NORMAL, xInstancesCount);
|
||||||
cost.setAmount(xAnnouncedValue * xMultiplier, xAnnouncedValue * xInstancesCount, false);
|
cost.setAmount(xAnnouncedValue * xMultiplier, xAnnouncedValue * xInstancesCount, false);
|
||||||
|
|
||||||
Assert.assertEquals("instances count", xInstancesCount, cost.getXInstancesCount());
|
Assert.assertEquals("instances count", xInstancesCount, cost.getXInstancesCount());
|
||||||
|
|
|
@ -259,7 +259,7 @@ public abstract class AbilityImpl implements Ability {
|
||||||
if (!this.getManaCostsToPay().getVariableCosts().isEmpty()) {
|
if (!this.getManaCostsToPay().getVariableCosts().isEmpty()) {
|
||||||
int xValue = this.getManaCostsToPay().getX();
|
int xValue = this.getManaCostsToPay().getX();
|
||||||
this.getManaCostsToPay().clear();
|
this.getManaCostsToPay().clear();
|
||||||
VariableManaCost xCosts = new VariableManaCost();
|
VariableManaCost xCosts = new VariableManaCost(VariableCostType.ADDITIONAL);
|
||||||
// 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, false);
|
xCosts.setAmount(xValue, xValue, false);
|
||||||
|
@ -555,9 +555,17 @@ public abstract class AbilityImpl implements Ability {
|
||||||
* @return variableManaCost for posting to log later
|
* @return variableManaCost for posting to log later
|
||||||
*/
|
*/
|
||||||
protected VariableManaCost handleManaXCosts(Game game, boolean noMana, Player controller) {
|
protected VariableManaCost handleManaXCosts(Game game, boolean noMana, Player controller) {
|
||||||
// 20121001 - 601.2b
|
// 20210723 - 601.2b
|
||||||
// If the spell has a variable cost that will be paid as it's being cast (such as an {X} in
|
// If the spell has alternative or additional costs that will
|
||||||
// its mana cost; see rule 107.3), the player announces the value of that variable.
|
// be paid as it’s being cast such as buyback or kicker costs (see rules 118.8 and 118.9),
|
||||||
|
// the player announces their intentions to pay any or all of those costs (see rule 601.2f).
|
||||||
|
// A player can’t apply two alternative methods of casting or two alternative costs to a
|
||||||
|
// single spell. If the spell has a variable cost that will be paid as it’s being cast
|
||||||
|
// (such as an {X} in its mana cost; see rule 107.3), the player announces the value of that
|
||||||
|
// variable. If the value of that variable is defined in the text of the spell by a choice
|
||||||
|
// that player would make later in the announcement or resolution of the spell, that player
|
||||||
|
// makes that choice at this time instead of that later time.
|
||||||
|
|
||||||
// TODO: Handle announcing other variable costs here like: RemoveVariableCountersSourceCost
|
// TODO: Handle announcing other variable costs here like: RemoveVariableCountersSourceCost
|
||||||
VariableManaCost variableManaCost = null;
|
VariableManaCost variableManaCost = null;
|
||||||
for (ManaCost cost : manaCostsToPay) {
|
for (ManaCost cost : manaCostsToPay) {
|
||||||
|
@ -574,7 +582,7 @@ public abstract class AbilityImpl implements Ability {
|
||||||
if (!variableManaCost.isPaid()) { // should only happen for human players
|
if (!variableManaCost.isPaid()) { // should only happen for human players
|
||||||
int xValue;
|
int xValue;
|
||||||
int xValueMultiplier = handleManaXMultiplier(game, 1);
|
int xValueMultiplier = handleManaXMultiplier(game, 1);
|
||||||
if (!noMana) {
|
if (!noMana || variableManaCost.getCostType().canUseAnnounceOnFreeCast()) {
|
||||||
xValue = controller.announceXMana(variableManaCost.getMinX(), variableManaCost.getMaxX(), xValueMultiplier,
|
xValue = controller.announceXMana(variableManaCost.getMinX(), variableManaCost.getMaxX(), xValueMultiplier,
|
||||||
"Announce the value for " + variableManaCost.getText(), game, this);
|
"Announce the value for " + variableManaCost.getText(), game, this);
|
||||||
int amountMana = xValue * variableManaCost.getXInstancesCount();
|
int amountMana = xValue * variableManaCost.getXInstancesCount();
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
package mage.abilities.costs;
|
package mage.abilities.costs;
|
||||||
|
|
||||||
import mage.util.Copyable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Virtual optional/additional cost, it must be tranformed to simple cost on resolve in your custom ability.
|
||||||
|
* Don't forget to set up cost type for variable costs
|
||||||
|
* <p>
|
||||||
|
* Example: KickerAbility.
|
||||||
|
*
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
*/
|
*/
|
||||||
public interface OptionalAdditionalCost extends Cost {
|
public interface OptionalAdditionalCost extends Cost {
|
||||||
|
@ -77,6 +80,13 @@ public interface OptionalAdditionalCost extends Cost {
|
||||||
*/
|
*/
|
||||||
int getActivateCount();
|
int getActivateCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set cost type to variable costs like additional or normal (example: Kicker)
|
||||||
|
*
|
||||||
|
* @param costType
|
||||||
|
*/
|
||||||
|
void setCostType(VariableCostType costType);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
OptionalAdditionalCost copy();
|
OptionalAdditionalCost copy();
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,6 +166,12 @@ public class OptionalAdditionalCostImpl extends CostsImpl<Cost> implements Optio
|
||||||
return activatedCounter;
|
return activatedCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCostType(VariableCostType costType) {
|
||||||
|
this.getVariableCosts().forEach(cost -> {
|
||||||
|
cost.setCostType(costType);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OptionalAdditionalCostImpl copy() {
|
public OptionalAdditionalCostImpl copy() {
|
||||||
|
|
|
@ -13,6 +13,12 @@ import mage.game.Game;
|
||||||
*/
|
*/
|
||||||
public interface OptionalAdditionalSourceCosts {
|
public interface OptionalAdditionalSourceCosts {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warning, don't forget to set up cost type for costs, it can help with X announce
|
||||||
|
*
|
||||||
|
* @param ability
|
||||||
|
* @param game
|
||||||
|
*/
|
||||||
// TODO: add AI support to use buyback, replicate and other additional costs (current version can't calc available mana before buyback use)
|
// TODO: add AI support to use buyback, replicate and other additional costs (current version can't calc available mana before buyback use)
|
||||||
void addOptionalAdditionalCosts(Ability ability, Game game);
|
void addOptionalAdditionalCosts(Ability ability, Game game);
|
||||||
|
|
||||||
|
|
|
@ -64,4 +64,8 @@ public interface VariableCost {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
Cost getFixedCostsFromAnnouncedValue(int xValue);
|
Cost getFixedCostsFromAnnouncedValue(int xValue);
|
||||||
|
|
||||||
|
VariableCostType getCostType();
|
||||||
|
|
||||||
|
void setCostType(VariableCostType costType);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import java.util.UUID;
|
||||||
public abstract class VariableCostImpl implements Cost, VariableCost {
|
public abstract class VariableCostImpl implements Cost, VariableCost {
|
||||||
|
|
||||||
protected UUID id;
|
protected UUID id;
|
||||||
|
protected VariableCostType costType;
|
||||||
protected String text;
|
protected String text;
|
||||||
protected boolean paid;
|
protected boolean paid;
|
||||||
protected Targets targets;
|
protected Targets targets;
|
||||||
|
@ -23,8 +24,8 @@ public abstract class VariableCostImpl implements Cost, VariableCost {
|
||||||
protected String xText;
|
protected String xText;
|
||||||
protected String actionText;
|
protected String actionText;
|
||||||
|
|
||||||
public VariableCostImpl(String actionText) {
|
public VariableCostImpl(VariableCostType costType, String actionText) {
|
||||||
this("X", actionText);
|
this(costType, "X", actionText);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,17 +33,19 @@ public abstract class VariableCostImpl implements Cost, VariableCost {
|
||||||
* @param actionText what happens with the value (e.g. "to tap", "to exile
|
* @param actionText what happens with the value (e.g. "to tap", "to exile
|
||||||
* from your graveyard")
|
* from your graveyard")
|
||||||
*/
|
*/
|
||||||
public VariableCostImpl(String xText, String actionText) {
|
public VariableCostImpl(VariableCostType costType, String xText, String actionText) {
|
||||||
id = UUID.randomUUID();
|
this.id = UUID.randomUUID();
|
||||||
paid = false;
|
this.costType = costType;
|
||||||
targets = new Targets();
|
this.paid = false;
|
||||||
amountPaid = 0;
|
this.targets = new Targets();
|
||||||
|
this.amountPaid = 0;
|
||||||
this.xText = xText;
|
this.xText = xText;
|
||||||
this.actionText = actionText;
|
this.actionText = actionText;
|
||||||
}
|
}
|
||||||
|
|
||||||
public VariableCostImpl(final VariableCostImpl cost) {
|
public VariableCostImpl(final VariableCostImpl cost) {
|
||||||
this.id = cost.id;
|
this.id = cost.id;
|
||||||
|
this.costType = cost.costType;
|
||||||
this.text = cost.text;
|
this.text = cost.text;
|
||||||
this.paid = cost.paid;
|
this.paid = cost.paid;
|
||||||
this.targets = cost.targets.copy();
|
this.targets = cost.targets.copy();
|
||||||
|
@ -107,14 +110,12 @@ public abstract class VariableCostImpl implements Cost, VariableCost {
|
||||||
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
||||||
return true;
|
return true;
|
||||||
/* not used */
|
/* not used */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
|
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||||
return true;
|
return true;
|
||||||
/* not used */
|
/* not used */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -150,4 +151,14 @@ public abstract class VariableCostImpl implements Cost, VariableCost {
|
||||||
}
|
}
|
||||||
return xValue;
|
return xValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VariableCostType getCostType() {
|
||||||
|
return this.costType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCostType(VariableCostType costType) {
|
||||||
|
this.costType = costType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package mage.abilities.costs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See rules 601.2b
|
||||||
|
*
|
||||||
|
* @author JayDi85
|
||||||
|
*/
|
||||||
|
public enum VariableCostType {
|
||||||
|
|
||||||
|
NORMAL(false),
|
||||||
|
ALTERNATIVE(false),
|
||||||
|
ADDITIONAL(true);
|
||||||
|
|
||||||
|
// allows announcing X value on free cast (noMana) for additional costs, example: Kicker X
|
||||||
|
private final boolean canUseAnnounceOnFreeCast;
|
||||||
|
|
||||||
|
VariableCostType(boolean canUseAnnounceOnFreeCast) {
|
||||||
|
this.canUseAnnounceOnFreeCast = canUseAnnounceOnFreeCast;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canUseAnnounceOnFreeCast() {
|
||||||
|
return this.canUseAnnounceOnFreeCast;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ package mage.abilities.costs.common;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.VariableCostImpl;
|
import mage.abilities.costs.VariableCostImpl;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.filter.FilterCard;
|
import mage.filter.FilterCard;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
@ -19,9 +20,10 @@ public class DiscardXTargetCost extends VariableCostImpl {
|
||||||
this(filter, false);
|
this(filter, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DiscardXTargetCost(FilterCard filter, boolean additionalCostText) {
|
public DiscardXTargetCost(FilterCard filter, boolean useAsAdditionalCost) {
|
||||||
super(filter.getMessage() + " to discard");
|
super(useAsAdditionalCost ? VariableCostType.ADDITIONAL : VariableCostType.NORMAL,
|
||||||
this.text = (additionalCostText ? "as an additional cost to cast this spell, discard " : "Discard ") + xText + ' ' + filter.getMessage();
|
filter.getMessage() + " to discard");
|
||||||
|
this.text = (useAsAdditionalCost ? "as an additional cost to cast this spell, discard " : "Discard ") + xText + ' ' + filter.getMessage();
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package mage.abilities.costs.common;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.CostImpl;
|
import mage.abilities.costs.CostImpl;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.abilities.costs.mana.VariableManaCost;
|
import mage.abilities.costs.mana.VariableManaCost;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.cards.Cards;
|
import mage.cards.Cards;
|
||||||
|
@ -23,7 +24,7 @@ import java.util.UUID;
|
||||||
public class ExileFromHandCost extends CostImpl {
|
public class ExileFromHandCost extends CostImpl {
|
||||||
|
|
||||||
List<Card> cards = new ArrayList<>();
|
List<Card> cards = new ArrayList<>();
|
||||||
private boolean setXFromCMC;
|
private final boolean setXFromCMC;
|
||||||
|
|
||||||
public ExileFromHandCost(TargetCardInHand target) {
|
public ExileFromHandCost(TargetCardInHand target) {
|
||||||
this(target, false);
|
this(target, false);
|
||||||
|
@ -32,7 +33,7 @@ public class ExileFromHandCost extends CostImpl {
|
||||||
/**
|
/**
|
||||||
* @param target
|
* @param target
|
||||||
* @param setXFromCMC the spells X value on the stack is set to the
|
* @param setXFromCMC the spells X value on the stack is set to the
|
||||||
* converted mana costs of the exiled card
|
* converted mana costs of the exiled card (alternative cost)
|
||||||
*/
|
*/
|
||||||
public ExileFromHandCost(TargetCardInHand target, boolean setXFromCMC) {
|
public ExileFromHandCost(TargetCardInHand target, boolean setXFromCMC) {
|
||||||
this.addTarget(target);
|
this.addTarget(target);
|
||||||
|
@ -66,9 +67,10 @@ public class ExileFromHandCost extends CostImpl {
|
||||||
player.moveCards(cardsToExile, Zone.EXILED, ability, game);
|
player.moveCards(cardsToExile, Zone.EXILED, ability, game);
|
||||||
paid = true;
|
paid = true;
|
||||||
if (setXFromCMC) {
|
if (setXFromCMC) {
|
||||||
VariableManaCost vmc = new VariableManaCost();
|
VariableManaCost vmc = new VariableManaCost(VariableCostType.ALTERNATIVE);
|
||||||
// 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.
|
||||||
|
// TODO: wtf, look at setXFromCMC usage -- it used in cards with alternative costs, not additional... need to fix?
|
||||||
vmc.setAmount(cmc, cmc, false);
|
vmc.setAmount(cmc, cmc, false);
|
||||||
vmc.setPaid();
|
vmc.setPaid();
|
||||||
ability.getManaCostsToPay().add(vmc);
|
ability.getManaCostsToPay().add(vmc);
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
|
|
||||||
package mage.abilities.costs.common;
|
package mage.abilities.costs.common;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.VariableCostImpl;
|
import mage.abilities.costs.VariableCostImpl;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.filter.FilterCard;
|
import mage.filter.FilterCard;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.target.common.TargetCardInYourGraveyard;
|
import mage.target.common.TargetCardInYourGraveyard;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
*/
|
*/
|
||||||
public class ExileXFromYourGraveCost extends VariableCostImpl {
|
public class ExileXFromYourGraveCost extends VariableCostImpl {
|
||||||
|
@ -21,10 +20,11 @@ public class ExileXFromYourGraveCost extends VariableCostImpl {
|
||||||
this(filter, false);
|
this(filter, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExileXFromYourGraveCost(FilterCard filter, boolean additionalCostText) {
|
public ExileXFromYourGraveCost(FilterCard filter, boolean useAsAdditionalCost) {
|
||||||
super(filter.getMessage() + " to exile");
|
super(useAsAdditionalCost ? VariableCostType.ADDITIONAL : VariableCostType.NORMAL,
|
||||||
|
filter.getMessage() + " to exile");
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
this.text = (additionalCostText ? "as an additional cost to cast this spell, exile " : "Exile ") + xText + ' ' + filter.getMessage();
|
this.text = (useAsAdditionalCost ? "as an additional cost to cast this spell, exile " : "Exile ") + xText + ' ' + filter.getMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExileXFromYourGraveCost(final ExileXFromYourGraveCost cost) {
|
public ExileXFromYourGraveCost(final ExileXFromYourGraveCost cost) {
|
||||||
|
|
|
@ -3,11 +3,11 @@ package mage.abilities.costs.common;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.VariableCostImpl;
|
import mage.abilities.costs.VariableCostImpl;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
*/
|
*/
|
||||||
public class PayVariableLifeCost extends VariableCostImpl {
|
public class PayVariableLifeCost extends VariableCostImpl {
|
||||||
|
@ -16,9 +16,10 @@ public class PayVariableLifeCost extends VariableCostImpl {
|
||||||
this(false);
|
this(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PayVariableLifeCost(boolean additionalCostText) {
|
public PayVariableLifeCost(boolean useAsAdditionalCost) {
|
||||||
super("life to pay");
|
super(useAsAdditionalCost ? VariableCostType.ADDITIONAL : VariableCostType.NORMAL,
|
||||||
this.text = new StringBuilder(additionalCostText ? "as an additional cost to cast this spell, pay " : "Pay ")
|
"life to pay");
|
||||||
|
this.text = new StringBuilder(useAsAdditionalCost ? "as an additional cost to cast this spell, pay " : "Pay ")
|
||||||
.append(xText).append(' ').append("life").toString();
|
.append(xText).append(' ').append("life").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import mage.abilities.Ability;
|
||||||
import mage.abilities.LoyaltyAbility;
|
import mage.abilities.LoyaltyAbility;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.VariableCostImpl;
|
import mage.abilities.costs.VariableCostImpl;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
|
@ -24,7 +25,7 @@ public class PayVariableLoyaltyCost extends VariableCostImpl {
|
||||||
private int costModification = 0;
|
private int costModification = 0;
|
||||||
|
|
||||||
public PayVariableLoyaltyCost() {
|
public PayVariableLoyaltyCost() {
|
||||||
super("loyality counters to remove");
|
super(VariableCostType.NORMAL, "loyality counters to remove");
|
||||||
this.text = "-X";
|
this.text = "-X";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,20 @@
|
||||||
|
|
||||||
package mage.abilities.costs.common;
|
package mage.abilities.costs.common;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.VariableCostImpl;
|
import mage.abilities.costs.VariableCostImpl;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.counters.Counter;
|
import mage.counters.Counter;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
*/
|
*/
|
||||||
public class RemoveVariableCountersSourceCost extends VariableCostImpl {
|
public class RemoveVariableCountersSourceCost extends VariableCostImpl {
|
||||||
|
|
||||||
protected int minimalCountersToPay = 0;
|
protected int minimalCountersToPay = 0;
|
||||||
private String counterName;
|
private final String counterName;
|
||||||
|
|
||||||
public RemoveVariableCountersSourceCost(Counter counter) {
|
public RemoveVariableCountersSourceCost(Counter counter) {
|
||||||
this(counter, 0);
|
this(counter, 0);
|
||||||
|
@ -30,7 +29,7 @@ public class RemoveVariableCountersSourceCost extends VariableCostImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public RemoveVariableCountersSourceCost(Counter counter, int minimalCountersToPay, String text) {
|
public RemoveVariableCountersSourceCost(Counter counter, int minimalCountersToPay, String text) {
|
||||||
super(counter.getName() + " counters to remove");
|
super(VariableCostType.NORMAL, counter.getName() + " counters to remove");
|
||||||
this.minimalCountersToPay = minimalCountersToPay;
|
this.minimalCountersToPay = minimalCountersToPay;
|
||||||
this.counterName = counter.getName();
|
this.counterName = counter.getName();
|
||||||
if (text == null || text.isEmpty()) {
|
if (text == null || text.isEmpty()) {
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
|
|
||||||
|
|
||||||
package mage.abilities.costs.common;
|
package mage.abilities.costs.common;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.VariableCostImpl;
|
import mage.abilities.costs.VariableCostImpl;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.counters.Counter;
|
import mage.counters.Counter;
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
import mage.filter.FilterPermanent;
|
import mage.filter.FilterPermanent;
|
||||||
|
@ -13,11 +11,12 @@ import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author LevelX
|
* @author LevelX
|
||||||
*/
|
*/
|
||||||
public class RemoveVariableCountersTargetCost extends VariableCostImpl {
|
public class RemoveVariableCountersTargetCost extends VariableCostImpl {
|
||||||
|
|
||||||
protected FilterPermanent filter;
|
protected FilterPermanent filter;
|
||||||
protected CounterType counterTypeToRemove;
|
protected CounterType counterTypeToRemove;
|
||||||
|
@ -32,7 +31,7 @@ public class RemoveVariableCountersTargetCost extends VariableCostImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public RemoveVariableCountersTargetCost(FilterPermanent filter, CounterType counterTypeToRemove, String xText, int minValue) {
|
public RemoveVariableCountersTargetCost(FilterPermanent filter, CounterType counterTypeToRemove, String xText, int minValue) {
|
||||||
super(xText, new StringBuilder(counterTypeToRemove != null ? counterTypeToRemove.getName() + ' ' :"").append("counters to remove").toString());
|
super(VariableCostType.NORMAL, xText, new StringBuilder(counterTypeToRemove != null ? counterTypeToRemove.getName() + ' ' : "").append("counters to remove").toString());
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
this.counterTypeToRemove = counterTypeToRemove;
|
this.counterTypeToRemove = counterTypeToRemove;
|
||||||
this.text = setText();
|
this.text = setText();
|
||||||
|
@ -67,11 +66,11 @@ public class RemoveVariableCountersTargetCost extends VariableCostImpl {
|
||||||
@Override
|
@Override
|
||||||
public int getMaxValue(Ability source, Game game) {
|
public int getMaxValue(Ability source, Game game) {
|
||||||
int maxValue = 0;
|
int maxValue = 0;
|
||||||
for (Permanent permanent :game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) {
|
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) {
|
||||||
if (counterTypeToRemove != null) {
|
if (counterTypeToRemove != null) {
|
||||||
maxValue += permanent.getCounters(game).getCount(counterTypeToRemove);
|
maxValue += permanent.getCounters(game).getCount(counterTypeToRemove);
|
||||||
} else {
|
} else {
|
||||||
for(Counter counter :permanent.getCounters(game).values()){
|
for (Counter counter : permanent.getCounters(game).values()) {
|
||||||
maxValue += counter.getCount();
|
maxValue += counter.getCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,7 +80,7 @@ public class RemoveVariableCountersTargetCost extends VariableCostImpl {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Cost getFixedCostsFromAnnouncedValue(int xValue) {
|
public Cost getFixedCostsFromAnnouncedValue(int xValue) {
|
||||||
return new RemoveCounterCost(new TargetPermanent(minValue,Integer.MAX_VALUE, filter, true), counterTypeToRemove, xValue);
|
return new RemoveCounterCost(new TargetPermanent(minValue, Integer.MAX_VALUE, filter, true), counterTypeToRemove, xValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
|
|
||||||
package mage.abilities.costs.common;
|
package mage.abilities.costs.common;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.VariableCostImpl;
|
import mage.abilities.costs.VariableCostImpl;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.filter.common.FilterControlledPermanent;
|
import mage.filter.common.FilterControlledPermanent;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.target.common.TargetControlledPermanent;
|
import mage.target.common.TargetControlledPermanent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
*/
|
*/
|
||||||
public class SacrificeXTargetCost extends VariableCostImpl {
|
public class SacrificeXTargetCost extends VariableCostImpl {
|
||||||
|
@ -20,9 +19,10 @@ public class SacrificeXTargetCost extends VariableCostImpl {
|
||||||
this(filter, false);
|
this(filter, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SacrificeXTargetCost(FilterControlledPermanent filter, boolean additionalCostText) {
|
public SacrificeXTargetCost(FilterControlledPermanent filter, boolean useAsAdditionalCost) {
|
||||||
super(filter.getMessage() + " to sacrifice");
|
super(useAsAdditionalCost ? VariableCostType.ADDITIONAL : VariableCostType.NORMAL,
|
||||||
this.text = (additionalCostText ? "as an additional cost to cast this spell, sacrifice " : "Sacrifice ") + xText + ' ' + filter.getMessage();
|
filter.getMessage() + " to sacrifice");
|
||||||
|
this.text = (useAsAdditionalCost ? "as an additional cost to cast this spell, sacrifice " : "Sacrifice ") + xText + ' ' + filter.getMessage();
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
|
|
||||||
|
|
||||||
package mage.abilities.costs.common;
|
package mage.abilities.costs.common;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.VariableCostImpl;
|
import mage.abilities.costs.VariableCostImpl;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.filter.common.FilterControlledPermanent;
|
import mage.filter.common.FilterControlledPermanent;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.target.common.TargetControlledPermanent;
|
import mage.target.common.TargetControlledPermanent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public class TapVariableTargetCost extends VariableCostImpl {
|
public class TapVariableTargetCost extends VariableCostImpl {
|
||||||
|
|
||||||
protected FilterControlledPermanent filter;
|
protected FilterControlledPermanent filter;
|
||||||
|
|
||||||
|
@ -21,10 +19,11 @@ public class TapVariableTargetCost extends VariableCostImpl {
|
||||||
this(filter, false, "X");
|
this(filter, false, "X");
|
||||||
}
|
}
|
||||||
|
|
||||||
public TapVariableTargetCost(FilterControlledPermanent filter, boolean additionalCostText, String xText) {
|
public TapVariableTargetCost(FilterControlledPermanent filter, boolean useAsAdditionalCost, String xText) {
|
||||||
super(xText, new StringBuilder(filter.getMessage()).append(" to tap").toString());
|
super(useAsAdditionalCost ? VariableCostType.ADDITIONAL : VariableCostType.NORMAL,
|
||||||
|
xText, new StringBuilder(filter.getMessage()).append(" to tap").toString());
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
this.text = new StringBuilder(additionalCostText ? "as an additional cost to cast this spell, tap ":"Tap ")
|
this.text = new StringBuilder(useAsAdditionalCost ? "as an additional cost to cast this spell, tap " : "Tap ")
|
||||||
.append(this.xText).append(' ').append(filter.getMessage()).toString();
|
.append(this.xText).append(' ').append(filter.getMessage()).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,7 @@ package mage.abilities.costs.mana;
|
||||||
|
|
||||||
import mage.Mana;
|
import mage.Mana;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.*;
|
||||||
import mage.abilities.costs.Costs;
|
|
||||||
import mage.abilities.costs.CostsImpl;
|
|
||||||
import mage.abilities.costs.VariableCost;
|
|
||||||
import mage.abilities.costs.common.PayLifeCost;
|
import mage.abilities.costs.common.PayLifeCost;
|
||||||
import mage.abilities.mana.ManaOptions;
|
import mage.abilities.mana.ManaOptions;
|
||||||
import mage.constants.ColoredManaSymbol;
|
import mage.constants.ColoredManaSymbol;
|
||||||
|
@ -32,7 +29,7 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
|
||||||
protected final UUID id;
|
protected final UUID id;
|
||||||
protected String text = null;
|
protected String text = null;
|
||||||
|
|
||||||
private static Map<String, ManaCosts> costsCache = new ConcurrentHashMap<>(); // must be thread safe, can't use nulls
|
private static final Map<String, ManaCosts> costsCache = new ConcurrentHashMap<>(); // must be thread safe, can't use nulls
|
||||||
|
|
||||||
public ManaCostsImpl() {
|
public ManaCostsImpl() {
|
||||||
this.id = UUID.randomUUID();
|
this.id = UUID.randomUUID();
|
||||||
|
@ -471,7 +468,7 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
|
||||||
modifierForX++;
|
modifierForX++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.add(new VariableManaCost(modifierForX));
|
this.add(new VariableManaCost(VariableCostType.NORMAL, modifierForX));
|
||||||
} //TODO: handle multiple {X} and/or {Y} symbols
|
} //TODO: handle multiple {X} and/or {Y} symbols
|
||||||
} else if (Character.isDigit(symbol.charAt(0))) {
|
} else if (Character.isDigit(symbol.charAt(0))) {
|
||||||
MonoHybridManaCost cost;
|
MonoHybridManaCost cost;
|
||||||
|
|
|
@ -4,6 +4,7 @@ import mage.Mana;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.VariableCost;
|
import mage.abilities.costs.VariableCost;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.constants.ColoredManaSymbol;
|
import mage.constants.ColoredManaSymbol;
|
||||||
import mage.filter.FilterMana;
|
import mage.filter.FilterMana;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
@ -18,6 +19,7 @@ public final class VariableManaCost extends ManaCostImpl implements VariableCost
|
||||||
// 1. as X value in spell/ability cast (announce X, set VariableManaCost as paid and add generic mana to pay instead)
|
// 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)
|
// 2. as X value in direct pay (X already announced, cost is unpaid, need direct pay)
|
||||||
|
|
||||||
|
protected VariableCostType costType;
|
||||||
protected int xInstancesCount; // number of {X} instances in cost like {X} or {X}{X}
|
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 int xPay = 0; // final/total need pay after announce and replace events (example: {X}{X}, X=3, xPay = 6)
|
protected int xPay = 0; // final/total need pay after announce and replace events (example: {X}{X}, X=3, xPay = 6)
|
||||||
|
@ -27,11 +29,12 @@ public final class VariableManaCost extends ManaCostImpl implements VariableCost
|
||||||
protected int minX = 0;
|
protected int minX = 0;
|
||||||
protected int maxX = Integer.MAX_VALUE;
|
protected int maxX = Integer.MAX_VALUE;
|
||||||
|
|
||||||
public VariableManaCost() {
|
public VariableManaCost(VariableCostType costType) {
|
||||||
this(1);
|
this(costType, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public VariableManaCost(int xInstancesCount) {
|
public VariableManaCost(VariableCostType costType, int xInstancesCount) {
|
||||||
|
this.costType = costType;
|
||||||
this.xInstancesCount = xInstancesCount;
|
this.xInstancesCount = xInstancesCount;
|
||||||
this.cost = new Mana();
|
this.cost = new Mana();
|
||||||
options.add(new Mana());
|
options.add(new Mana());
|
||||||
|
@ -39,6 +42,7 @@ public final class VariableManaCost extends ManaCostImpl implements VariableCost
|
||||||
|
|
||||||
public VariableManaCost(final VariableManaCost manaCost) {
|
public VariableManaCost(final VariableManaCost manaCost) {
|
||||||
super(manaCost);
|
super(manaCost);
|
||||||
|
this.costType = manaCost.costType;
|
||||||
this.xInstancesCount = manaCost.xInstancesCount;
|
this.xInstancesCount = manaCost.xInstancesCount;
|
||||||
this.xValue = manaCost.xValue;
|
this.xValue = manaCost.xValue;
|
||||||
this.xPay = manaCost.xPay;
|
this.xPay = manaCost.xPay;
|
||||||
|
@ -171,4 +175,14 @@ public final class VariableManaCost extends ManaCostImpl implements VariableCost
|
||||||
public void setFilter(FilterMana filter) {
|
public void setFilter(FilterMana filter) {
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VariableCostType getCostType() {
|
||||||
|
return this.costType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCostType(VariableCostType costType) {
|
||||||
|
this.costType = costType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,25 +36,31 @@ public class BuybackAbility extends StaticAbility implements OptionalAdditionalS
|
||||||
private static final String keywordText = "Buyback";
|
private static final String keywordText = "Buyback";
|
||||||
private static final String reminderTextCost = "You may {cost} in addition to any other costs as you cast this spell. If you do, put this card into your hand as it resolves.";
|
private static final String reminderTextCost = "You may {cost} in addition to any other costs as you cast this spell. If you do, put this card into your hand as it resolves.";
|
||||||
private static final String reminderTextMana = "You may pay an additional {cost} as you cast this spell. If you do, put this card into your hand as it resolves.";
|
private static final String reminderTextMana = "You may pay an additional {cost} as you cast this spell. If you do, put this card into your hand as it resolves.";
|
||||||
|
|
||||||
protected OptionalAdditionalCost buybackCost;
|
protected OptionalAdditionalCost buybackCost;
|
||||||
private int amountToReduceBy = 0;
|
private int amountToReduceBy = 0;
|
||||||
|
|
||||||
public BuybackAbility(String manaString) {
|
public BuybackAbility(String manaString) {
|
||||||
super(Zone.STACK, new BuybackEffect());
|
super(Zone.STACK, new BuybackEffect());
|
||||||
this.buybackCost = new OptionalAdditionalCostImpl(keywordText, reminderTextMana, new ManaCostsImpl(manaString));
|
addBuybackCostAndSetup(new OptionalAdditionalCostImpl(keywordText, reminderTextMana, new ManaCostsImpl(manaString)));
|
||||||
setRuleAtTheTop(true);
|
setRuleAtTheTop(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BuybackAbility(Cost cost) {
|
public BuybackAbility(Cost cost) {
|
||||||
super(Zone.STACK, new BuybackEffect());
|
super(Zone.STACK, new BuybackEffect());
|
||||||
this.buybackCost = new OptionalAdditionalCostImpl(keywordText, "—", reminderTextCost, cost);
|
addBuybackCostAndSetup(new OptionalAdditionalCostImpl(keywordText, "—", reminderTextCost, cost));
|
||||||
setRuleAtTheTop(true);
|
setRuleAtTheTop(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addBuybackCostAndSetup(OptionalAdditionalCost newCost) {
|
||||||
|
this.buybackCost = newCost;
|
||||||
|
this.buybackCost.setCostType(VariableCostType.ADDITIONAL);
|
||||||
|
}
|
||||||
|
|
||||||
public BuybackAbility(final BuybackAbility ability) {
|
public BuybackAbility(final BuybackAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
buybackCost = new OptionalAdditionalCostImpl((OptionalAdditionalCostImpl) ability.buybackCost);
|
this.buybackCost = ability.buybackCost.copy();
|
||||||
amountToReduceBy = ability.amountToReduceBy;
|
this.amountToReduceBy = ability.amountToReduceBy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -4,11 +4,9 @@ import mage.abilities.Ability;
|
||||||
import mage.abilities.SpellAbility;
|
import mage.abilities.SpellAbility;
|
||||||
import mage.abilities.StaticAbility;
|
import mage.abilities.StaticAbility;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.TriggeredAbilityImpl;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.*;
|
||||||
import mage.abilities.costs.Costs;
|
|
||||||
import mage.abilities.costs.OptionalAdditionalCostImpl;
|
|
||||||
import mage.abilities.costs.OptionalAdditionalSourceCosts;
|
|
||||||
import mage.abilities.costs.common.TapTargetCost;
|
import mage.abilities.costs.common.TapTargetCost;
|
||||||
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
|
@ -62,9 +60,9 @@ public class ConspireAbility extends StaticAbility implements OptionalAdditional
|
||||||
MORE
|
MORE
|
||||||
}
|
}
|
||||||
|
|
||||||
private UUID conspireId;
|
private final UUID conspireId;
|
||||||
private String reminderText;
|
private String reminderText;
|
||||||
private OptionalAdditionalCostImpl conspireCost;
|
private OptionalAdditionalCost conspireCost;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unique Id for a ConspireAbility but may not change while a continuous
|
* Unique Id for a ConspireAbility but may not change while a continuous
|
||||||
|
@ -87,12 +85,19 @@ public class ConspireAbility extends StaticAbility implements OptionalAdditional
|
||||||
reminderText = "As you cast this spell, you may tap two untapped creatures you control that share a color with it. When you do, copy it and you may choose new targets for the copy.";
|
reminderText = "As you cast this spell, you may tap two untapped creatures you control that share a color with it. When you do, copy it and you may choose new targets for the copy.";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cost cost = new TapTargetCost(new TargetControlledPermanent(2, 2, filter, true));
|
Cost cost = new TapTargetCost(new TargetControlledPermanent(2, 2, filter, true));
|
||||||
cost.setText("");
|
cost.setText("");
|
||||||
conspireCost = new OptionalAdditionalCostImpl(keywordText, " ", reminderText, cost);
|
addConspireCostAndSetup(new OptionalAdditionalCostImpl(keywordText, " ", reminderText, cost));
|
||||||
|
|
||||||
addSubAbility(new ConspireTriggeredAbility(conspireId));
|
addSubAbility(new ConspireTriggeredAbility(conspireId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addConspireCostAndSetup(OptionalAdditionalCost newCost) {
|
||||||
|
this.conspireCost = newCost;
|
||||||
|
this.conspireCost.setCostType(VariableCostType.ADDITIONAL);
|
||||||
|
}
|
||||||
|
|
||||||
public ConspireAbility(final ConspireAbility ability) {
|
public ConspireAbility(final ConspireAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
this.conspireId = ability.conspireId;
|
this.conspireId = ability.conspireId;
|
||||||
|
@ -139,9 +144,13 @@ public class ConspireAbility extends StaticAbility implements OptionalAdditional
|
||||||
if (conspireCost.canPay(ability, this, getControllerId(), game)
|
if (conspireCost.canPay(ability, this, getControllerId(), game)
|
||||||
&& player.chooseUse(Outcome.Benefit, "Pay " + conspireCost.getText(false) + " ?", ability, game)) {
|
&& player.chooseUse(Outcome.Benefit, "Pay " + conspireCost.getText(false) + " ?", ability, game)) {
|
||||||
activateConspire(ability, game);
|
activateConspire(ability, game);
|
||||||
for (Iterator it = conspireCost.iterator(); it.hasNext(); ) {
|
for (Iterator it = ((Costs) conspireCost).iterator(); it.hasNext(); ) {
|
||||||
Cost cost = (Cost) it.next();
|
Cost cost = (Cost) it.next();
|
||||||
ability.getCosts().add(cost.copy());
|
if (cost instanceof ManaCostsImpl) {
|
||||||
|
ability.getManaCostsToPay().add((ManaCostsImpl) cost.copy());
|
||||||
|
} else {
|
||||||
|
ability.getCosts().add(cost.copy());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -194,7 +203,7 @@ public class ConspireAbility extends StaticAbility implements OptionalAdditional
|
||||||
|
|
||||||
class ConspireTriggeredAbility extends TriggeredAbilityImpl {
|
class ConspireTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
private UUID conspireId;
|
private final UUID conspireId;
|
||||||
|
|
||||||
public ConspireTriggeredAbility(UUID conspireId) {
|
public ConspireTriggeredAbility(UUID conspireId) {
|
||||||
super(Zone.STACK, new ConspireEffect());
|
super(Zone.STACK, new ConspireEffect());
|
||||||
|
|
|
@ -3,10 +3,7 @@ package mage.abilities.keyword;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.SpellAbility;
|
import mage.abilities.SpellAbility;
|
||||||
import mage.abilities.StaticAbility;
|
import mage.abilities.StaticAbility;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.*;
|
||||||
import mage.abilities.costs.OptionalAdditionalCost;
|
|
||||||
import mage.abilities.costs.OptionalAdditionalCostImpl;
|
|
||||||
import mage.abilities.costs.OptionalAdditionalModeSourceCosts;
|
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
|
@ -14,6 +11,7 @@ import mage.game.Game;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,12 +33,12 @@ public class EntwineAbility extends StaticAbility implements OptionalAdditionalM
|
||||||
private static final String keywordText = "Entwine";
|
private static final String keywordText = "Entwine";
|
||||||
protected static final String reminderText = "You may {cost} in addition to any other costs to use all modes.";
|
protected static final String reminderText = "You may {cost} in addition to any other costs to use all modes.";
|
||||||
|
|
||||||
protected OptionalAdditionalCost additionalCost;
|
protected OptionalAdditionalCost entwineCost;
|
||||||
protected Set<String> activations = new HashSet<>(); // same logic as KickerAbility: activations per zoneChangeCounter
|
protected Set<String> activations = new HashSet<>(); // same logic as KickerAbility: activations per zoneChangeCounter
|
||||||
|
|
||||||
public EntwineAbility(String manaString) {
|
public EntwineAbility(String manaString) {
|
||||||
super(Zone.STACK, null);
|
super(Zone.STACK, null);
|
||||||
this.additionalCost = new OptionalAdditionalCostImpl(keywordText, reminderText, new ManaCostsImpl(manaString));
|
addEntwineCostAndSetup(new OptionalAdditionalCostImpl(keywordText, reminderText, new ManaCostsImpl(manaString)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public EntwineAbility(Cost cost) {
|
public EntwineAbility(Cost cost) {
|
||||||
|
@ -49,14 +47,20 @@ public class EntwineAbility extends StaticAbility implements OptionalAdditionalM
|
||||||
|
|
||||||
public EntwineAbility(Cost cost, String reminderText) {
|
public EntwineAbility(Cost cost, String reminderText) {
|
||||||
super(Zone.STACK, null);
|
super(Zone.STACK, null);
|
||||||
this.additionalCost = new OptionalAdditionalCostImpl(keywordText, "—", reminderText, cost);
|
|
||||||
|
addEntwineCostAndSetup(new OptionalAdditionalCostImpl(keywordText, "—", reminderText, cost));
|
||||||
setRuleAtTheTop(true);
|
setRuleAtTheTop(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addEntwineCostAndSetup(OptionalAdditionalCost newCost) {
|
||||||
|
this.entwineCost = newCost;
|
||||||
|
this.entwineCost.setCostType(VariableCostType.ADDITIONAL);
|
||||||
|
}
|
||||||
|
|
||||||
public EntwineAbility(final EntwineAbility ability) {
|
public EntwineAbility(final EntwineAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
if (ability.additionalCost != null) {
|
if (ability.entwineCost != null) {
|
||||||
this.additionalCost = ability.additionalCost.copy();
|
this.entwineCost = ability.entwineCost.copy();
|
||||||
}
|
}
|
||||||
this.activations.addAll(ability.activations);
|
this.activations.addAll(ability.activations);
|
||||||
}
|
}
|
||||||
|
@ -77,32 +81,40 @@ public class EntwineAbility extends StaticAbility implements OptionalAdditionalM
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.resetCosts(game, ability);
|
this.resetEntwine(game, ability);
|
||||||
if (additionalCost == null) {
|
if (entwineCost == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (additionalCost.canPay(ability, this, ability.getControllerId(), game)
|
// AI can use it
|
||||||
&& player.chooseUse(Outcome.Benefit, "Pay " + additionalCost.getText(false) + " ?", ability, game)) {
|
if (entwineCost.canPay(ability, this, ability.getControllerId(), game)
|
||||||
addCostsToAbility(additionalCost, ability);
|
&& player.chooseUse(Outcome.Benefit, "Pay " + entwineCost.getText(false) + " ?", ability, game)) {
|
||||||
activateCost(game, ability);
|
for (Iterator it = ((Costs) entwineCost).iterator(); it.hasNext(); ) {
|
||||||
|
Cost cost = (Cost) it.next();
|
||||||
|
if (cost instanceof ManaCostsImpl) {
|
||||||
|
ability.getManaCostsToPay().add((ManaCostsImpl) cost.copy());
|
||||||
|
} else {
|
||||||
|
ability.getCosts().add(cost.copy());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
activateEntwine(game, ability);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRule() {
|
public String getRule() {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
if (additionalCost != null) {
|
if (entwineCost != null) {
|
||||||
sb.append(additionalCost.getText(false));
|
sb.append(entwineCost.getText(false));
|
||||||
sb.append(' ').append(additionalCost.getReminderText());
|
sb.append(' ').append(entwineCost.getReminderText());
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCastMessageSuffix() {
|
public String getCastMessageSuffix() {
|
||||||
if (additionalCost != null) {
|
if (entwineCost != null) {
|
||||||
return additionalCost.getCastSuffixMessage(0);
|
return entwineCost.getCastSuffixMessage(0);
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -119,20 +131,16 @@ public class EntwineAbility extends StaticAbility implements OptionalAdditionalM
|
||||||
ability.getModes().setMaxModes(maxModes);
|
ability.getModes().setMaxModes(maxModes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCostsToAbility(Cost cost, Ability ability) {
|
private void resetEntwine(Game game, Ability source) {
|
||||||
ability.addCost(cost.copy());
|
if (entwineCost != null) {
|
||||||
}
|
entwineCost.reset();
|
||||||
|
|
||||||
private void resetCosts(Game game, Ability source) {
|
|
||||||
if (additionalCost != null) {
|
|
||||||
additionalCost.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String key = getActivationKey(source, game);
|
String key = getActivationKey(source, game);
|
||||||
this.activations.remove(key);
|
this.activations.remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void activateCost(Game game, Ability source) {
|
private void activateEntwine(Game game, Ability source) {
|
||||||
String key = getActivationKey(source, game);
|
String key = getActivationKey(source, game);
|
||||||
this.activations.add(key);
|
this.activations.add(key);
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,17 +95,24 @@ public class KickerAbility extends StaticAbility implements OptionalAdditionalSo
|
||||||
}
|
}
|
||||||
|
|
||||||
public final OptionalAdditionalCost addKickerCost(String manaString) {
|
public final OptionalAdditionalCost addKickerCost(String manaString) {
|
||||||
OptionalAdditionalCost kickerCost = new OptionalAdditionalCostImpl(
|
OptionalAdditionalCost newCost = new OptionalAdditionalCostImpl(
|
||||||
keywordText, reminderText, new ManaCostsImpl(manaString));
|
keywordText, reminderText, new ManaCostsImpl(manaString));
|
||||||
kickerCosts.add(kickerCost);
|
addKickerCostAndSetup(newCost);
|
||||||
return kickerCost;
|
return newCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final OptionalAdditionalCost addKickerCost(Cost cost) {
|
public final OptionalAdditionalCost addKickerCost(Cost cost) {
|
||||||
OptionalAdditionalCost kickerCost = new OptionalAdditionalCostImpl(
|
OptionalAdditionalCost newCost = new OptionalAdditionalCostImpl(
|
||||||
keywordText, "-", reminderText, cost);
|
keywordText, "-", reminderText, cost);
|
||||||
kickerCosts.add(kickerCost);
|
addKickerCostAndSetup(newCost);
|
||||||
return kickerCost;
|
return newCost;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addKickerCostAndSetup(OptionalAdditionalCost newCost) {
|
||||||
|
this.kickerCosts.add(newCost);
|
||||||
|
this.kickerCosts.forEach(cost -> {
|
||||||
|
cost.setCostType(VariableCostType.ADDITIONAL);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resetKicker(Game game, Ability source) {
|
public void resetKicker(Game game, Ability source) {
|
||||||
|
@ -250,6 +257,7 @@ public class KickerAbility extends StaticAbility implements OptionalAdditionalSo
|
||||||
"Pay " + times + kickerCost.getText(false) + " ?", ability, game)) {
|
"Pay " + times + kickerCost.getText(false) + " ?", ability, game)) {
|
||||||
this.activateKicker(kickerCost, ability, game);
|
this.activateKicker(kickerCost, ability, game);
|
||||||
if (kickerCost instanceof Costs) {
|
if (kickerCost instanceof Costs) {
|
||||||
|
// as multiple costs
|
||||||
for (Iterator itKickerCost = ((Costs) kickerCost).iterator(); itKickerCost.hasNext(); ) {
|
for (Iterator itKickerCost = ((Costs) kickerCost).iterator(); itKickerCost.hasNext(); ) {
|
||||||
Object kickerCostObject = itKickerCost.next();
|
Object kickerCostObject = itKickerCost.next();
|
||||||
if ((kickerCostObject instanceof Costs)) {
|
if ((kickerCostObject instanceof Costs)) {
|
||||||
|
@ -262,6 +270,7 @@ public class KickerAbility extends StaticAbility implements OptionalAdditionalSo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// as single cost
|
||||||
addKickerCostsToAbility(kickerCost, ability, game);
|
addKickerCostsToAbility(kickerCost, ability, game);
|
||||||
}
|
}
|
||||||
again = kickerCost.isRepeatable();
|
again = kickerCost.isRepeatable();
|
||||||
|
@ -275,7 +284,8 @@ public class KickerAbility extends StaticAbility implements OptionalAdditionalSo
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addKickerCostsToAbility(Cost cost, Ability ability, Game game) {
|
private void addKickerCostsToAbility(Cost cost, Ability ability, Game game) {
|
||||||
// can contains multiple costs from multikicker ability
|
// can contain multiple costs from multikicker ability
|
||||||
|
// must be additional cost type
|
||||||
if (cost instanceof ManaCostsImpl) {
|
if (cost instanceof ManaCostsImpl) {
|
||||||
ability.getManaCostsToPay().add((ManaCostsImpl) cost.copy());
|
ability.getManaCostsToPay().add((ManaCostsImpl) cost.copy());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
package mage.abilities.keyword;
|
package mage.abilities.keyword;
|
||||||
|
|
||||||
|
import mage.ApprovingObject;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.SpecialAction;
|
import mage.abilities.SpecialAction;
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.TriggeredAbilityImpl;
|
||||||
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
||||||
import mage.abilities.condition.common.SuspendedCondition;
|
import mage.abilities.condition.common.SuspendedCondition;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.abilities.costs.mana.ManaCost;
|
import mage.abilities.costs.mana.ManaCost;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.abilities.costs.mana.VariableManaCost;
|
import mage.abilities.costs.mana.VariableManaCost;
|
||||||
|
@ -26,7 +28,6 @@ import mage.target.targetpointer.FixedTarget;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.ApprovingObject;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 502.59. Suspend
|
* 502.59. Suspend
|
||||||
|
@ -108,16 +109,16 @@ import mage.ApprovingObject;
|
||||||
*/
|
*/
|
||||||
public class SuspendAbility extends SpecialAction {
|
public class SuspendAbility extends SpecialAction {
|
||||||
|
|
||||||
private String ruleText;
|
private final String ruleText;
|
||||||
private boolean gainedTemporary;
|
private boolean gainedTemporary;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gives the card the SuspendAbility
|
* Gives the card the SuspendAbility
|
||||||
*
|
*
|
||||||
* @param suspend - amount of time counters, if Integer.MAX_VALUE is set
|
* @param suspend - amount of time counters, if Integer.MAX_VALUE is set
|
||||||
* there will be {X} costs and X counters added
|
* there will be {X} costs and X counters added
|
||||||
* @param cost - null is used for temporary gained suspend ability
|
* @param cost - null is used for temporary gained suspend ability
|
||||||
* @param card - card that has the suspend ability
|
* @param card - card that has the suspend ability
|
||||||
*/
|
*/
|
||||||
public SuspendAbility(int suspend, ManaCost cost, Card card) {
|
public SuspendAbility(int suspend, ManaCost cost, Card card) {
|
||||||
this(suspend, cost, card, false);
|
this(suspend, cost, card, false);
|
||||||
|
@ -129,7 +130,7 @@ public class SuspendAbility extends SpecialAction {
|
||||||
this.addEffect(new SuspendExileEffect(suspend));
|
this.addEffect(new SuspendExileEffect(suspend));
|
||||||
this.usesStack = false;
|
this.usesStack = false;
|
||||||
if (suspend == Integer.MAX_VALUE) {
|
if (suspend == Integer.MAX_VALUE) {
|
||||||
VariableManaCost xCosts = new VariableManaCost();
|
VariableManaCost xCosts = new VariableManaCost(VariableCostType.ALTERNATIVE);
|
||||||
xCosts.setMinX(1);
|
xCosts.setMinX(1);
|
||||||
this.addManaCost(xCosts);
|
this.addManaCost(xCosts);
|
||||||
cost = new ManaCostsImpl("{X}" + cost.getText());
|
cost = new ManaCostsImpl("{X}" + cost.getText());
|
||||||
|
@ -138,7 +139,7 @@ public class SuspendAbility extends SpecialAction {
|
||||||
if (cost != null) {
|
if (cost != null) {
|
||||||
sb.append(suspend == Integer.MAX_VALUE ? "X" : suspend).append("—")
|
sb.append(suspend == Integer.MAX_VALUE ? "X" : suspend).append("—")
|
||||||
.append(cost.getText()).append(suspend
|
.append(cost.getText()).append(suspend
|
||||||
== Integer.MAX_VALUE ? ". X can't be 0." : "");
|
== Integer.MAX_VALUE ? ". X can't be 0." : "");
|
||||||
if (!shortRule) {
|
if (!shortRule) {
|
||||||
sb.append(" <i>(Rather than cast this card from your hand, pay ")
|
sb.append(" <i>(Rather than cast this card from your hand, pay ")
|
||||||
.append(cost.getText())
|
.append(cost.getText())
|
||||||
|
@ -191,7 +192,7 @@ public class SuspendAbility extends SpecialAction {
|
||||||
UUID exileId = (UUID) game.getState().getValue("SuspendExileId" + controllerId.toString());
|
UUID exileId = (UUID) game.getState().getValue("SuspendExileId" + controllerId.toString());
|
||||||
if (exileId == null) {
|
if (exileId == null) {
|
||||||
exileId = UUID.randomUUID();
|
exileId = UUID.randomUUID();
|
||||||
game.getState().setValue("SuspendExileId" + controllerId.toString(), exileId);
|
game.getState().setValue("SuspendExileId" + controllerId, exileId);
|
||||||
}
|
}
|
||||||
return exileId;
|
return exileId;
|
||||||
}
|
}
|
||||||
|
@ -212,7 +213,7 @@ public class SuspendAbility extends SpecialAction {
|
||||||
return new ActivationStatus(object.isInstant(game)
|
return new ActivationStatus(object.isInstant(game)
|
||||||
|| object.hasAbility(FlashAbility.getInstance(), game)
|
|| object.hasAbility(FlashAbility.getInstance(), game)
|
||||||
|| null != game.getContinuousEffects().asThough(sourceId,
|
|| null != game.getContinuousEffects().asThough(sourceId,
|
||||||
AsThoughEffectType.CAST_AS_INSTANT, this, playerId, game)
|
AsThoughEffectType.CAST_AS_INSTANT, this, playerId, game)
|
||||||
|| game.canPlaySorcery(playerId), null);
|
|| game.canPlaySorcery(playerId), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,7 +307,7 @@ class SuspendPlayCardAbility extends TriggeredAbilityImpl {
|
||||||
@Override
|
@Override
|
||||||
public String getRule() {
|
public String getRule() {
|
||||||
return "When the last time counter is removed from this card ({this}), "
|
return "When the last time counter is removed from this card ({this}), "
|
||||||
+ "if it's removed from the game, " ;
|
+ "if it's removed from the game, ";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -428,7 +429,7 @@ class SuspendBeginningOfUpkeepInterveningIfTriggeredAbility extends ConditionalI
|
||||||
|
|
||||||
public SuspendBeginningOfUpkeepInterveningIfTriggeredAbility() {
|
public SuspendBeginningOfUpkeepInterveningIfTriggeredAbility() {
|
||||||
super(new BeginningOfUpkeepTriggeredAbility(Zone.EXILED, new RemoveCounterSourceEffect(CounterType.TIME.createInstance()),
|
super(new BeginningOfUpkeepTriggeredAbility(Zone.EXILED, new RemoveCounterSourceEffect(CounterType.TIME.createInstance()),
|
||||||
TargetController.YOU, false),
|
TargetController.YOU, false),
|
||||||
SuspendedCondition.instance,
|
SuspendedCondition.instance,
|
||||||
"At the beginning of your upkeep, if this card ({this}) is suspended, remove a time counter from it.");
|
"At the beginning of your upkeep, if this card ({this}) is suspended, remove a time counter from it.");
|
||||||
this.setRuleVisible(false);
|
this.setRuleVisible(false);
|
||||||
|
|
|
@ -2,6 +2,7 @@ package mage.game.command.emblems;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.LimitedTimesPerTurnActivatedAbility;
|
import mage.abilities.common.LimitedTimesPerTurnActivatedAbility;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.abilities.costs.common.DiscardCardCost;
|
import mage.abilities.costs.common.DiscardCardCost;
|
||||||
import mage.abilities.costs.mana.VariableManaCost;
|
import mage.abilities.costs.mana.VariableManaCost;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
@ -18,12 +19,12 @@ import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.command.Emblem;
|
import mage.game.command.Emblem;
|
||||||
import mage.game.permanent.token.EmptyToken;
|
import mage.game.permanent.token.EmptyToken;
|
||||||
|
import mage.game.permanent.token.Token;
|
||||||
|
import mage.game.permanent.token.custom.CreatureToken;
|
||||||
import mage.util.CardUtil;
|
import mage.util.CardUtil;
|
||||||
import mage.util.RandomUtil;
|
import mage.util.RandomUtil;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import mage.game.permanent.token.Token;
|
|
||||||
import mage.game.permanent.token.custom.CreatureToken;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author spjspj
|
* @author spjspj
|
||||||
|
@ -37,7 +38,7 @@ public final class MomirEmblem extends Emblem {
|
||||||
|
|
||||||
// {X}, Discard a card: Create a token that's a copy of a creature card with converted mana cost X chosen at random.
|
// {X}, Discard a card: Create a token that's a copy of a creature card with converted mana cost X chosen at random.
|
||||||
// Activate this ability only any time you could cast a sorcery and only once each turn.
|
// Activate this ability only any time you could cast a sorcery and only once each turn.
|
||||||
LimitedTimesPerTurnActivatedAbility ability = new LimitedTimesPerTurnActivatedAbility(Zone.COMMAND, new MomirEffect(), new VariableManaCost());
|
LimitedTimesPerTurnActivatedAbility ability = new LimitedTimesPerTurnActivatedAbility(Zone.COMMAND, new MomirEffect(), new VariableManaCost(VariableCostType.NORMAL));
|
||||||
ability.addCost(new DiscardCardCost());
|
ability.addCost(new DiscardCardCost());
|
||||||
ability.setTiming(TimingRule.SORCERY);
|
ability.setTiming(TimingRule.SORCERY);
|
||||||
this.getAbilities().add(ability);
|
this.getAbilities().add(ability);
|
||||||
|
@ -65,7 +66,7 @@ class MomirEffect extends OneShotEffect {
|
||||||
int value = source.getManaCostsToPay().getX();
|
int value = source.getManaCostsToPay().getX();
|
||||||
if (game.isSimulation()) {
|
if (game.isSimulation()) {
|
||||||
// Create dummy token to prevent multiple DB find cards what causes H2 java.lang.IllegalStateException if AI cancels calculation because of time out
|
// Create dummy token to prevent multiple DB find cards what causes H2 java.lang.IllegalStateException if AI cancels calculation because of time out
|
||||||
Token token = new CreatureToken(value, value +1);
|
Token token = new CreatureToken(value, value + 1);
|
||||||
token.putOntoBattlefield(1, game, source, source.getControllerId(), false, false);
|
token.putOntoBattlefield(1, game, source, source.getControllerId(), false, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import mage.ManaSymbol;
|
||||||
import mage.ObjectColor;
|
import mage.ObjectColor;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
|
import mage.abilities.costs.VariableCostType;
|
||||||
import mage.abilities.costs.common.TapSourceCost;
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
import mage.abilities.costs.mana.*;
|
import mage.abilities.costs.mana.*;
|
||||||
import mage.abilities.dynamicvalue.DynamicValue;
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
|
@ -648,7 +649,7 @@ public final class ManaUtil {
|
||||||
*/
|
*/
|
||||||
public static ManaCost createManaCost(int genericManaCount, boolean payAsX) {
|
public static ManaCost createManaCost(int genericManaCount, boolean payAsX) {
|
||||||
if (payAsX) {
|
if (payAsX) {
|
||||||
VariableManaCost xCost = new VariableManaCost();
|
VariableManaCost xCost = new VariableManaCost(VariableCostType.NORMAL);
|
||||||
xCost.setAmount(genericManaCount, genericManaCount, false);
|
xCost.setAmount(genericManaCount, genericManaCount, false);
|
||||||
return xCost;
|
return xCost;
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue