* FlashbackAbility - Fixed that for flashbacked spells additional optional costs did not work (e.g. Buyback, Replicate, Kicker).

This commit is contained in:
LevelX2 2014-04-27 16:06:07 +02:00
parent bf260cd9c6
commit b4dcddd0a9
7 changed files with 79 additions and 28 deletions

View file

@ -49,6 +49,7 @@ import mage.abilities.effects.Effect;
import mage.abilities.effects.Effects;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.PostResolveEffect;
import mage.abilities.keyword.FlashbackAbility;
import mage.abilities.mana.ManaAbility;
import mage.cards.Card;
import mage.choices.Choice;
@ -219,15 +220,25 @@ public abstract class AbilityImpl<T extends AbilityImpl<T>> implements Ability {
}
}
// if ability can be cast for no mana, clear the mana costs now, because additional mana costs must be paid.
// For Flashback ability can be set X before, so the X costs have to be restored for the flashbacked ability
if (noMana) {
int xValue = this.getManaCostsToPay().getX();
this.getManaCostsToPay().clear();
VariableManaCost xCosts = new VariableManaCost();
xCosts.setAmount(xValue);
this.getManaCostsToPay().add(xCosts);
}
// 20130201 - 601.2b
// If the spell has alternative or additional costs that will be paid as it's being cast such
// as buyback, kicker, or convoke costs (see rules 117.8 and 117.9), the player announces his
// or her intentions to pay any or all of those costs (see rule 601.2e).
// A player can't apply two alternative methods of casting or two alternative costs to a single spell.
if (card != null) {
if (card != null && !(this instanceof FlashbackAbility)) {
boolean alternativeCostisUsed = false;
for (Ability ability : card.getAbilities()) {
if (ability instanceof AlternativeSourceCosts) {
// if cast for noMana no Alternative costs are allowed
if (!noMana && ability instanceof AlternativeSourceCosts) {
AlternativeSourceCosts alternativeSpellCosts = (AlternativeSourceCosts) ability;
if (alternativeSpellCosts.isAvailable(this, game)) {
if (alternativeSpellCosts.askToActivateAlternativeCosts(this, game)) {
@ -241,7 +252,8 @@ public abstract class AbilityImpl<T extends AbilityImpl<T>> implements Ability {
((OptionalAdditionalSourceCosts)ability).addOptionalAdditionalCosts(this, game);
}
}
if (!alternativeCostisUsed) {
// controller specific alternate spell costs
if (!noMana && !alternativeCostisUsed) {
if (this.getAbilityType().equals(AbilityType.SPELL)) {
for (AlternativeSourceCosts alternativeSourceCosts: controller.getAlternativeSourceCosts()) {
if (alternativeSourceCosts.isAvailable(this, game)) {
@ -328,8 +340,8 @@ public abstract class AbilityImpl<T extends AbilityImpl<T>> implements Ability {
if (!useAlternativeCost(game)) { // old way still used?
//20100716 - 601.2f
if (!manaCostsToPay.pay(this, game, sourceId, activatorId, noMana)) {
//20100716 - 601.2f (noMana is not used here, because mana costs were cleared for this abaility before adding additional costs and applying cost modification effects)
if (!manaCostsToPay.pay(this, game, sourceId, activatorId, false)) {
logger.debug("activate failed - mana");
return false;
}
@ -385,6 +397,7 @@ public abstract class AbilityImpl<T extends AbilityImpl<T>> implements Ability {
*
* @param game
* @param noMana
* @param controller
* @return variableManaCost for posting to log later
*/
protected VariableManaCost handleManaXCosts(Game game, boolean noMana, Player controller) {

View file

@ -116,7 +116,7 @@ public class SpellAbility extends ActivatedAbilityImpl<SpellAbility> {
@Override
public String getGameLogMessage(Game game) {
return new StringBuilder(" casts ").append(getMessageText(game)).toString();
return getMessageText(game);
}
@Override

View file

@ -148,7 +148,7 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
@Override
public ManaCosts<T> getUnpaid() {
ManaCosts<T> unpaid = new ManaCostsImpl<T>();
ManaCosts<T> unpaid = new ManaCostsImpl<>();
for (T cost : this) {
if (!(cost instanceof VariableManaCost) && !cost.isPaid()) {
unpaid.add((T) cost.getUnpaid());
@ -159,7 +159,7 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
@Override
public ManaCosts<T> getUnpaidVariableCosts() {
ManaCosts<T> unpaid = new ManaCostsImpl<T>();
ManaCosts<T> unpaid = new ManaCostsImpl<>();
for (ManaCost cost : this) {
if (cost instanceof VariableManaCost && !cost.isPaid()) {
unpaid.add((T) cost.getUnpaid());
@ -171,7 +171,7 @@ public class ManaCostsImpl<T extends ManaCost> extends ArrayList<T> implements M
@Override
public List<VariableCost> getVariableCosts() {
List<VariableCost> variableCosts = new ArrayList<VariableCost>();
List<VariableCost> variableCosts = new ArrayList<>();
for (ManaCost cost : this) {
if (cost instanceof VariableCost) {
variableCosts.add((VariableCost) cost);

View file

@ -27,6 +27,7 @@
*/
package mage.abilities.keyword;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.SpellAbility;
@ -73,6 +74,17 @@ public class FlashbackAbility extends SpellAbility {
this.abilityName = ability.abilityName;
}
@Override
public boolean canActivate(UUID playerId, Game game) {
if (super.canActivate(playerId, game)) {
Card card = game.getCard(getSourceId());
if (card != null) {
return card.getSpellAbility().canActivate(playerId, game);
}
}
return false;
}
@Override
public FlashbackAbility copy() {
return new FlashbackAbility(this);
@ -157,11 +169,13 @@ class FlashbackEffect extends OneShotEffect<FlashbackEffect> {
}
spellAbility.clear();
// used if flashbacked spell has a {X} cost
int amount = source.getManaCostsToPay().getX();
spellAbility.getManaCostsToPay().setX(amount);
for (Target target : spellAbility.getTargets()) {
target.setRequired(true);
}
game.informPlayers(new StringBuilder(controller.getName()).append(" flashbacks ").append(card.getName()).toString());
return controller.cast(spellAbility, game, true);
}
}

View file

@ -146,7 +146,13 @@ public class Spell<T extends Spell<T>> implements StackObject, Card {
}
public String getActivatedMessage(Game game) {
return ability.getGameLogMessage(game);
StringBuilder sb = new StringBuilder();
if (isCopiedSpell()) {
sb.append(" copies ");
} else {
sb.append(" casts ");
}
return sb.append(ability.getGameLogMessage(game)).toString();
}
@Override