Merge pull request #937 from ImperatorPrime/master

Changed Kentaro, the Smiling Cat's ability to be an alternate cost instead of a set cost effect.
This commit is contained in:
LevelX2 2015-04-27 11:59:38 +02:00
commit d68668d7c1
4 changed files with 138 additions and 69 deletions

View file

@ -27,22 +27,31 @@
*/
package mage.sets.betrayersofkamigawa;
import mage.constants.*;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
import mage.abilities.condition.common.SourceIsSpellCondition;
import mage.abilities.costs.AlternativeCostSourceAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.DynamicCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.keyword.BushidoAbility;
import mage.abilities.keyword.FlashbackAbility;
import mage.abilities.keyword.RetraceAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.SubLayer;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
import mage.players.Player;
import java.util.UUID;
/**
* @author LevelX2
*/
@ -62,7 +71,7 @@ public class KentaroTheSmilingCat extends CardImpl {
this.addAbility(new BushidoAbility(1));
// You may pay {X} rather than pay the mana cost for Samurai spells you cast, where X is that spell's converted mana cost.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new KentaroTheSmilingCatCostReductionEffect()));
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new KentaroTheSmilingCatCastingEffect()));
}
@ -75,50 +84,63 @@ public class KentaroTheSmilingCat extends CardImpl {
public KentaroTheSmilingCat copy() {
return new KentaroTheSmilingCat(this);
}
//TODO : change CostModification to AlternativCost
private class KentaroTheSmilingCatCostReductionEffect extends CostModificationEffectImpl {
private static final String effectText = "You may pay {X} rather than pay the mana cost for Samurai spells you cast, where X is that spell's converted mana cost";
KentaroTheSmilingCatCostReductionEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.SET_COST);
staticText = effectText;
}
KentaroTheSmilingCatCostReductionEffect(KentaroTheSmilingCatCostReductionEffect effect) {
class KentaroTheSmilingCatCastingEffect extends ContinuousEffectImpl {
private static final FilterCard filterSamurai = new FilterCard();
static {
filterSamurai.add(new SubtypePredicate("Samurai"));
}
static final AlternativeCostSourceAbility alternativeCastingCostAbility = new AlternativeCostSourceAbility(
SourceIsSpellCondition.getInstance(), null, filterSamurai, true, new ColorlessConvertedManaCost());
public KentaroTheSmilingCatCastingEffect() {
super(Duration.WhileOnBattlefield, Outcome.Benefit);
staticText = "You may pay {X} rather than pay the mana cost for Samurai spells you cast, where X is that spell's converted mana cost";
}
public KentaroTheSmilingCatCastingEffect(final KentaroTheSmilingCatCastingEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source, Ability abilityToModify) {
return true;
public KentaroTheSmilingCatCastingEffect copy() {
return new KentaroTheSmilingCatCastingEffect(this);
}
@Override
public boolean applies(Ability abilityToModify, Ability source, Game game) {
if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility || abilityToModify instanceof RetraceAbility) {
Ability spell = abilityToModify;
if (spell.getControllerId().equals(source.getControllerId())) {
Card sourceCard = game.getCard(spell.getSourceId());
if (sourceCard != null && sourceCard.hasSubtype("Samurai")) {
String manaCostsString = "{" + sourceCard.getManaCost().convertedManaCost() + "}";
Player player = game.getPlayer(spell.getControllerId());
if (player != null && player.chooseUse(Outcome.Benefit, "Pay converted mana cost rather than pay the mana cost for Samurai creature?", game)) {
spell.getManaCostsToPay().clear();
spell.getManaCostsToPay().load(manaCostsString);
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
controller.getAlternativeSourceCosts().add(alternativeCastingCostAbility);
return true;
}
}
}
}
return false;
}
@Override
public KentaroTheSmilingCatCostReductionEffect copy() {
return new KentaroTheSmilingCatCostReductionEffect(this);
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public boolean hasLayer(Layer layer) {
return layer == Layer.RulesEffects;
}
}
class ColorlessConvertedManaCost implements DynamicCost {
@Override
public Cost getCost(Ability ability, Game game) {
return new GenericManaCost(ability.getManaCosts().convertedManaCost());
}
@Override
public String getText(Ability ability, Game game) {
return "Pay " + getCost(ability, game).getText() + " rather than " + ability.getManaCosts().getText() + " for Samurai?";
}
}

View file

@ -51,6 +51,7 @@ public class AlternativeCostSourceAbility extends StaticAbility implements Alter
protected String rule;
protected FilterCard filter;
protected boolean onlyMana;
protected DynamicCost dynamicCost;
public AlternativeCostSourceAbility(Cost cost) {
this(cost, null);
@ -78,7 +79,7 @@ public class AlternativeCostSourceAbility extends StaticAbility implements Alter
*/
public AlternativeCostSourceAbility(Cost cost, Condition condition, String rule, FilterCard filter, boolean onlyMana) {
super(Zone.ALL, null);
this.convertToAlternativeCostAndAdd(cost);
this.addCost(cost);
this.setRuleAtTheTop(true);
this.condition = condition;
this.rule = rule;
@ -86,6 +87,16 @@ public class AlternativeCostSourceAbility extends StaticAbility implements Alter
this.onlyMana = onlyMana;
}
public AlternativeCostSourceAbility(Condition condition, String rule, FilterCard filter, boolean onlyMana, DynamicCost dynamicCost) {
super(Zone.ALL, null);
this.setRuleAtTheTop(true);
this.condition = condition;
this.rule = rule;
this.filter = filter;
this.onlyMana = onlyMana;
this.dynamicCost = dynamicCost;
}
public AlternativeCostSourceAbility(final AlternativeCostSourceAbility ability) {
super(ability);
this.alternateCosts = ability.alternateCosts;
@ -93,20 +104,21 @@ public class AlternativeCostSourceAbility extends StaticAbility implements Alter
this.rule = ability.rule;
this.filter = ability.filter;
this.onlyMana = ability.onlyMana;
this.dynamicCost = ability.dynamicCost;
}
@Override
public void addCost(Cost cost) {
this.convertToAlternativeCostAndAdd(cost);
}
private void convertToAlternativeCostAndAdd(Cost cost) {
if (cost != null) {
AlternativeCost2 alternativeCost = new AlternativeCost2Impl(null, null, cost);
AlternativeCost2 alternativeCost = convertToAlternativeCost(cost);
if(alternativeCost != null) {
this.alternateCosts.add(alternativeCost);
}
}
private AlternativeCost2 convertToAlternativeCost(Cost cost) {
return cost != null ? new AlternativeCost2Impl(null, cost.getText(), cost) : null;
}
@Override
public AlternativeCostSourceAbility copy() {
return new AlternativeCostSourceAbility(this);
@ -131,13 +143,29 @@ public class AlternativeCostSourceAbility extends StaticAbility implements Alter
}
Player player = game.getPlayer(ability.getControllerId());
if (player != null) {
if (alternateCosts.canPay(ability, ability.getSourceId(), ability.getControllerId(), game) &&
player.chooseUse(Outcome.Detriment, alternateCosts.isEmpty() ? "Cast without paying its mana cost?":"Pay alternative costs? (" + alternateCosts.getText() +")", game)) {
Costs<AlternativeCost2> alternativeCosts;
if(dynamicCost != null) {
alternativeCosts = new CostsImpl<>();
alternativeCosts.add(convertToAlternativeCost(dynamicCost.getCost(ability, game)));
} else {
alternativeCosts = this.alternateCosts;
}
String costChoiceText;
if(dynamicCost != null) {
costChoiceText = dynamicCost.getText(ability, game);
} else {
costChoiceText = alternativeCosts.isEmpty() ? "Cast without paying its mana cost?" : "Pay alternative costs? (" + alternativeCosts.getText() +")";
}
if (alternativeCosts.canPay(ability, ability.getSourceId(), ability.getControllerId(), game) &&
player.chooseUse(Outcome.Benefit, costChoiceText, game)) {
ability.getManaCostsToPay().clear();
if(!onlyMana) {
ability.getCosts().clear();
}
for (Cost cost : alternateCosts) {
for (Cost cost : alternativeCosts) {
AlternativeCost2 alternateCost = (AlternativeCost2) cost;
alternateCost.activate();
for (Iterator it = ((Costs) alternateCost).iterator(); it.hasNext();) {
@ -161,7 +189,14 @@ public class AlternativeCostSourceAbility extends StaticAbility implements Alter
@Override
public boolean isActivated(Ability source, Game game) {
for (AlternativeCost2 cost : alternateCosts) {
Costs<AlternativeCost2> alternativeCosts;
if(dynamicCost != null) {
alternativeCosts = new CostsImpl<>();
alternativeCosts.add(convertToAlternativeCost(dynamicCost.getCost(source, game)));
} else {
alternativeCosts = this.alternateCosts;
}
for (AlternativeCost2 cost : alternativeCosts) {
if (cost.isActivated(game)) {
return true;
}

View file

@ -0,0 +1,12 @@
package mage.abilities.costs;
import mage.abilities.Ability;
import mage.game.Game;
public interface DynamicCost {
Cost getCost(Ability ability, Game game);
String getText(Ability ability, Game game);
}

View file

@ -131,13 +131,13 @@ public class DashAbility extends StaticAbility implements AlternativeSourceCosts
Player player = game.getPlayer(controllerId);
if (player != null) {
this.resetDash();
for (AlternativeCost2 evokeCost: alternativeSourceCosts) {
if (evokeCost.canPay(ability, sourceId, controllerId, game) &&
player.chooseUse(Outcome.Benefit, new StringBuilder(KEYWORD).append(" the creature for ").append(evokeCost.getText(true)).append(" ?").toString(), game)) {
activateDash(evokeCost, game);
for (AlternativeCost2 dashCost: alternativeSourceCosts) {
if (dashCost.canPay(ability, sourceId, controllerId, game) &&
player.chooseUse(Outcome.Benefit, new StringBuilder(KEYWORD).append(" the creature for ").append(dashCost.getText(true)).append(" ?").toString(), game)) {
activateDash(dashCost, game);
ability.getManaCostsToPay().clear();
ability.getCosts().clear();
for (Iterator it = ((Costs) evokeCost).iterator(); it.hasNext();) {
for (Iterator it = ((Costs) dashCost).iterator(); it.hasNext();) {
Cost cost = (Cost) it.next();
if (cost instanceof ManaCostsImpl) {
ability.getManaCostsToPay().add((ManaCostsImpl) cost.copy());
@ -170,12 +170,12 @@ public class DashAbility extends StaticAbility implements AlternativeSourceCosts
StringBuilder sb = new StringBuilder();
int numberCosts = 0;
String remarkText = "";
for (AlternativeCost2 evokeCost: alternativeSourceCosts) {
for (AlternativeCost2 dashCost: alternativeSourceCosts) {
if (numberCosts == 0) {
sb.append(evokeCost.getText(false));
remarkText = evokeCost.getReminderText();
sb.append(dashCost.getText(false));
remarkText = dashCost.getReminderText();
} else {
sb.append(" and/or ").append(evokeCost.getText(true));
sb.append(" and/or ").append(dashCost.getText(true));
}
++numberCosts;
}