Skip to content

Commit 7ec420f

Browse files
authored
Fix cascade: use mana value of spell, not card (#14693)
* Use spell mana value instead of card mana value for cascade Cascade should use the mana value of the spell rather than the mana value of the card. (Only?) relevant for X-cost spells. No need to document rule 202.3e in `CascadeAbility` since it is already documented in `Spell.getManaValue()`. Fixes #14687 * And also have cascade look back at LKI --------- Co-authored-by: matoro <matoro@users.noreply.github.com>
1 parent 5f311fe commit 7ec420f

2 files changed

Lines changed: 58 additions & 3 deletions

File tree

Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/CascadeTest.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import mage.constants.Zone;
55
import org.junit.Assert;
66
import org.junit.Test;
7+
import org.mage.test.player.TestPlayer;
78
import org.mage.test.serverside.base.CardTestPlayerBase;
89

910
/**
@@ -236,4 +237,56 @@ public void testWithSplitSpell() {
236237
assertGraveyardCount(playerA, "Breaking // Entering", 0);
237238
assertLibraryCount(playerA, "Breaking // Entering", 1);
238239
}
240+
241+
// https://github.com/magefree/mage/issues/14687
242+
@Test
243+
public void testWithXCost() {
244+
skipInitShuffling();
245+
playerA.getLibrary().clear();
246+
addCard(Zone.LIBRARY, playerA, "Lotus Petal");
247+
addCard(Zone.LIBRARY, playerA, "Dwarven Trader");
248+
addCard(Zone.HAND, playerA, "Fireball");
249+
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
250+
addCard(Zone.BATTLEFIELD, playerA, "Maelstrom Nexus");
251+
252+
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fireball");
253+
setChoice(playerA, "X=4");
254+
addTarget(playerA, playerB);
255+
addTarget(playerA, TestPlayer.TARGET_SKIP);
256+
setChoice(playerA, true);
257+
258+
setStrictChooseMode(true);
259+
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
260+
execute();
261+
262+
assertPermanentCount(playerA, "Dwarven Trader", 1);
263+
assertPermanentCount(playerA, "Lotus Petal", 0);
264+
assertGraveyardCount(playerA, "Fireball", 1);
265+
assertLife(playerB, 16);
266+
}
267+
268+
@Test
269+
public void testRemovedFromStack() {
270+
skipInitShuffling();
271+
playerA.getLibrary().clear();
272+
addCard(Zone.LIBRARY, playerA, "Dwarven Trader");
273+
addCard(Zone.HAND, playerA, "Balduvian Bears");
274+
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
275+
addCard(Zone.HAND, playerB, "Unsubstantiate");
276+
addCard(Zone.BATTLEFIELD, playerB, "Island", 2);
277+
addCard(Zone.BATTLEFIELD, playerA, "Maelstrom Nexus");
278+
279+
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears");
280+
setChoice(playerA, true);
281+
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Unsubstantiate");
282+
addTarget(playerB, "Balduvian Bears");
283+
284+
setStrictChooseMode(true);
285+
setStopAt(1, PhaseStep.PRECOMBAT_MAIN);
286+
execute();
287+
288+
assertPermanentCount(playerA, "Dwarven Trader", 1);
289+
assertPermanentCount(playerA, "Balduvian Bears", 0);
290+
assertHandCount(playerA, "Balduvian Bears", 1);
291+
}
239292
}

Mage/src/main/java/mage/abilities/keyword/CascadeAbility.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import mage.game.stack.Spell;
1818
import mage.players.Player;
1919
import mage.target.common.TargetCardInExile;
20+
import mage.target.targetpointer.FixedTarget;
2021
import mage.util.CardUtil;
2122

2223
/**
@@ -79,6 +80,7 @@ public boolean checkEventType(GameEvent event, Game game) {
7980
@Override
8081
public boolean checkTrigger(GameEvent event, Game game) {
8182
Spell spell = game.getStack().getSpell(event.getTargetId());
83+
this.getEffects().setTargetPointer(new FixedTarget(event.getTargetId()));
8284
return spell != null
8385
&& spell.getSourceId().equals(this.getSourceId());
8486
}
@@ -111,14 +113,14 @@ public boolean apply(Game game, Ability source) {
111113
if (controller == null) {
112114
return false;
113115
}
114-
Card sourceCard = game.getCard(source.getSourceId());
115-
if (sourceCard == null) {
116+
Spell sourceSpell = game.getSpellOrLKIStack(this.getTargetPointer().getFirst(game, source));
117+
if (sourceSpell == null) {
116118
return false;
117119
}
118120

119121
// exile cards from the top of your library until you exile a nonland card whose converted mana cost is less than this spell's converted mana cost
120122
Cards cardsToExile = new CardsImpl();
121-
int sourceCost = sourceCard.getManaValue();
123+
int sourceCost = sourceSpell.getManaValue();
122124
Card cardToCast = null;
123125
for (Card card : controller.getLibrary().getCards(game)) {
124126
cardsToExile.add(card);

0 commit comments

Comments
 (0)