CardFactoryUtil: Disguise Keyword

This commit is contained in:
Hans Mackowiak
2024-01-20 22:13:02 +01:00
committed by Chris H
parent 6639da3f20
commit ff3ea852b7
14 changed files with 215 additions and 81 deletions

View File

@@ -310,6 +310,9 @@ public abstract class GameState {
if (c.isManifested()) {
newText.append(":Manifested");
}
if (c.isCloaked()) {
newText.append(":Cloaked");
}
}
if (c.getCurrentStateName().equals(CardStateName.Transformed)) {
newText.append("|Transformed");
@@ -1280,6 +1283,9 @@ public abstract class GameState {
if (info.endsWith("Manifested")) {
c.setManifested(true);
}
if (info.endsWith("Cloaked")) {
c.setCloaked(true);
}
} else if (info.startsWith("Transformed")) {
c.setState(CardStateName.Transformed, true);
c.setBackSide(true);

View File

@@ -389,6 +389,9 @@ public class GameCopier {
if (c.isManifested()) {
newCard.setManifested(true);
}
if (c.isCloaked()) {
newCard.setCloaked(true);
}
}
if (c.isMonstrous()) {
newCard.setMonstrous(true);

View File

@@ -23,7 +23,9 @@ public final class ImageKeys {
public static final String HIDDEN_CARD = "hidden";
public static final String MORPH_IMAGE = "morph";
public static final String DISGUISED_IMAGE = "disguised";
public static final String MANIFEST_IMAGE = "manifest";
public static final String CLOAKED_IMAGE = "cloaked";
public static final String FORETELL_IMAGE = "foretell";
public static final String BACKFACE_POSTFIX = "$alt";
@@ -406,7 +408,7 @@ public final class ImageKeys {
CardEdition ed = StaticData.instance().getEditions().get(setFolder);
if (ed != null && !editionAlias.containsKey(setFolder)) {
String alias = ed.getAlias();
Set aliasSet = new HashSet<>();
Set<String> aliasSet = new HashSet<>();
if (alias != null) {
if (!alias.equalsIgnoreCase(setFolder))
aliasSet.add(alias);

View File

@@ -189,7 +189,7 @@ public class GameAction {
if (c.isSplitCard()) {
boolean resetToOriginal = false;
if (c.isManifested()) {
if (c.isManifested() || c.isCloaked()) {
if (fromBattlefield) {
// Make sure the card returns from the battlefield as the original card with two halves
resetToOriginal = true;
@@ -351,7 +351,7 @@ public class GameAction {
ReplacementResult repres = game.getReplacementHandler().run(ReplacementType.Moved, repParams);
if (repres != ReplacementResult.NotReplaced && repres != ReplacementResult.Updated) {
// reset failed manifested Cards back to original
if (c.isManifested() && !c.isInPlay()) {
if ((c.isManifested() || c.isCloaked()) && !c.isInPlay()) {
c.forceTurnFaceUp();
}

View File

@@ -323,7 +323,7 @@ public class PlayEffect extends SpellAbilityEffect {
if (sa.hasParam("CastFaceDown")) {
// For Illusionary Mask effect
tgtSA = CardFactoryUtil.abilityMorphDown(tgtCard.getCurrentState(), false);
tgtSA = CardFactoryUtil.abilityCastFaceDown(tgtCard.getCurrentState(), false, "Morph");
} else {
tgtSA = controller.getController().getAbilityToPlay(tgtCard, sas);
}

View File

@@ -161,10 +161,8 @@ public class SetStateEffect extends SpellAbilityEffect {
}
boolean hasTransformed = false;
if (sa.isMorphUp()) {
if (sa.isTurnFaceUp()) {
hasTransformed = gameCard.turnFaceUp(sa);
} else if (sa.isManifestUp()) {
hasTransformed = gameCard.turnFaceUp(true, true, sa);
} else if ("Specialize".equals(mode)) {
hasTransformed = gameCard.changeCardState(mode, host.getChosenColor(), sa);
host.setChosenColors(null);
@@ -182,6 +180,12 @@ public class SetStateEffect extends SpellAbilityEffect {
} else if (sa.isManifestUp()) {
String sb = p + " has unmanifested " + gameCard.getName();
game.getGameLog().add(GameLogEntryType.STACK_RESOLVE, sb);
} else if (sa.isDisguiseUp()) {
String sb = p + " has undisguised " + gameCard.getName();
game.getGameLog().add(GameLogEntryType.STACK_RESOLVE, sb);
} else if (sa.isCloakUp()) {
String sb = p + " has uncloaked " + gameCard.getName();
game.getGameLog().add(GameLogEntryType.STACK_RESOLVE, sb);
} else if (hiddenAgenda) {
if (gameCard.hasKeyword("Double agenda")) {
String sb = p + " has revealed " + gameCard.getName() + " with the chosen names: " +

View File

@@ -221,6 +221,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
private boolean suspected = false;
private boolean manifested;
private boolean cloaked;
private boolean foretold;
private boolean foretoldCostByEffect;
@@ -516,6 +517,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
// Cleared tests, about to change states
if (currentStateName.equals(CardStateName.FaceDown) && state.equals(CardStateName.Original)) {
this.setManifested(false);
this.setCloaked(false);
}
currentStateName = state;
@@ -732,6 +734,32 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
return c;
}
public Card cloak(Player p, SpellAbility sa, Map<AbilityKey, Object> params) {
// Turn Face Down (even if it's DFC).
// Sometimes cards are manifested while already being face down
if (!turnFaceDown(true) && !isFaceDown()) {
return null;
}
// Just in case you aren't the controller, now you are!
setController(p, game.getNextTimestamp());
// Mark this card as "cloaked"
setCloaked(true);
// give it Ward:2
getFaceDownState().addIntrinsicKeyword("Ward:2", true);
// Move to p's battlefield
Card c = game.getAction().moveToPlay(this, p, sa, params);
if (c.isInPlay()) {
c.setCloaked(true);
c.turnFaceDown(true);
c.updateStateForView();
}
return c;
}
public boolean turnFaceDown() {
return turnFaceDown(false);
}
@@ -762,58 +790,52 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
}
public boolean turnFaceUp(SpellAbility cause) {
return turnFaceUp(false, true, cause);
return turnFaceUp(true, cause);
}
public boolean turnFaceUp(boolean manifestPaid, boolean runTriggers, SpellAbility cause) {
if (isFaceDown()) {
if (manifestPaid && isManifested() && !getRules().getType().isCreature()) {
// If we've manifested a non-creature and we're demanifesting disallow it
// Unless this creature also has a Morph ability
return false;
}
CardCollectionView cards = hasMergedCard() ? getMergedCards() : new CardCollection(this);
boolean retResult = false;
for (final Card c : cards) {
boolean result;
if (c.isFlipped() && c.isFlipCard()) {
result = c.setState(CardStateName.Flipped, true);
} else {
result = c.setState(CardStateName.Original, true);
}
c.facedown = false;
c.turnedFaceUpThisTurn = true;
c.updateStateForView(); //fixes cards with backside viewable
// need to run faceup commands, currently
// it does cleanup the modified facedown state
if (result) {
c.runFaceupCommands();
}
retResult = retResult || result;
}
if (retResult && hasMergedCard()) {
removeMutatedStates();
rebuildMutatedStates(cause);
game.getTriggerHandler().clearActiveTriggers(this, null);
game.getTriggerHandler().registerActiveTrigger(this, false);
}
if (retResult && runTriggers) {
// Run replacement effects
getGame().getReplacementHandler().run(ReplacementType.TurnFaceUp, AbilityKey.mapFromAffected(this));
// Run triggers
final Map<AbilityKey, Object> runParams = AbilityKey.mapFromCard(this);
runParams.put(AbilityKey.Cause, cause);
getGame().getTriggerHandler().registerActiveTrigger(this, false);
getGame().getTriggerHandler().runTrigger(TriggerType.TurnFaceUp, runParams, false);
}
return retResult;
public boolean turnFaceUp(boolean runTriggers, SpellAbility cause) {
if (!isFaceDown()) {
return false;
}
return false;
CardCollectionView cards = hasMergedCard() ? getMergedCards() : new CardCollection(this);
boolean retResult = false;
for (final Card c : cards) {
boolean result;
if (c.isFlipped() && c.isFlipCard()) {
result = c.setState(CardStateName.Flipped, true);
} else {
result = c.setState(CardStateName.Original, true);
}
c.facedown = false;
c.turnedFaceUpThisTurn = true;
c.updateStateForView(); //fixes cards with backside viewable
// need to run faceup commands, currently
// it does cleanup the modified facedown state
if (result) {
c.runFaceupCommands();
}
retResult = retResult || result;
}
if (retResult && hasMergedCard()) {
removeMutatedStates();
rebuildMutatedStates(cause);
game.getTriggerHandler().clearActiveTriggers(this, null);
game.getTriggerHandler().registerActiveTrigger(this, false);
}
if (retResult && runTriggers) {
// Run replacement effects
getGame().getReplacementHandler().run(ReplacementType.TurnFaceUp, AbilityKey.mapFromAffected(this));
// Run triggers
final Map<AbilityKey, Object> runParams = AbilityKey.mapFromCard(this);
runParams.put(AbilityKey.Cause, cause);
getGame().getTriggerHandler().registerActiveTrigger(this, false);
getGame().getTriggerHandler().runTrigger(TriggerType.TurnFaceUp, runParams, false);
}
return retResult;
}
public boolean wasTurnedFaceUpThisTurn() {
@@ -2143,6 +2165,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
} else if (keyword.startsWith("Ripple")) {
sbLong.append(TextUtil.fastReplace(keyword, ":", " ")).append("\r\n");
} else if (keyword.startsWith("Morph") || keyword.startsWith("Megamorph")
|| keyword.startsWith("Disguise")
|| keyword.startsWith("Escape") || keyword.startsWith("Foretell:")
|| keyword.startsWith("Madness:")|| keyword.startsWith("Recover")
|| keyword.startsWith("Reconfigure") || keyword.startsWith("Squad")
@@ -2615,6 +2638,9 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
if (manifested) {
sb.append("Manifested\r\n");
}
if (cloaked) {
sb.append("Cloaked\r\n");
}
String keywordText = keywordsToText(getUnhiddenKeywords(state));
sb.append(keywordText).append(keywordText.length() > 0 ? linebreak : "");
@@ -3172,7 +3198,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
return false;
}
for (SpellAbility sa : getSpellAbilities()) {
if (!(sa instanceof SpellPermanent && sa.isBasicSpell()) && !sa.isMorphUp()) {
if (!(sa instanceof SpellPermanent && sa.isBasicSpell()) && !sa.isMorphUp() && !sa.isDisguiseUp()) {
return false;
}
}
@@ -3206,7 +3232,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
if (isInPlay()) {
if ((null == mana || false == mana) && isFaceDown() && state.getView().getState() == CardStateName.FaceDown) {
for (SpellAbility sa : getState(CardStateName.Original).getNonManaAbilities()) {
if (sa.isManifestUp() || sa.isMorphUp()) {
if (sa.isTurnFaceUp()) {
list.add(sa);
}
}
@@ -4425,6 +4451,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
perpetual.add(p);
}
@SuppressWarnings("unchecked")
public final void executePerpetual(Map<String, Object> p) {
final String category = (String) p.get("Category");
if (category.equals("NewPT")) {
@@ -6269,6 +6296,13 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
this.manifested = manifested;
}
public final boolean isCloaked() {
return cloaked;
}
public final void setCloaked(final boolean cloaked) {
this.cloaked = cloaked;
}
public final boolean isForetold() {
// in exile and foretold
if (this.isInZone(ZoneType.Exile)) {
@@ -7061,10 +7095,13 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
}
}
if (isInPlay() && isFaceDown() && isManifested()) {
ManaCost cost = oState.getManaCost();
if (oState.getType().isCreature()) {
abilities.add(CardFactoryUtil.abilityManifestFaceUp(this, cost));
if (isInPlay() && isFaceDown() && oState.getType().isCreature())
{
if (isManifested()) {
abilities.add(oState.getManifestUp());
}
if (isCloaked()) {
abilities.add(oState.getCloakUp());
}
}
@@ -7387,7 +7424,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
public void forceTurnFaceUp() {
getGame().getTriggerHandler().suppressMode(TriggerType.TurnFaceUp);
turnFaceUp(false, false, null);
turnFaceUp(false, null);
getGame().getTriggerHandler().clearSuppression(TriggerType.TurnFaceUp);
}

View File

@@ -102,7 +102,7 @@ public class CardFactoryUtil {
*
* @return a {@link forge.game.spellability.SpellAbility} object.
*/
public static SpellAbility abilityMorphDown(final CardState cardState, final boolean intrinsic) {
public static SpellAbility abilityCastFaceDown(final CardState cardState, final boolean intrinsic, String key) {
final Spell morphDown = new Spell(cardState.getCard(), new Cost(ManaCost.THREE, false)) {
private static final long serialVersionUID = -1438810964807867610L;
@@ -111,13 +111,16 @@ public class CardFactoryUtil {
if (!hostCard.isFaceDown()) {
hostCard.setOriginalStateAsFaceDown();
}
CardFactoryUtil.setFaceDownState(hostCard, this);
final Game game = hostCard.getGame();
Map<AbilityKey, Object> moveParams = AbilityKey.newMap();
moveParams.put(AbilityKey.LastStateBattlefield, game.copyLastStateBattlefield());
moveParams.put(AbilityKey.LastStateGraveyard, game.copyLastStateGraveyard());
CardZoneTable table = new CardZoneTable(game.copyLastStateBattlefield(), game.copyLastStateBattlefield());
Map<AbilityKey, Object> params = AbilityKey.newMap();
params.put(AbilityKey.LastStateBattlefield, table.getLastStateBattlefield());
params.put(AbilityKey.LastStateGraveyard, table.getLastStateGraveyard());
params.put(AbilityKey.InternalTriggerTable, table);
hostCard.getGame().getAction().moveToPlay(hostCard, this, moveParams);
hostCard.getGame().getAction().moveToPlay(hostCard, this, params);
}
@Override
@@ -138,9 +141,8 @@ public class CardFactoryUtil {
morphDown.setCardState(cardState);
morphDown.setDescription("(You may cast this card face down as a 2/2 creature for {3}.)");
morphDown.setStackDescription("Morph - Creature 2/2");
morphDown.setStackDescription(key + " - Creature 2/2");
morphDown.setCastFaceDown(true);
morphDown.setBasicSpell(false);
morphDown.setIntrinsic(intrinsic);
@@ -187,18 +189,48 @@ public class CardFactoryUtil {
return morphUp;
}
public static SpellAbility abilityDisguiseUp(final CardState cardState, final String costStr, final boolean intrinsic) {
Cost cost = new Cost(costStr, true);
StringBuilder sbCost = new StringBuilder("Disguise");
sbCost.append(" ");
if (!cost.isOnlyManaCost()) {
sbCost.append("");
}
sbCost.append(cost.toString());
public static SpellAbility abilityManifestFaceUp(final Card sourceCard, final ManaCost manaCost) {
StringBuilder sb = new StringBuilder();
sb.append("ST$ SetState | Cost$ ").append(costStr).append(" | CostDesc$ ").append(sbCost);
sb.append(" | DisguiseUp$ True | Secondary$ True | IsPresent$ Card.Self+faceDown");
sb.append(" | Mode$ TurnFaceUp | SpellDescription$ (Turn this face up any time for its disguise cost.)");
final SpellAbility morphUp = AbilityFactory.getAbility(sb.toString(), cardState);
// if Cost has X in cost, need to check source for an SVar for this
if (cost.hasXInAnyCostPart() && cardState.hasSVar("X")) {
morphUp.setSVar("X", cardState.getSVar("X"));
}
final StringBuilder sbStack = new StringBuilder();
sbStack.append(cardState.getName()).append(" - turn this card face up.");
morphUp.setStackDescription(sbStack.toString());
morphUp.setIntrinsic(intrinsic);
return morphUp;
}
public static SpellAbility abilityTurnFaceUp(final CardState sourceCard, String key, String desc) {
final ManaCost manaCost = sourceCard.getManaCost();
String costDesc = manaCost.toString();
// Cost need to be set later
StringBuilder sb = new StringBuilder();
sb.append("ST$ SetState | Cost$ 0 | CostDesc$ Unmanifest ").append(costDesc);
sb.append(" | ManifestUp$ True | Secondary$ True | PresentDefined$ Self | IsPresent$ Card.faceDown+manifested");
sb.append(" | Mode$ TurnFaceUp | SpellDescription$ (Turn this face up any time for its mana cost.)");
sb.append("ST$ SetState | Cost$ 0 | ").append("PrecostDesc$ ").append(desc).append(" | CostDesc$ ").append(costDesc);
sb.append(" | ").append(key).append("$ True | Secondary$ True | Mode$ TurnFaceUp | SpellDescription$ (Turn this face up any time for its mana cost.)");
final SpellAbility manifestUp = AbilityFactory.getAbility(sb.toString(), sourceCard);
manifestUp.setPayCosts(new Cost(manaCost, true));
manifestUp.rebuiltDescription();
final StringBuilder sbStack = new StringBuilder();
sbStack.append(sourceCard.getName()).append(" - turn this card face up.");
@@ -2760,6 +2792,13 @@ public class CardFactoryUtil {
newSA.setAlternativeCost(AlternativeCost.Dash);
newSA.setIntrinsic(intrinsic);
inst.addSpellAbility(newSA);
} else if (keyword.startsWith("Disguise")) {
final String[] k = keyword.split(":");
SpellAbility faceDown = abilityCastFaceDown(card, intrinsic, "Disguise");
faceDown.putParam("FaceDownKeyword", "Ward:2");
inst.addSpellAbility(faceDown);
inst.addSpellAbility(abilityDisguiseUp(card, k[1], intrinsic));
} else if (keyword.startsWith("Disturb")) {
final String[] k = keyword.split(":");
final Cost disturbCost = new Cost(k[1], true);
@@ -3128,12 +3167,12 @@ public class CardFactoryUtil {
} else if (keyword.startsWith("Morph")) {
final String[] k = keyword.split(":");
inst.addSpellAbility(abilityMorphDown(card, intrinsic));
inst.addSpellAbility(abilityCastFaceDown(card, intrinsic, "Morph"));
inst.addSpellAbility(abilityMorphUp(card, k[1], false, intrinsic));
} else if (keyword.startsWith("Megamorph")) {
final String[] k = keyword.split(":");
inst.addSpellAbility(abilityMorphDown(card, intrinsic));
inst.addSpellAbility(abilityCastFaceDown(card, intrinsic, "Morph"));
inst.addSpellAbility(abilityMorphUp(card, k[1], true, intrinsic));
} else if (keyword.startsWith("More Than Meets the Eye")) {
final String[] n = keyword.split(":");
@@ -4018,9 +4057,12 @@ public class CardFactoryUtil {
if (sa.hasParam("FaceDownSetType")) {
faceDown.setType(new CardType(Arrays.asList(sa.getParam("FaceDownSetType").split(" & ")), false));
}
if (sa.hasParam("FaceDownKeyword")) {
faceDown.addIntrinsicKeywords(Arrays.asList(sa.getParam("FaceDownKeyword").split(" & ")));
}
if (sa.hasParam("FaceDownPower") || sa.hasParam("FaceDownToughness")
|| sa.hasParam("FaceDownSetType")) {
|| sa.hasParam("FaceDownSetType") || sa.hasParam("FaceDownKeyword")) {
final GameCommand unanimate = new GameCommand() {
private static final long serialVersionUID = 8853789549297846163L;

View File

@@ -1124,10 +1124,14 @@ public class CardProperty {
if (card.isPhasedOut()) {
return false;
}
} else if (property.startsWith("manifested")) {
} else if (property.equals("manifested")) {
if (!card.isManifested()) {
return false;
}
} else if (property.equals("cloaked")) {
if (!card.isCloaked()) {
return false;
}
} else if (property.startsWith("DrawnThisTurn")) {
if (!card.getDrawnThisTurn()) {
return false;

View File

@@ -86,6 +86,9 @@ public class CardState extends GameObject implements IHasSVars {
private ReplacementEffect battleTypeRep;
private ReplacementEffect sagaRep;
private SpellAbility manifestUp;
private SpellAbility cloakUp;
public CardState(Card card, CardStateName name) {
this(card.getView().createAlternateState(name), card);
}
@@ -759,4 +762,16 @@ public class CardState extends GameObject implements IHasSVars {
return n;
}
public SpellAbility getManifestUp() {
if (this.manifestUp == null) {
manifestUp = CardFactoryUtil.abilityTurnFaceUp(this, "ManifestUp", "Unmanifest");
}
return manifestUp;
}
public SpellAbility getCloakUp() {
if (this.cloakUp == null) {
cloakUp = CardFactoryUtil.abilityTurnFaceUp(this, "CloakUp", "Uncloak");
}
return cloakUp;
}
}

View File

@@ -145,6 +145,9 @@ public class CardView extends GameEntityView {
public boolean isManifested() {
return get(TrackableProperty.Manifested);
}
public boolean isCloaked() {
return get(TrackableProperty.Cloaked);
}
public boolean isFlipCard() {
return get(TrackableProperty.FlipCard);
@@ -948,6 +951,7 @@ public class CardView extends GameEntityView {
set(TrackableProperty.Facedown, c.isFaceDown());
set(TrackableProperty.Foretold, c.isForetold());
set(TrackableProperty.Manifested, c.isManifested());
set(TrackableProperty.Cloaked, c.isCloaked());
set(TrackableProperty.Adventure, c.isAdventureCard());
set(TrackableProperty.DoubleFaced, c.isDoubleFaced());
set(TrackableProperty.Modal, c.isModal());
@@ -1230,8 +1234,13 @@ public class CardView extends GameEntityView {
if (getCard().getZone() == ZoneType.Exile) {
return ImageKeys.getTokenKey(getCard().isForeTold() ? ImageKeys.FORETELL_IMAGE : ImageKeys.HIDDEN_CARD);
}
return ImageKeys.getTokenKey(getCard().isManifested() ? ImageKeys.MANIFEST_IMAGE
: getType().getCreatureTypes().isEmpty() ? isCreature() ? ImageKeys.MORPH_IMAGE : ImageKeys.HIDDEN_CARD
if (getCard().isManifested()) {
return ImageKeys.getTokenKey(ImageKeys.MANIFEST_IMAGE);
} else if (getCard().isCloaked()) {
return ImageKeys.getTokenKey(ImageKeys.CLOAKED_IMAGE);
}
return ImageKeys.getTokenKey(getType().getCreatureTypes().isEmpty() ? isCreature() ? ImageKeys.MORPH_IMAGE : ImageKeys.HIDDEN_CARD
: getType().getCreatureTypes().toString().toLowerCase().replace(" ", "_").replace("[", "").replace("]",""));
}
if (canBeShownToAny(viewers)) {

View File

@@ -61,6 +61,7 @@ public enum Keyword {
DETHRONE("Dethrone", SimpleKeyword.class, false, "Whenever this creature attacks the player with the most life or tied for the most life, put a +1/+1 counter on it."),
DEVOUR("Devour", KeywordWithAmount.class, false, "As this creature enters the battlefield, you may sacrifice any number of creatures. This creature enters the battlefield with {%d:+1/+1 counter} on it for each creature sacrificed this way."),
DEVOID("Devoid", SimpleKeyword.class, true, "This card has no color."),
DISGUISE("Disguise", KeywordWithCost.class, false, "You may cast this card face down for {3} as a 2/2 creature with ward {2}. Turn it face up any time for its disguise cost."),
DISTURB("Disturb", KeywordWithCost.class, false, "You may cast this card from your graveyard transformed for its disturb cost."),
DOCTORS_COMPANION("Doctor's companion", Partner.class, true, "You can have two commanders if the other is the Doctor."),
DOUBLE_STRIKE("Double Strike", SimpleKeyword.class, true, "This creature deals both first-strike and regular combat damage."),

View File

@@ -519,9 +519,16 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
public boolean isAbility() { return true; }
public boolean isActivatedAbility() { return false; }
public boolean isTurnFaceUp() {
return isMorphUp() || isDisguiseUp() || isManifestUp() || isCloakUp();
}
public boolean isMorphUp() {
return this.hasParam("MorphUp");
}
public boolean isDisguiseUp() {
return this.hasParam("DisguiseUp");
}
public boolean isCastFaceDown() {
return false;
@@ -530,6 +537,9 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
public boolean isManifestUp() {
return hasParam("ManifestUp");
}
public boolean isCloakUp() {
return hasParam("CloakUp");
}
public boolean isCycling() {
return isAlternativeCost(AlternativeCost.Cycling);
@@ -1060,7 +1070,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
}
public boolean isBasicSpell() {
return basicSpell && this.altCost == null && getRootAbility().optionalCosts.isEmpty();
return basicSpell && !isCastFaceDown() && this.altCost == null && getRootAbility().optionalCosts.isEmpty();
}
public void setBasicSpell(final boolean basicSpell0) {
basicSpell = basicSpell0;

View File

@@ -32,6 +32,7 @@ public enum TrackableProperty {
Facedown(TrackableTypes.BooleanType),
Foretold(TrackableTypes.BooleanType),
Manifested(TrackableTypes.BooleanType),
Cloaked(TrackableTypes.BooleanType),
Modal(TrackableTypes.BooleanType),
Adventure(TrackableTypes.BooleanType),
DoubleFaced(TrackableTypes.BooleanType),