cleaned code from Shoal spells, solved problem that the shoal cards itself was counted as cards that can be used for ExileCardFromHandCost.

This commit is contained in:
LevelX2 2012-11-06 16:59:03 +01:00
parent 5856e69f84
commit 35f90e8b57
6 changed files with 127 additions and 269 deletions

View file

@ -27,28 +27,21 @@
*/
package mage.sets.betrayersofkamigawa;
import java.util.List;
import java.util.UUID;
import mage.Constants;
import mage.Constants.CardType;
import mage.Constants.Duration;
import mage.Constants.Rarity;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.costs.AlternativeCost;
import mage.abilities.costs.AlternativeCostImpl;
import mage.abilities.costs.Cost;
import mage.abilities.costs.Costs;
import mage.abilities.costs.common.ExileFromHandCost;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.ExileFromHandCostCardConvertedMana;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.continious.BoostTargetEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.filter.FilterCard;
import mage.filter.common.FilterOwnedCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardIdPredicate;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.other.OwnerPredicate;
import mage.game.Game;
import mage.target.common.TargetCardInHand;
import mage.target.common.TargetCreaturePermanent;
@ -59,12 +52,6 @@ import mage.target.common.TargetCreaturePermanent;
public class BlazingShoal extends CardImpl<BlazingShoal> {
private static final String ALTERNATIVE_COST_DESCRIPTION = "You may exile a red card with converted mana cost X from your hand rather than pay Blazing Shoal's mana cost";
private static final FilterCard filter = new FilterCard("red card from your hand");
static {
filter.add(new ColorPredicate(ObjectColor.RED));
filter.add(new OwnerPredicate(Constants.TargetController.YOU));
}
public BlazingShoal(UUID ownerId) {
super(ownerId, 96, "Blazing Shoal", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{X}{R}{R}");
@ -73,10 +60,13 @@ public class BlazingShoal extends CardImpl<BlazingShoal> {
this.color.setRed(true);
// You may exile a red card with converted mana cost X from your hand rather than pay Blazing Shoal's mana cost.
FilterOwnedCard filter = new FilterOwnedCard("red card from your hand");
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
this.getSpellAbility().addAlternativeCost(new AlternativeCostImpl(ALTERNATIVE_COST_DESCRIPTION, new ExileFromHandCost(new TargetCardInHand(filter))));
// Target creature gets +X/+0 until end of turn.
this.getSpellAbility().addEffect(new BoostTargetEffect(new BlazingShoalVariableValue(), new StaticValue(0), Duration.EndOfTurn));
this.getSpellAbility().addEffect(new BoostTargetEffect(new ExileFromHandCostCardConvertedMana(), new StaticValue(0), Duration.EndOfTurn));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
@ -89,41 +79,3 @@ public class BlazingShoal extends CardImpl<BlazingShoal> {
return new BlazingShoal(this);
}
}
class BlazingShoalVariableValue implements DynamicValue {
@Override
public int calculate(Game game, Ability sourceAbility) {
List<AlternativeCost> aCosts = sourceAbility.getAlternativeCosts();
for (AlternativeCost aCost: aCosts) {
if (aCost.isPaid()) {
Costs aCostsList = (Costs) aCost;
for (int x=0; x < aCostsList.size(); x++) {
Cost cost = (Cost) aCostsList.get(x);
if (cost instanceof ExileFromHandCost) {
int xMana = 0;
for (Card card : ((ExileFromHandCost) cost).getCards()) {
xMana += card.getManaCost().convertedManaCost();
}
return xMana;
}
}
}
}
return sourceAbility.getManaCostsToPay().getX();
}
@Override
public DynamicValue clone() {
return new BlazingShoalVariableValue();
}
@Override
public String toString() {
return "X";
}
@Override
public String getMessage() {
return "";
}
}

View file

@ -27,28 +27,23 @@
*/
package mage.sets.betrayersofkamigawa;
import java.util.List;
import java.util.UUID;
import mage.Constants;
import mage.Constants.CardType;
import mage.Constants.Outcome;
import mage.Constants.Rarity;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.costs.AlternativeCost;
import mage.abilities.costs.AlternativeCostImpl;
import mage.abilities.costs.Cost;
import mage.abilities.costs.Costs;
import mage.abilities.costs.common.ExileFromHandCost;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.ExileFromHandCostCardConvertedMana;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.filter.FilterCard;
import mage.filter.common.FilterOwnedCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardIdPredicate;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.other.OwnerIdPredicate;
import mage.filter.predicate.other.OwnerPredicate;
import mage.game.Game;
import mage.game.stack.Spell;
import mage.target.TargetSpell;
@ -61,12 +56,6 @@ import mage.target.common.TargetCardInHand;
public class DisruptingShoal extends CardImpl<DisruptingShoal> {
private static final String ALTERNATIVE_COST_DESCRIPTION = "You may exile a blue card with converted mana cost X from your hand rather than pay Disrupting Shoal's mana cost";
private static final FilterCard filter = new FilterCard("blue card from your hand");
static {
filter.add(new ColorPredicate(ObjectColor.BLUE));
filter.add(new OwnerPredicate(Constants.TargetController.YOU));
}
public DisruptingShoal(UUID ownerId) {
super(ownerId, 33, "Disrupting Shoal", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{X}{U}{U}");
@ -75,6 +64,9 @@ public class DisruptingShoal extends CardImpl<DisruptingShoal> {
this.color.setBlue(true);
// You may exile a blue card with converted mana cost X from your hand rather than pay Disrupting Shoal's mana cost.
FilterOwnedCard filter = new FilterOwnedCard("blue card from your hand");
filter.add(new ColorPredicate(ObjectColor.BLUE));
filter.add(Predicates.not(new CardIdPredicate(this.getId()))); // the exile cost can never be paid with the card itself
this.getSpellAbility().addAlternativeCost(new AlternativeCostImpl(ALTERNATIVE_COST_DESCRIPTION, new ExileFromHandCost(new TargetCardInHand(filter))));
// 2/1/2005: Disrupting Shoal can target any spell, but does nothing unless that spell's converted mana cost is X.
@ -92,42 +84,6 @@ public class DisruptingShoal extends CardImpl<DisruptingShoal> {
return new DisruptingShoal(this);
}
}
// ConvertedManaExileFromHandOrVariableManaValue
class DisruptingShoalVariableValue implements DynamicValue {
@Override
public int calculate(Game game, Ability sourceAbility) {
for (AlternativeCost aCost: (List<AlternativeCost>) sourceAbility.getAlternativeCosts()) {
if (aCost.isPaid()) {
for (int x=0; x < ((Costs) aCost).size(); x++) {
Cost cost = (Cost) ((Costs) aCost).get(x);
if (cost instanceof ExileFromHandCost) {
int xValue = 0;
for (Card card : ((ExileFromHandCost) cost).getCards()) {
xValue += card.getManaCost().convertedManaCost();
}
return xValue;
}
}
}
}
return sourceAbility.getManaCostsToPay().getX();
}
@Override
public DynamicValue clone() {
return new DisruptingShoalVariableValue();
}
@Override
public String toString() {
return "X";
}
@Override
public String getMessage() {
return "";
}
}
class DisruptingShoalCounterTargetEffect extends OneShotEffect<DisruptingShoalCounterTargetEffect> {
@ -146,7 +102,7 @@ class DisruptingShoalCounterTargetEffect extends OneShotEffect<DisruptingShoalCo
@Override
public boolean apply(Game game, Ability source) {
DynamicValue amount = new DisruptingShoalVariableValue();
DynamicValue amount = new ExileFromHandCostCardConvertedMana();
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
if (spell != null && spell.getManaCost().convertedManaCost() == amount.calculate(game, source)) {
return game.getStack().counter(source.getFirstTarget(), source.getSourceId(), game);

View file

@ -27,26 +27,19 @@
*/
package mage.sets.betrayersofkamigawa;
import java.util.List;
import java.util.UUID;
import mage.Constants;
import mage.Constants.CardType;
import mage.Constants.Rarity;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.costs.AlternativeCost;
import mage.abilities.costs.AlternativeCostImpl;
import mage.abilities.costs.Cost;
import mage.abilities.costs.Costs;
import mage.abilities.costs.common.ExileFromHandCost;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.ExileFromHandCostCardConvertedMana;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.filter.FilterCard;
import mage.filter.common.FilterOwnedCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardIdPredicate;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.other.OwnerPredicate;
import mage.game.Game;
import mage.target.common.TargetCardInHand;
/**
@ -56,12 +49,6 @@ import mage.target.common.TargetCardInHand;
public class NourishingShoal extends CardImpl<NourishingShoal> {
private static final String ALTERNATIVE_COST_DESCRIPTION = "You may exile a green card with converted mana cost X from your hand rather than pay Nourishing Shoal's mana cost";
private static final FilterCard filter = new FilterCard("green card from your hand");
static {
filter.add(new ColorPredicate(ObjectColor.GREEN));
filter.add(new OwnerPredicate(Constants.TargetController.YOU));
}
public NourishingShoal(UUID ownerId) {
super(ownerId, 137, "Nourishing Shoal", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{X}{G}{G}");
@ -70,10 +57,13 @@ public class NourishingShoal extends CardImpl<NourishingShoal> {
this.color.setGreen(true);
// You may exile a green card with converted mana cost X from your hand rather than pay Nourishing Shoal's mana cost.
FilterOwnedCard filter = new FilterOwnedCard("green card from your hand");
filter.add(new ColorPredicate(ObjectColor.GREEN));
filter.add(Predicates.not(new CardIdPredicate(this.getId()))); // the exile cost can never be paid with the card itself
this.getSpellAbility().addAlternativeCost(new AlternativeCostImpl(ALTERNATIVE_COST_DESCRIPTION, new ExileFromHandCost(new TargetCardInHand(filter))));
// You gain X life.
this.getSpellAbility().addEffect(new GainLifeEffect(new NourishingShoalVariableValue()));
this.getSpellAbility().addEffect(new GainLifeEffect(new ExileFromHandCostCardConvertedMana()));
}
@ -86,41 +76,3 @@ public class NourishingShoal extends CardImpl<NourishingShoal> {
return new NourishingShoal(this);
}
}
class NourishingShoalVariableValue implements DynamicValue {
@Override
public int calculate(Game game, Ability sourceAbility) {
List<AlternativeCost> aCosts = sourceAbility.getAlternativeCosts();
for (AlternativeCost aCost: aCosts) {
if (aCost.isPaid()) {
Costs aCostsList = (Costs) aCost;
for (int x=0; x < aCostsList.size(); x++) {
Cost cost = (Cost) aCostsList.get(x);
if (cost instanceof ExileFromHandCost) {
int xMana = 0;
for (Card card : ((ExileFromHandCost) cost).getCards()) {
xMana += card.getManaCost().convertedManaCost();
}
return xMana;
}
}
}
}
return sourceAbility.getManaCostsToPay().getX();
}
@Override
public DynamicValue clone() {
return new NourishingShoalVariableValue();
}
@Override
public String toString() {
return "X";
}
@Override
public String getMessage() {
return "";
}
}

View file

@ -27,7 +27,6 @@
*/
package mage.sets.betrayersofkamigawa;
import java.util.List;
import java.util.UUID;
import mage.Constants;
import mage.Constants.CardType;
@ -35,18 +34,16 @@ import mage.Constants.Rarity;
import mage.MageObject;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.costs.AlternativeCost;
import mage.abilities.costs.AlternativeCostImpl;
import mage.abilities.costs.Cost;
import mage.abilities.costs.Costs;
import mage.abilities.costs.common.ExileFromHandCost;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.ExileFromHandCostCardConvertedMana;
import mage.abilities.effects.PreventionEffectImpl;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.filter.FilterCard;
import mage.filter.common.FilterOwnedCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardIdPredicate;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.other.OwnerPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
@ -62,12 +59,6 @@ import mage.target.common.TargetCreatureOrPlayer;
public class ShiningShoal extends CardImpl<ShiningShoal> {
private static final String ALTERNATIVE_COST_DESCRIPTION = "You may exile a white card with converted mana cost X from your hand rather than pay Shining Shoal's mana cost";
private static final FilterCard filter = new FilterCard("white card from your hand");
static {
filter.add(new ColorPredicate(ObjectColor.WHITE));
filter.add(new OwnerPredicate(Constants.TargetController.YOU));
}
public ShiningShoal(UUID ownerId) {
super(ownerId, 21, "Shining Shoal", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{X}{W}{W}");
@ -76,10 +67,13 @@ public class ShiningShoal extends CardImpl<ShiningShoal> {
this.color.setWhite(true);
// You may exile a white card with converted mana cost X from your hand rather than pay Shining Shoal's mana cost
FilterOwnedCard filter = new FilterOwnedCard("white card from your hand");
filter.add(new ColorPredicate(ObjectColor.WHITE));
filter.add(Predicates.not(new CardIdPredicate(this.getId()))); // the exile cost can never be paid with the card itself
this.getSpellAbility().addAlternativeCost(new AlternativeCostImpl(ALTERNATIVE_COST_DESCRIPTION, new ExileFromHandCost(new TargetCardInHand(filter))));
// The next X damage that a source of your choice would deal to you and/or creatures you control this turn is dealt to target creature or player instead.
this.getSpellAbility().addEffect(new ShiningShoalPreventDamageTargetEffect(Constants.Duration.EndOfTurn, new ShiningShoalVariableValue()));
this.getSpellAbility().addEffect(new ShiningShoalPreventDamageTargetEffect(Constants.Duration.EndOfTurn, new ExileFromHandCostCardConvertedMana()));
this.getSpellAbility().addTarget(new TargetSource());
this.getSpellAbility().addTarget(new TargetCreatureOrPlayer());
}
@ -94,43 +88,6 @@ public class ShiningShoal extends CardImpl<ShiningShoal> {
}
}
class ShiningShoalVariableValue implements DynamicValue {
@Override
public int calculate(Game game, Ability sourceAbility) {
List<AlternativeCost> aCosts = sourceAbility.getAlternativeCosts();
for (AlternativeCost aCost: aCosts) {
if (aCost.isPaid()) {
Costs aCostsList = (Costs) aCost;
for (int x=0; x < aCostsList.size(); x++) {
Cost cost = (Cost) aCostsList.get(x);
if (cost instanceof ExileFromHandCost) {
int xMana = 0;
for (Card card : ((ExileFromHandCost) cost).getCards()) {
xMana += card.getManaCost().convertedManaCost();
}
return xMana;
}
}
}
}
return sourceAbility.getManaCostsToPay().getX();
}
@Override
public DynamicValue clone() {
return new ShiningShoalVariableValue();
}
@Override
public String toString() {
return "X";
}
@Override
public String getMessage() {
return "";
}
}
class ShiningShoalPreventDamageTargetEffect extends PreventionEffectImpl<ShiningShoalPreventDamageTargetEffect> {

View file

@ -27,27 +27,22 @@
*/
package mage.sets.betrayersofkamigawa;
import java.util.List;
import java.util.UUID;
import mage.Constants;
import mage.Constants.CardType;
import mage.Constants.Duration;
import mage.Constants.Rarity;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.costs.AlternativeCost;
import mage.abilities.costs.AlternativeCostImpl;
import mage.abilities.costs.Cost;
import mage.abilities.costs.Costs;
import mage.abilities.costs.common.ExileFromHandCost;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.ExileFromHandCostCardConvertedMana;
import mage.abilities.dynamicvalue.common.SignInversionDynamicValue;
import mage.abilities.effects.common.continious.BoostTargetEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.filter.FilterCard;
import mage.filter.common.FilterOwnedCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardIdPredicate;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.filter.predicate.other.OwnerPredicate;
import mage.game.Game;
import mage.target.common.TargetCardInHand;
import mage.target.common.TargetCreaturePermanent;
@ -58,12 +53,6 @@ import mage.target.common.TargetCreaturePermanent;
public class SickeningShoal extends CardImpl<SickeningShoal> {
private static final String ALTERNATIVE_COST_DESCRIPTION = "You may exile a black card with converted mana cost X from your hand rather than pay Sickening Shoal's mana cost";
private static final FilterCard filter = new FilterCard("black card from your hand");
static {
filter.add(new ColorPredicate(ObjectColor.BLACK));
filter.add(new OwnerPredicate(Constants.TargetController.YOU));
}
public SickeningShoal(UUID ownerId) {
super(ownerId, 82, "Sickening Shoal", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{X}{B}{B}");
@ -72,11 +61,14 @@ public class SickeningShoal extends CardImpl<SickeningShoal> {
this.color.setBlack(true);
// You may exile a black card with converted mana cost X from your hand rather than pay Sickening Shoal's mana cost.
FilterOwnedCard filter = new FilterOwnedCard("black card from your hand");
filter.add(new ColorPredicate(ObjectColor.BLACK));
filter.add(Predicates.not(new CardIdPredicate(this.getId()))); // the exile cost can never be paid with the card itself
this.getSpellAbility().addAlternativeCost(new AlternativeCostImpl(ALTERNATIVE_COST_DESCRIPTION, new ExileFromHandCost(new TargetCardInHand(filter))));
// Target creature gets -X/-X until end of turn.
DynamicValue x = new SignInversionDynamicValue(new SickeningShoalVariableValue());
this.getSpellAbility().addEffect(new BoostTargetEffect(x, x, Constants.Duration.EndOfTurn, true));
DynamicValue x = new SignInversionDynamicValue(new ExileFromHandCostCardConvertedMana());
this.getSpellAbility().addEffect(new BoostTargetEffect(x, x, Duration.EndOfTurn, true));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
}
@ -89,39 +81,3 @@ public class SickeningShoal extends CardImpl<SickeningShoal> {
return new SickeningShoal(this);
}
}
// ConvertedManaExileFromHandOrVariableManaValue
class SickeningShoalVariableValue implements DynamicValue {
@Override
public int calculate(Game game, Ability sourceAbility) {
for (AlternativeCost aCost: (List<AlternativeCost>) sourceAbility.getAlternativeCosts()) {
if (aCost.isPaid()) {
for (int x=0; x < ((Costs) aCost).size(); x++) {
Cost cost = (Cost) ((Costs) aCost).get(x);
if (cost instanceof ExileFromHandCost) {
int xValue = 0;
for (Card card : ((ExileFromHandCost) cost).getCards()) {
xValue += card.getManaCost().convertedManaCost();
}
return xValue;
}
}
}
}
return sourceAbility.getManaCostsToPay().getX();
}
@Override
public DynamicValue clone() {
return new SickeningShoalVariableValue();
}
@Override
public String toString() {
return "X";
}
@Override
public String getMessage() {
return "";
}
}

View file

@ -0,0 +1,85 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.dynamicvalue.common;
import java.util.List;
import mage.abilities.Ability;
import mage.abilities.costs.AlternativeCost;
import mage.abilities.costs.Cost;
import mage.abilities.costs.Costs;
import mage.abilities.costs.common.ExileFromHandCost;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.cards.Card;
import mage.game.Game;
/**
* Calculates the converted mana costs of a card that was
* exiled from hand as cost.
* If no card was exiled the getManaCostsToPay().getX() will
* be used as value.
*
*
* @author LevelX2
*/
public class ExileFromHandCostCardConvertedMana implements DynamicValue {
@Override
public int calculate(Game game, Ability sourceAbility) {
for (AlternativeCost aCost: (List<AlternativeCost>) sourceAbility.getAlternativeCosts()) {
if (aCost.isPaid()) {
for (int x=0; x < ((Costs) aCost).size(); x++) {
Cost cost = (Cost) ((Costs) aCost).get(x);
if (cost instanceof ExileFromHandCost) {
int xValue = 0;
for (Card card : ((ExileFromHandCost) cost).getCards()) {
xValue += card.getManaCost().convertedManaCost();
}
return xValue;
}
}
}
}
return sourceAbility.getManaCostsToPay().getX();
}
@Override
public DynamicValue clone() {
return new ExileFromHandCostCardConvertedMana();
}
@Override
public String toString() {
return "X";
}
@Override
public String getMessage() {
return "";
}
}