mirror of
https://github.com/magefree/mage.git
synced 2025-12-22 11:32:00 -08:00
This commit is contained in:
parent
2e827a50ec
commit
d80d588963
9 changed files with 107 additions and 122 deletions
|
|
@ -30,7 +30,6 @@ package mage.cards.c;
|
||||||
import java.util.UUID;
|
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.common.DiscardTargetCost;
|
|
||||||
import mage.abilities.costs.common.DiscardXTargetCost;
|
import mage.abilities.costs.common.DiscardXTargetCost;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.abilities.dynamicvalue.DynamicValue;
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
|
|
@ -82,8 +81,8 @@ class ConflagrateVariableValue implements DynamicValue {
|
||||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||||
int xValue = sourceAbility.getManaCostsToPay().getX();
|
int xValue = sourceAbility.getManaCostsToPay().getX();
|
||||||
for (Cost cost : sourceAbility.getCosts()) {
|
for (Cost cost : sourceAbility.getCosts()) {
|
||||||
if (cost instanceof DiscardTargetCost) {
|
if (cost instanceof DiscardXTargetCost) {
|
||||||
xValue = ((DiscardTargetCost) cost).getCards().size();
|
xValue = ((DiscardXTargetCost) cost).getAmount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return xValue;
|
return xValue;
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,9 @@
|
||||||
*/
|
*/
|
||||||
package org.mage.test.cards.abilities.keywords;
|
package org.mage.test.cards.abilities.keywords;
|
||||||
|
|
||||||
|
import mage.abilities.keyword.TrampleAbility;
|
||||||
import mage.constants.PhaseStep;
|
import mage.constants.PhaseStep;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
|
@ -39,6 +39,27 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
*/
|
*/
|
||||||
public class FlashbackTest extends CardTestPlayerBase {
|
public class FlashbackTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNormalWildHunger() {
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
|
||||||
|
|
||||||
|
// Target creature gets +3/+1 and gains trample until end of turn.
|
||||||
|
// Flashback {3}{R}
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, "Wild Hunger");
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1);
|
||||||
|
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Flashback", "Silvercoat Lion");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPowerToughness(playerA, "Silvercoat Lion", 5, 3);
|
||||||
|
assertAbility(playerA, "Silvercoat Lion", TrampleAbility.getInstance(), true);
|
||||||
|
assertExileCount("Wild Hunger", 1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fracturing Gust is bugged. In a match against Affinity, it worked
|
* Fracturing Gust is bugged. In a match against Affinity, it worked
|
||||||
* properly when cast from hand. When I cast it from graveyard c/o
|
* properly when cast from hand. When I cast it from graveyard c/o
|
||||||
|
|
@ -219,7 +240,7 @@ public class FlashbackTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
// Conflagrate deals X damage divided as you choose among any number of target creatures and/or players.
|
// Conflagrate deals X damage divided as you choose among any number of target creatures and/or players.
|
||||||
// Flashback-{R}{R}, Discard X cards.
|
// Flashback-{R}{R}, Discard X cards.
|
||||||
addCard(Zone.HAND, playerA, "Conflagrate", 1);
|
addCard(Zone.HAND, playerA, "Conflagrate", 1); // Sorcery {X}{X}{R}
|
||||||
|
|
||||||
addCard(Zone.HAND, playerA, "Forest", 4);
|
addCard(Zone.HAND, playerA, "Forest", 4);
|
||||||
|
|
||||||
|
|
@ -307,20 +328,26 @@ public class FlashbackTest extends CardTestPlayerBase {
|
||||||
public void testAltarsReap() {
|
public void testAltarsReap() {
|
||||||
|
|
||||||
addCard(Zone.LIBRARY, playerA, "Island", 2);
|
addCard(Zone.LIBRARY, playerA, "Island", 2);
|
||||||
addCard(Zone.GRAVEYARD, playerA, "Altar's Reap", 1);
|
// As an additional cost to cast Altar's Reap, sacrifice a creature.
|
||||||
|
// Draw two cards.
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, "Altar's Reap", 1); // Instant {1}{B}
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Underground Sea", 4);
|
addCard(Zone.BATTLEFIELD, playerA, "Underground Sea", 4);
|
||||||
addCard(Zone.HAND, playerA, "Snapcaster Mage", 1);
|
addCard(Zone.HAND, playerA, "Snapcaster Mage", 1);
|
||||||
|
|
||||||
|
// Flash
|
||||||
|
// When Snapcaster Mage enters the battlefield, target instant or sorcery card in your graveyard gains flashback until end of turn.
|
||||||
|
// The flashback cost is equal to its mana cost.
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Snapcaster Mage");
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Snapcaster Mage");
|
||||||
setChoice(playerA, "Altar's Reap");
|
setChoice(playerA, "Altar's Reap");
|
||||||
|
|
||||||
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flashback {1}{B}");
|
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flashback");
|
||||||
setChoice(playerA, "Snapcaster Mage");
|
setChoice(playerA, "Snapcaster Mage");
|
||||||
|
|
||||||
setStopAt(1, PhaseStep.END_TURN);
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
assertGraveyardCount(playerA, "Snapcaster Mage", 1);
|
assertGraveyardCount(playerA, "Snapcaster Mage", 1);
|
||||||
|
assertExileCount(playerA, "Altar's Reap", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -520,7 +547,6 @@ public class FlashbackTest extends CardTestPlayerBase {
|
||||||
* to a spell, and the flashback cost is already an alternative cost.
|
* to a spell, and the flashback cost is already an alternative cost.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
|
||||||
public void testSnapcasterMageSpellWithAlternateCost() {
|
public void testSnapcasterMageSpellWithAlternateCost() {
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,6 @@ import mage.abilities.effects.Effects;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.DynamicManaEffect;
|
import mage.abilities.effects.common.DynamicManaEffect;
|
||||||
import mage.abilities.effects.common.ManaEffect;
|
import mage.abilities.effects.common.ManaEffect;
|
||||||
import mage.abilities.keyword.FlashbackAbility;
|
|
||||||
import mage.abilities.mana.ActivatedManaAbilityImpl;
|
import mage.abilities.mana.ActivatedManaAbilityImpl;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.cards.SplitCard;
|
import mage.cards.SplitCard;
|
||||||
|
|
@ -337,9 +336,7 @@ public abstract class AbilityImpl implements Ability {
|
||||||
if (sourceObject != null && this.getAbilityType() != AbilityType.TRIGGERED) { // triggered abilities check this already in playerImpl.triggerAbility
|
if (sourceObject != null && this.getAbilityType() != AbilityType.TRIGGERED) { // triggered abilities check this already in playerImpl.triggerAbility
|
||||||
sourceObject.adjustTargets(this, game);
|
sourceObject.adjustTargets(this, game);
|
||||||
}
|
}
|
||||||
// Flashback abilities haven't made the choices the underlying spell might need for targeting.
|
if (!getTargets().isEmpty()) {
|
||||||
if (!(this instanceof FlashbackAbility)
|
|
||||||
&& !getTargets().isEmpty()) {
|
|
||||||
Outcome outcome = getEffects().isEmpty() ? Outcome.Detriment : getEffects().get(0).getOutcome();
|
Outcome outcome = getEffects().isEmpty() ? Outcome.Detriment : getEffects().get(0).getOutcome();
|
||||||
if (getTargets().chooseTargets(outcome, this.controllerId, this, noMana, game) == false) {
|
if (getTargets().chooseTargets(outcome, this.controllerId, this, noMana, game) == false) {
|
||||||
if ((variableManaCost != null || announceString != null)) {
|
if ((variableManaCost != null || announceString != null)) {
|
||||||
|
|
@ -445,8 +442,15 @@ public abstract class AbilityImpl implements Ability {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean activateAlternateOrAdditionalCosts(MageObject sourceObject, boolean noMana, Player controller, Game game) {
|
public boolean activateAlternateOrAdditionalCosts(MageObject sourceObject, boolean noMana, Player controller, Game game) {
|
||||||
|
if (this instanceof SpellAbility) {
|
||||||
|
if (((SpellAbility) this).getSpellAbilityCastMode() != SpellAbilityCastMode.NORMAL) {
|
||||||
|
// A player can't apply two alternative methods of casting or two alternative costs to a single spell.
|
||||||
|
// So can only use alternate costs if the spell is cast in normal mode
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
boolean alternativeCostisUsed = false;
|
boolean alternativeCostisUsed = false;
|
||||||
if (sourceObject != null && !(sourceObject instanceof Permanent) && !(this instanceof FlashbackAbility)) {
|
if (sourceObject != null && !(sourceObject instanceof Permanent)) {
|
||||||
Abilities<Ability> abilities = null;
|
Abilities<Ability> abilities = null;
|
||||||
if (sourceObject instanceof Card) {
|
if (sourceObject instanceof Card) {
|
||||||
abilities = ((Card) sourceObject).getAbilities(game);
|
abilities = ((Card) sourceObject).getAbilities(game);
|
||||||
|
|
|
||||||
|
|
@ -217,7 +217,7 @@ public class SpellAbility extends ActivatedAbilityImpl {
|
||||||
this.name = "Cast fused " + cardName;
|
this.name = "Cast fused " + cardName;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
this.name = "Cast " + cardName + (this.spellAbilityCastMode != SpellAbilityCastMode.NORMAL ? " by " + spellAbilityCastMode.toString() : "");
|
this.name = "Cast " + cardName + (this.spellAbilityCastMode != SpellAbilityCastMode.NORMAL ? " using " + spellAbilityCastMode.toString() : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -230,4 +230,11 @@ public class SpellAbility extends ActivatedAbilityImpl {
|
||||||
setSpellName();
|
setSpellName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpellAbility getSpellAbilityToResolve(Game game) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(UUID idToUse) {
|
||||||
|
this.id = idToUse;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ package mage.abilities.costs;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.keyword.FlashbackAbility;
|
|
||||||
import mage.abilities.mana.ManaAbility;
|
import mage.abilities.mana.ManaAbility;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.stack.StackObject;
|
import mage.game.stack.StackObject;
|
||||||
|
|
@ -173,7 +172,6 @@ public abstract class VariableCostImpl implements Cost, VariableCost {
|
||||||
StackObject stackObject = game.getStack().getStackObject(source.getId());
|
StackObject stackObject = game.getStack().getStackObject(source.getId());
|
||||||
if (controller != null
|
if (controller != null
|
||||||
&& (source instanceof ManaAbility
|
&& (source instanceof ManaAbility
|
||||||
|| source instanceof FlashbackAbility
|
|
||||||
|| stackObject != null)) {
|
|| stackObject != null)) {
|
||||||
xValue = controller.announceXCost(getMinValue(source, game), getMaxValue(source, game),
|
xValue = controller.announceXCost(getMinValue(source, game), getMaxValue(source, game),
|
||||||
"Announce the number of " + actionText, game, source, this);
|
"Announce the number of " + actionText, game, source, this);
|
||||||
|
|
|
||||||
|
|
@ -32,14 +32,13 @@ import mage.abilities.Ability;
|
||||||
import mage.abilities.SpellAbility;
|
import mage.abilities.SpellAbility;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.Costs;
|
import mage.abilities.costs.Costs;
|
||||||
import mage.abilities.costs.mana.ManaCost;
|
|
||||||
import mage.abilities.effects.ContinuousEffect;
|
import mage.abilities.effects.ContinuousEffect;
|
||||||
import mage.abilities.effects.OneShotEffect;
|
|
||||||
import mage.abilities.effects.ReplacementEffectImpl;
|
import mage.abilities.effects.ReplacementEffectImpl;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.cards.SplitCard;
|
import mage.cards.SplitCard;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.SpellAbilityCastMode;
|
||||||
import mage.constants.SpellAbilityType;
|
import mage.constants.SpellAbilityType;
|
||||||
import mage.constants.TimingRule;
|
import mage.constants.TimingRule;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
|
|
@ -66,23 +65,21 @@ import mage.target.targetpointer.FixedTarget;
|
||||||
public class FlashbackAbility extends SpellAbility {
|
public class FlashbackAbility extends SpellAbility {
|
||||||
|
|
||||||
private String abilityName;
|
private String abilityName;
|
||||||
|
private SpellAbility spellAbilityToResolve;
|
||||||
|
|
||||||
public FlashbackAbility(Cost cost, TimingRule timingRule) {
|
public FlashbackAbility(Cost cost, TimingRule timingRule) {
|
||||||
super(null, "", Zone.GRAVEYARD);
|
super(null, "", Zone.GRAVEYARD, SpellAbilityType.BASE_ALTERNATE, SpellAbilityCastMode.FLASHBACK);
|
||||||
this.setAdditionalCostsRuleVisible(false);
|
this.setAdditionalCostsRuleVisible(false);
|
||||||
this.name = "Flashback " + cost.getText();
|
this.name = "Flashback " + cost.getText();
|
||||||
this.addEffect(new FlashbackEffect());
|
|
||||||
this.addCost(cost);
|
this.addCost(cost);
|
||||||
this.timing = timingRule;
|
this.timing = timingRule;
|
||||||
this.usesStack = false;
|
|
||||||
this.spellAbilityType = SpellAbilityType.BASE_ALTERNATE;
|
|
||||||
setCostModificationActive(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public FlashbackAbility(final FlashbackAbility ability) {
|
public FlashbackAbility(final FlashbackAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
this.spellAbilityType = ability.spellAbilityType;
|
this.spellAbilityType = ability.spellAbilityType;
|
||||||
this.abilityName = ability.abilityName;
|
this.abilityName = ability.abilityName;
|
||||||
|
this.spellAbilityToResolve = ability.spellAbilityToResolve;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -108,6 +105,47 @@ public class FlashbackAbility extends SpellAbility {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpellAbility getSpellAbilityToResolve(Game game) {
|
||||||
|
Card card = game.getCard(getSourceId());
|
||||||
|
if (card != null) {
|
||||||
|
if (spellAbilityToResolve == null) {
|
||||||
|
SpellAbility spellAbilityCopy = null;
|
||||||
|
if (card.isSplitCard()) {
|
||||||
|
if (((SplitCard) card).getLeftHalfCard().getName().equals(abilityName)) {
|
||||||
|
spellAbilityCopy = ((SplitCard) card).getLeftHalfCard().getSpellAbility().copy();
|
||||||
|
} else if (((SplitCard) card).getRightHalfCard().getName().equals(abilityName)) {
|
||||||
|
spellAbilityCopy = ((SplitCard) card).getRightHalfCard().getSpellAbility().copy();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
spellAbilityCopy = card.getSpellAbility().copy();
|
||||||
|
}
|
||||||
|
if (spellAbilityCopy == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
spellAbilityCopy.setId(this.getId());
|
||||||
|
spellAbilityCopy.getManaCosts().clear();
|
||||||
|
spellAbilityCopy.getManaCostsToPay().clear();
|
||||||
|
spellAbilityCopy.getCosts().addAll(this.getCosts());
|
||||||
|
spellAbilityCopy.addCost(this.getManaCosts());
|
||||||
|
spellAbilityCopy.setSpellAbilityCastMode(this.getSpellAbilityCastMode());
|
||||||
|
spellAbilityToResolve = spellAbilityCopy;
|
||||||
|
ContinuousEffect effect = new FlashbackReplacementEffect();
|
||||||
|
effect.setTargetPointer(new FixedTarget(getSourceId(), game.getState().getZoneChangeCounter(getSourceId())));
|
||||||
|
game.addEffect(effect, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return spellAbilityToResolve;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Costs<Cost> getCosts() {
|
||||||
|
if (spellAbilityToResolve == null) {
|
||||||
|
return super.getCosts();
|
||||||
|
}
|
||||||
|
return spellAbilityToResolve.getCosts();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FlashbackAbility copy() {
|
public FlashbackAbility copy() {
|
||||||
return new FlashbackAbility(this);
|
return new FlashbackAbility(this);
|
||||||
|
|
@ -144,102 +182,18 @@ public class FlashbackAbility extends SpellAbility {
|
||||||
return sbRule.toString();
|
return sbRule.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public void setSpellAbilityType(SpellAbilityType spellAbilityType) {
|
* Used for split card sin PlayerImpl method:
|
||||||
this.spellAbilityType = spellAbilityType;
|
* getOtherUseableActivatedAbilities
|
||||||
}
|
*
|
||||||
|
* @param abilityName
|
||||||
@Override
|
*/
|
||||||
public SpellAbilityType getSpellAbilityType() {
|
|
||||||
return this.spellAbilityType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAbilityName(String abilityName) {
|
public void setAbilityName(String abilityName) {
|
||||||
this.abilityName = abilityName;
|
this.abilityName = abilityName;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class FlashbackEffect extends OneShotEffect {
|
|
||||||
|
|
||||||
public FlashbackEffect() {
|
|
||||||
super(Outcome.Benefit);
|
|
||||||
staticText = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public FlashbackEffect(final FlashbackEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FlashbackEffect copy() {
|
|
||||||
return new FlashbackEffect(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
Card card = (Card) game.getObject(source.getSourceId());
|
|
||||||
if (card != null) {
|
|
||||||
Player controller = game.getPlayer(source.getControllerId());
|
|
||||||
if (controller != null) {
|
|
||||||
SpellAbility spellAbility;
|
|
||||||
switch (((FlashbackAbility) source).getSpellAbilityType()) {
|
|
||||||
case SPLIT_LEFT:
|
|
||||||
spellAbility = ((SplitCard) card).getLeftHalfCard().getSpellAbility().copy();
|
|
||||||
break;
|
|
||||||
case SPLIT_RIGHT:
|
|
||||||
spellAbility = ((SplitCard) card).getRightHalfCard().getSpellAbility().copy();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
spellAbility = card.getSpellAbility().copy();
|
|
||||||
}
|
|
||||||
|
|
||||||
spellAbility.clear();
|
|
||||||
// set the payed flashback costs to the spell ability so abilities like Converge or calculation of {X} values work
|
|
||||||
spellAbility.getManaCostsToPay().clear();
|
|
||||||
spellAbility.getManaCostsToPay().addAll(source.getManaCosts());
|
|
||||||
spellAbility.getManaCosts().clear();
|
|
||||||
spellAbility.getManaCosts().addAll(source.getManaCosts());
|
|
||||||
// needed to get e.g. paid costs from Conflagrate
|
|
||||||
|
|
||||||
for (Cost cost : source.getCosts()) {
|
|
||||||
if (cost instanceof Costs) {
|
|
||||||
Costs<Cost> listOfCosts = (Costs<Cost>) cost;
|
|
||||||
for (Cost singleCost : listOfCosts) {
|
|
||||||
if (singleCost instanceof ManaCost) {
|
|
||||||
singleCost.clearPaid();
|
|
||||||
spellAbility.getManaCosts().add((ManaCost) singleCost);
|
|
||||||
spellAbility.getManaCostsToPay().add((ManaCost) singleCost);
|
|
||||||
} else {
|
|
||||||
spellAbility.getCosts().add(singleCost);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (cost instanceof ManaCost) {
|
|
||||||
spellAbility.getManaCosts().add((ManaCost) cost);
|
|
||||||
spellAbility.getManaCostsToPay().add((ManaCost) cost);
|
|
||||||
} else {
|
|
||||||
spellAbility.getCosts().add(cost);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!game.isSimulation()) {
|
|
||||||
game.informPlayers(controller.getLogName() + " flashbacks " + card.getLogName());
|
|
||||||
}
|
|
||||||
if (controller.cast(spellAbility, game, false)) {
|
|
||||||
ContinuousEffect effect = new FlashbackReplacementEffect();
|
|
||||||
effect.setTargetPointer(new FixedTarget(source.getSourceId(), game.getState().getZoneChangeCounter(source.getSourceId())));
|
|
||||||
game.addEffect(effect, source);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class FlashbackReplacementEffect extends ReplacementEffectImpl {
|
class FlashbackReplacementEffect extends ReplacementEffectImpl {
|
||||||
|
|
||||||
public FlashbackReplacementEffect() {
|
public FlashbackReplacementEffect() {
|
||||||
|
|
@ -287,7 +241,7 @@ class FlashbackReplacementEffect extends ReplacementEffectImpl {
|
||||||
&& ((ZoneChangeEvent) event).getToZone() != Zone.EXILED) {
|
&& ((ZoneChangeEvent) event).getToZone() != Zone.EXILED) {
|
||||||
|
|
||||||
int zcc = game.getState().getZoneChangeCounter(source.getSourceId());
|
int zcc = game.getState().getZoneChangeCounter(source.getSourceId());
|
||||||
if (((FixedTarget) getTargetPointer()).getZoneChangeCounter() == zcc) {
|
if (((FixedTarget) getTargetPointer()).getZoneChangeCounter() + 1 == zcc) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -516,7 +516,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
||||||
Card mainCard = getMainCard();
|
Card mainCard = getMainCard();
|
||||||
ZoneChangeEvent event = new ZoneChangeEvent(mainCard.getId(), ability.getId(), controllerId, fromZone, Zone.STACK);
|
ZoneChangeEvent event = new ZoneChangeEvent(mainCard.getId(), ability.getId(), controllerId, fromZone, Zone.STACK);
|
||||||
ZoneChangeInfo.Stack info
|
ZoneChangeInfo.Stack info
|
||||||
= new ZoneChangeInfo.Stack(event, new Spell(this, ability.copy(), controllerId, event.getFromZone()));
|
= new ZoneChangeInfo.Stack(event, new Spell(this, ability.getSpellAbilityToResolve(game), controllerId, event.getFromZone()));
|
||||||
return ZonesHandler.cast(info, game);
|
return ZonesHandler.cast(info, game);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,8 @@ package mage.constants;
|
||||||
*/
|
*/
|
||||||
public enum SpellAbilityCastMode {
|
public enum SpellAbilityCastMode {
|
||||||
NORMAL("Normal"),
|
NORMAL("Normal"),
|
||||||
MADNESS("Madness");
|
MADNESS("Madness"),
|
||||||
|
FLASHBACK("Flashback");
|
||||||
|
|
||||||
private final String text;
|
private final String text;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1158,7 +1158,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int bookmark = game.bookmarkState();
|
int bookmark = game.bookmarkState();
|
||||||
if (ability.activate(game, ability instanceof FlashbackAbility)) {
|
if (ability.activate(game, false)) {
|
||||||
ability.resolve(game);
|
ability.resolve(game);
|
||||||
game.removeBookmark(bookmark);
|
game.removeBookmark(bookmark);
|
||||||
resetStoredBookmark(game);
|
resetStoredBookmark(game);
|
||||||
|
|
@ -1219,11 +1219,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
result = playManaAbility((ActivatedManaAbilityImpl) ability.copy(), game);
|
result = playManaAbility((ActivatedManaAbilityImpl) ability.copy(), game);
|
||||||
break;
|
break;
|
||||||
case SPELL:
|
case SPELL:
|
||||||
if (ability instanceof FlashbackAbility) {
|
result = cast((SpellAbility) ability.copy(), game, false);
|
||||||
result = playAbility(ability.copy(), game);
|
|
||||||
} else {
|
|
||||||
result = cast((SpellAbility) ability, game, false);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
result = playAbility(ability.copy(), game);
|
result = playAbility(ability.copy(), game);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue