mirror of
https://github.com/correl/mage.git
synced 2025-01-12 19:25:44 +00:00
* GUI: added card icon for announced X value (card cast);
This commit is contained in:
parent
fc0ff6c22d
commit
76082e1d7a
9 changed files with 353 additions and 12 deletions
|
@ -7,10 +7,12 @@ import mage.abilities.Abilities;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.Effects;
|
||||
import mage.abilities.icon.CardIcon;
|
||||
import mage.abilities.icon.other.FaceDownStatusIcon;
|
||||
import mage.abilities.icon.other.FaceDownCardIcon;
|
||||
import mage.abilities.icon.other.VariableCostCardIcon;
|
||||
import mage.abilities.keyword.AftermathAbility;
|
||||
import mage.cards.*;
|
||||
import mage.cards.mock.MockCard;
|
||||
|
@ -369,7 +371,7 @@ public class CardView extends SimpleCardView {
|
|||
this.manaCostRightStr = String.join("", mainCard.getRightHalfCard().getManaCostSymbols());
|
||||
} else if (card instanceof AdventureCard) {
|
||||
AdventureCard adventureCard = ((AdventureCard) card);
|
||||
AdventureCardSpell adventureCardSpell = ((AdventureCardSpell) adventureCard.getSpellCard());
|
||||
AdventureCardSpell adventureCardSpell = adventureCard.getSpellCard();
|
||||
fullCardName = adventureCard.getName() + MockCard.ADVENTURE_NAME_SEPARATOR + adventureCardSpell.getName();
|
||||
this.manaCostLeftStr = String.join("", adventureCardSpell.getManaCostSymbols());
|
||||
this.manaCostRightStr = String.join("", adventureCard.getManaCostSymbols());
|
||||
|
@ -420,11 +422,10 @@ public class CardView extends SimpleCardView {
|
|||
permanent.getAbilities(game).forEach(ability -> {
|
||||
this.cardIcons.addAll(ability.getIcons(game));
|
||||
});
|
||||
// other
|
||||
// face down
|
||||
if (permanent.isFaceDown(game)) {
|
||||
this.cardIcons.add(FaceDownStatusIcon.instance);
|
||||
this.cardIcons.add(FaceDownCardIcon.instance);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (card.isCopy()) {
|
||||
this.mageObjectType = MageObjectType.COPY_CARD;
|
||||
|
@ -439,6 +440,25 @@ public class CardView extends SimpleCardView {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// card icons for any permanents and cards
|
||||
if (game != null) {
|
||||
// x cost
|
||||
Zone cardZone = game.getState().getZone(card.getId());
|
||||
if (card.getManaCost().containsX()
|
||||
&& (cardZone.match(Zone.BATTLEFIELD) || cardZone.match(Zone.STACK))) {
|
||||
int costX;
|
||||
if (card instanceof Permanent) {
|
||||
// permanent on battlefield
|
||||
costX = ManacostVariableValue.ETB.calculate(game, card.getSpellAbility(), null);
|
||||
} else {
|
||||
// other like Stack
|
||||
costX = ManacostVariableValue.REGULAR.calculate(game, card.getSpellAbility(), null);
|
||||
}
|
||||
this.cardIcons.add(new VariableCostCardIcon(costX));
|
||||
}
|
||||
}
|
||||
|
||||
this.power = Integer.toString(card.getPower().getValue());
|
||||
this.toughness = Integer.toString(card.getToughness().getValue());
|
||||
this.cardTypes = card.getCardType(game);
|
||||
|
|
|
@ -9,6 +9,7 @@ import mage.cards.SplitCard;
|
|||
import mage.cards.repository.CardRepository;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.util.CardUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
@ -522,6 +523,138 @@ public class CopySpellTest extends CardTestPlayerBase {
|
|||
assertAllCommandsUsed();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_CopiedSpellsAndX_1() {
|
||||
// testing:
|
||||
// 1. x in copied instant spell (copy X)
|
||||
// 2. x in copied creature (X=0)
|
||||
|
||||
// test use case with rules:
|
||||
// https://tappedout.net/mtg-questions/copying-a-creature-with-x-in-its-mana-cost/#c3561513
|
||||
// 107.3f If a card in any zone other than the stack has an {X} in its mana cost, the value of {X} is
|
||||
// treated as 0, even if the value of X is defined somewhere within its text.
|
||||
|
||||
// Whenever you cast an instant or sorcery spell, you may pay {U}{R}. If you do, copy that spell. You may choose new targets for the copy.
|
||||
// Whenever another nontoken creature enters the battlefield under your control, you may pay {G}{U}. If you do, create a token that’s a copy of that creature.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Riku of Two Reflections", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||
//
|
||||
// Banefire deals X damage to any target.
|
||||
addCard(Zone.HAND, playerA, "Banefire", 1); // {X}{R}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||
//
|
||||
// 0/0
|
||||
// Capricopian enters the battlefield with X +1/+1 counters on it.
|
||||
addCard(Zone.HAND, playerA, "Capricopian", 1); // {X}{G}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
|
||||
|
||||
// 1
|
||||
// cast banefire and make copy
|
||||
// announced X=2 must be copied
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}", 3);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Banefire", playerB);
|
||||
setChoice(playerA, "X=2");
|
||||
setChoice(playerA, "Yes"); // make copy
|
||||
setChoice(playerA, "No"); // keep target same
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkLife("after spell copy", 1, PhaseStep.PRECOMBAT_MAIN, playerB, 20 - 2 * 2);
|
||||
|
||||
// 2
|
||||
// cast creature and copy it as token
|
||||
// token must have x=0 (dies)
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Capricopian");
|
||||
setChoice(playerA, "X=1");
|
||||
setChoice(playerA, "Yes"); // make copy
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkPermanentCount("after creature copy", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Capricopian", 1);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_CopiedSpellsHasntETB() {
|
||||
// testing:
|
||||
// - x in copied creature spell (copy x)
|
||||
// - copied spells enters as tokens and it hasn't ETB, see rules below
|
||||
|
||||
// 0/0
|
||||
// Capricopian enters the battlefield with X +1/+1 counters on it.
|
||||
addCard(Zone.HAND, playerA, "Capricopian", 1); // {X}{G}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
|
||||
//
|
||||
// Grenzo, Dungeon Warden enters the battlefield with X +1/+1 counters on it.
|
||||
addCard(Zone.HAND, playerA, "Grenzo, Dungeon Warden", 1);// {X}{B}{R}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||
//
|
||||
// Copy target creature spell you control, except it isn't legendary if the spell is legendary.
|
||||
// (A copy of a creature spell becomes a token.)
|
||||
addCard(Zone.HAND, playerA, "Double Major", 2); // {G}{U}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
|
||||
|
||||
// 1. Capricopian
|
||||
// cast and put on stack
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G}", 3);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Capricopian");
|
||||
setChoice(playerA, "X=2");
|
||||
// copy of spell
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G}", 1);
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {U}", 1);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Double Major", "Capricopian", "Capricopian");
|
||||
|
||||
// 2. Grenzo, Dungeon Warden
|
||||
// cast and put on stack
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G}", 2);
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}", 1);
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}", 1);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grenzo, Dungeon Warden");
|
||||
setChoice(playerA, "X=2");
|
||||
// copy of spell
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G}", 1);
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {U}", 1);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Double Major", "Grenzo, Dungeon Warden", "Grenzo, Dungeon Warden");
|
||||
|
||||
// ETB triggers will not trigger here due not normal cast. From rules:
|
||||
// - The token that a resolving copy of a spell becomes isn’t said to have been “created.” (2021-04-16)
|
||||
// - A nontoken permanent “enters the battlefield” when it’s moved onto the battlefield from another zone.
|
||||
// A token “enters the battlefield” when it’s created. See rules 403.3, 603.6a, 603.6d, and 614.12.
|
||||
//
|
||||
// So both copies enters without counters:
|
||||
// - Capricopian copy must die
|
||||
// - Grenzo, Dungeon Warden must have default PT
|
||||
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkPermanentCount("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Capricopian", 1); // copy dies
|
||||
checkPermanentCount("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grenzo, Dungeon Warden", 2);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
// counters checks
|
||||
int originalCounters = currentGame.getBattlefield().getAllActivePermanents().stream()
|
||||
.filter(p -> p.getName().equals("Grenzo, Dungeon Warden"))
|
||||
.filter(p -> !p.isCopy())
|
||||
.mapToInt(p -> p.getCounters(currentGame).getCount(CounterType.P1P1))
|
||||
.sum();
|
||||
int copyCounters = currentGame.getBattlefield().getAllActivePermanents().stream()
|
||||
.filter(p -> p.getName().equals("Grenzo, Dungeon Warden"))
|
||||
.filter(p -> p.isCopy())
|
||||
.mapToInt(p -> p.getCounters(currentGame).getCount(CounterType.P1P1))
|
||||
.sum();
|
||||
Assert.assertEquals("original grenzo must have 2x counters", 2, originalCounters);
|
||||
Assert.assertEquals("copied grenzo must have 0x counters", 0, copyCounters);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_SimpleCopy_Card() {
|
||||
Card sourceCard = CardRepository.instance.findCard("Grizzly Bears").getCard();
|
||||
|
@ -628,7 +761,7 @@ public class CopySpellTest extends CardTestPlayerBase {
|
|||
return;
|
||||
}
|
||||
|
||||
Assert.fail(infoPrefix + " - " + "ability source must be same: " + ability.toString());
|
||||
Assert.fail(infoPrefix + " - " + "ability source must be same: " + ability);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
package org.mage.test.serverside;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import mage.view.CardView;
|
||||
import mage.view.GameView;
|
||||
import mage.view.PlayerView;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* GUI tests: card icons for cards
|
||||
*
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class CardIconsTest extends CardTestPlayerBase {
|
||||
|
||||
@Test
|
||||
public void test_CostX_Spells() {
|
||||
// Chalice of the Void enters the battlefield with X charge counters on it.
|
||||
// Whenever a player casts a spell with converted mana cost equal to the number of charge counters on Chalice of the Void, counter that spell.
|
||||
addCard(Zone.HAND, playerA, "Chalice of the Void", 1); // {X}{X}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
|
||||
|
||||
// hand (not visible)
|
||||
runCode("card icons in hand", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> {
|
||||
GameView gameView = getGameView(player);
|
||||
Assert.assertEquals("must have 1 card in hand", 1, gameView.getHand().values().size());
|
||||
CardView cardView = gameView.getHand().values().stream().findFirst().get();
|
||||
Assert.assertEquals("must have non x cost card icons in hand", 0, cardView.getCardIcons().size());
|
||||
});
|
||||
|
||||
// cast and put on stack
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Chalice of the Void");
|
||||
setChoice(playerA, "X=2");
|
||||
|
||||
// stack (visible)
|
||||
runCode("card icons on stack (spell)", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> {
|
||||
GameView gameView = getGameView(player);
|
||||
Assert.assertEquals("must have 1 card in stack", 1, gameView.getStack().values().size());
|
||||
CardView cardView = gameView.getStack().values().stream().findFirst().get();
|
||||
Assert.assertEquals("must have x cost card icons in stack", 1, cardView.getCardIcons().size());
|
||||
Assert.assertEquals("x cost text", "x=2", cardView.getCardIcons().get(0).getText());
|
||||
});
|
||||
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkPermanentCount("after cast", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Chalice of the Void", 1);
|
||||
|
||||
// battlefield (card, not visible)
|
||||
runCode("card icons in battlefield (card)", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> {
|
||||
GameView gameView = getGameView(player);
|
||||
PlayerView playerView = gameView.getPlayers().get(0);
|
||||
Assert.assertEquals("player", player.getName(), playerView.getName());
|
||||
CardView cardView = playerView.getBattlefield().values().stream().filter(p -> p.getName().equals("Chalice of the Void")).findFirst().orElse(null);
|
||||
Assert.assertNotNull("must have 1 chalice in battlefield", cardView);
|
||||
Assert.assertEquals("must have x cost card icons in battlefield (card)", 1, cardView.getCardIcons().size());
|
||||
Assert.assertEquals("x cost text", "x=2", cardView.getCardIcons().get(0).getText());
|
||||
});
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_CostX_Copies() {
|
||||
// Grenzo, Dungeon Warden enters the battlefield with X +1/+1 counters on it.
|
||||
addCard(Zone.HAND, playerA, "Grenzo, Dungeon Warden", 1);// {X}{B}{R}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||
//
|
||||
// Copy target creature spell you control, except it isn't legendary if the spell is legendary.
|
||||
addCard(Zone.HAND, playerA, "Double Major", 1); // {G}{U}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
|
||||
// cast and put on stack
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G}", 2);
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}", 1);
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}", 1);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grenzo, Dungeon Warden");
|
||||
setChoice(playerA, "X=2");
|
||||
|
||||
// prepare copy of spell
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G}", 1);
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {U}", 1);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Double Major", "Grenzo, Dungeon Warden", "Grenzo, Dungeon Warden");
|
||||
checkStackSize("before copy spell", 1, PhaseStep.PRECOMBAT_MAIN, playerA, 2);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA, true);
|
||||
checkStackSize("after copy spell", 1, PhaseStep.PRECOMBAT_MAIN, playerA, 2);
|
||||
|
||||
// stack (copied spell)
|
||||
runCode("card icons on stack (copied spell)", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> {
|
||||
GameView gameView = getGameView(player);
|
||||
Assert.assertEquals("must have 2 cards in stack", 2, gameView.getStack().values().size());
|
||||
CardView originalCardView = gameView.getStack().values()
|
||||
.stream()
|
||||
.filter(c -> !c.getOriginalCard().isCopy())
|
||||
.findFirst()
|
||||
.get();
|
||||
CardView copiedCardView = gameView.getStack().values()
|
||||
.stream()
|
||||
.filter(c -> c.getOriginalCard().isCopy())
|
||||
.findFirst()
|
||||
.get();
|
||||
Assert.assertNotNull("stack must have original spell", originalCardView);
|
||||
Assert.assertNotNull("stack must have copied spell", copiedCardView);
|
||||
Assert.assertNotEquals("must find two spells on stack", originalCardView.getId(), copiedCardView.getId());
|
||||
Assert.assertEquals("original spell must have x cost card icons", 1, originalCardView.getCardIcons().size());
|
||||
Assert.assertEquals("copied spell must have x cost card icons", 1, copiedCardView.getCardIcons().size());
|
||||
Assert.assertEquals("original x cost text", "x=2", originalCardView.getCardIcons().get(0).getText());
|
||||
Assert.assertEquals("copied x cost text", "x=2", copiedCardView.getCardIcons().get(0).getText());
|
||||
});
|
||||
|
||||
// must resolve copied creature spell as a token
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkPermanentCount("after cast", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grenzo, Dungeon Warden", 2);
|
||||
|
||||
// battlefield (card and copied card as token)
|
||||
runCode("card icons in battlefield (copied)", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> {
|
||||
GameView gameView = getGameView(player);
|
||||
PlayerView playerView = gameView.getPlayers().get(0);
|
||||
Assert.assertEquals("player", player.getName(), playerView.getName());
|
||||
// copied spell goes as token to battlefield, not copied card - so must check isToken
|
||||
// original
|
||||
CardView originalCardView = playerView.getBattlefield().values()
|
||||
.stream()
|
||||
.filter(p -> p.getName().equals("Grenzo, Dungeon Warden"))
|
||||
.filter(p -> !p.isToken())
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
Assert.assertNotNull("original card must be in battlefield", originalCardView);
|
||||
Assert.assertEquals("original must have x cost card icons", 1, originalCardView.getCardIcons().size());
|
||||
Assert.assertEquals("original x cost text", "x=2", originalCardView.getCardIcons().get(0).getText());
|
||||
//
|
||||
CardView copiedCardView = playerView.getBattlefield().values()
|
||||
.stream()
|
||||
.filter(p -> p.getName().equals("Grenzo, Dungeon Warden"))
|
||||
.filter(p -> p.isToken())
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
Assert.assertNotNull("copied card must be in battlefield", copiedCardView);
|
||||
Assert.assertEquals("copied must have x cost card icons", 1, copiedCardView.getCardIcons().size());
|
||||
Assert.assertEquals("copied x cost text", "x=0", copiedCardView.getCardIcons().get(0).getText());
|
||||
});
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
}
|
||||
}
|
|
@ -7,7 +7,9 @@ import mage.game.Game;
|
|||
import mage.watchers.common.ManaSpentToCastWatcher;
|
||||
|
||||
public enum ManacostVariableValue implements DynamicValue {
|
||||
REGULAR, ETB;
|
||||
|
||||
REGULAR, // if you need X on cast/activate (in stack)
|
||||
ETB; // if you need X after ETB (in battlefield)
|
||||
|
||||
@Override
|
||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||
|
@ -15,7 +17,10 @@ public enum ManacostVariableValue implements DynamicValue {
|
|||
return sourceAbility.getManaCostsToPay().getX();
|
||||
}
|
||||
ManaSpentToCastWatcher watcher = game.getState().getWatcher(ManaSpentToCastWatcher.class);
|
||||
return watcher != null ? watcher.getAndResetLastXValue(sourceAbility.getSourceId()) : sourceAbility.getManaCostsToPay().getX();
|
||||
if (watcher != null) {
|
||||
return watcher.getAndResetLastXValue(sourceAbility);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -32,6 +32,7 @@ public enum CardIconType {
|
|||
ABILITY_CLASS_LEVEL("prepared/hexagon-fill.svg", CardIconCategory.ABILITY, 100),
|
||||
//
|
||||
OTHER_FACEDOWN("prepared/reply-fill.svg", CardIconCategory.ABILITY, 100),
|
||||
OTHER_COST_X("prepared/square-fill.svg", CardIconCategory.ABILITY, 100),
|
||||
//
|
||||
SYSTEM_COMBINED("prepared/square-fill.svg", CardIconCategory.SYSTEM, 1000), // inner usage, must use last order
|
||||
SYSTEM_DEBUG("prepared/link.svg", CardIconCategory.SYSTEM, 1000); // used for test render dialog
|
||||
|
|
|
@ -6,7 +6,7 @@ import mage.abilities.icon.CardIconType;
|
|||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public enum FaceDownStatusIcon implements CardIcon {
|
||||
public enum FaceDownCardIcon implements CardIcon {
|
||||
instance;
|
||||
|
||||
@Override
|
|
@ -0,0 +1,16 @@
|
|||
package mage.abilities.icon.other;
|
||||
|
||||
import mage.abilities.icon.CardIconImpl;
|
||||
import mage.abilities.icon.CardIconType;
|
||||
|
||||
/**
|
||||
* Showing x cost value
|
||||
*
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class VariableCostCardIcon extends CardIconImpl {
|
||||
|
||||
public VariableCostCardIcon(int costX) {
|
||||
super(CardIconType.OTHER_COST_X, "Announced X = " + costX, "x=" + costX);
|
||||
}
|
||||
}
|
|
@ -81,7 +81,11 @@ public class CopyTokenFunction implements Function<Token, Card> {
|
|||
|
||||
for (Ability ability0 : sourceObj.getAbilities()) {
|
||||
Ability ability = ability0.copy();
|
||||
ability.newOriginalId(); // The token is independant from the copy from object so it need a new original Id, otherwise there are problems to check for created continuous effects to check if the source (the Token) has still this ability
|
||||
|
||||
// The token is independant from the copy from object so it need a new original Id,
|
||||
// otherwise there are problems to check for created continuous effects to check if
|
||||
// the source (the Token) has still this ability
|
||||
ability.newOriginalId();
|
||||
|
||||
target.addAbility(ability);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package mage.watchers.common;
|
||||
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
|
@ -51,8 +52,14 @@ public class ManaSpentToCastWatcher extends Watcher {
|
|||
return manaMap.getOrDefault(sourceId, null);
|
||||
}
|
||||
|
||||
public int getAndResetLastXValue(UUID sourceId) {
|
||||
return xValueMap.getOrDefault(sourceId, 0);
|
||||
public int getAndResetLastXValue(Ability source) {
|
||||
if (xValueMap.containsKey(source.getSourceId())) {
|
||||
// cast normal way
|
||||
return xValueMap.get(source.getSourceId());
|
||||
} else {
|
||||
// put to battlefield without cast (example: copied spell must keep announced X)
|
||||
return source.getManaCostsToPay().getX();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in a new issue