diff --git a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java index b1fe62567bf..2ab4d392c64 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java +++ b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java @@ -310,7 +310,8 @@ public class GameCopier { newCard.setManifested(true); // TODO: Should be able to copy other abilities... if (isCreature && hasManaCost) { - newCard.addSpellAbility(CardFactoryUtil.abilityManifestFaceUp(newCard, newCard.getManaCost())); + newCard.getState(CardStateName.Original).addSpellAbility( + CardFactoryUtil.abilityManifestFaceUp(newCard, newCard.getManaCost())); } } } diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index ece24a74a2f..f200b4a930d 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -528,30 +528,30 @@ public class Card extends GameEntity implements Comparable { public Card manifest(Player p, SpellAbility sa) { // Turn Face Down (even if it's DFC). - CardState originalCard = this.getState(CardStateName.Original); - ManaCost cost = originalCard.getManaCost(); + ManaCost cost = getState(CardStateName.Original).getManaCost(); - boolean isCreature = this.isCreature(); + boolean isCreature = isCreature(); - // Sometimes cards are manifested while already being face down - if (!turnFaceDown(true) && currentStateName != CardStateName.FaceDown) { - return null; - } + // Sometimes cards are manifested while already being face down + if (!turnFaceDown(true) && !isFaceDown()) { + return null; + } // Move to p's battlefield Game game = p.getGame(); - // Just in case you aren't the controller, now you are! - this.setController(p, game.getNextTimestamp()); + + // Just in case you aren't the controller, now you are! + setController(p, game.getNextTimestamp()); // Mark this card as "manifested" - this.setPreFaceDownState(CardStateName.Original); - this.setManifested(true); + setPreFaceDownState(CardStateName.Original); + setManifested(true); Card c = game.getAction().moveToPlay(this, p, sa); // Add manifest demorph static ability for creatures if (isCreature && !cost.isNoCost()) { - c.addSpellAbility(CardFactoryUtil.abilityManifestFaceUp(c, cost)); - + // Add Manifest to original State + c.getState(CardStateName.Original).addSpellAbility(CardFactoryUtil.abilityManifestFaceUp(c, cost)); c.updateStateForView(); } @@ -2233,6 +2233,16 @@ public class Card extends GameEntity implements Comparable { updateBasicLandAbilities(list, state); } + // add Facedown abilities from Original state but only if this state is face down + // need CardStateView#getState or might crash in StackOverflow + if ((mana == null || mana == false) && isFaceDown() && state.getView().getState() == CardStateName.FaceDown) { + for (SpellAbility sa : getState(CardStateName.Original).getNonManaAbilities()) { + if (sa.isManifestUp() || sa.isMorphUp()) { + list.add(sa); + } + } + } + for (KeywordInterface kw : getUnhiddenKeywords(state)) { for (SpellAbility sa : kw.getAbilities()) { if (mana == null || mana == sa.isManaAbility()) { diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java index 65cebaa7191..f467b6658ca 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -136,27 +136,27 @@ public class CardFactoryUtil { public static SpellAbility abilityMorphUp(final Card sourceCard, final String costStr, final boolean mega) { Cost cost = new Cost(costStr, true); String costDesc = cost.toString(); - // get rid of the ": " at the end - costDesc = costDesc.substring(0, costDesc.length() - 2); - + StringBuilder sbCost = new StringBuilder(mega ? "Megamorph" : "Morph"); + sbCost.append(" "); if (!cost.isOnlyManaCost()) { - costDesc = "—" + costDesc; + sbCost.append("— "); } + // get rid of the ": " at the end + sbCost.append(costDesc.substring(0, costDesc.length() - 2)); - String ab = "ST$ SetState | Cost$ " + costStr + " | CostDesc$ Morph" + costDesc - + " | MorphUp$ True" - + " | ConditionDefined$ Self | ConditionPresent$ Card.faceDown" - + " | Mode$ TurnFace | SpellDescription$ (Turn this face up any time for its morph cost.)"; + StringBuilder sb = new StringBuilder(); + sb.append("ST$ SetState | Cost$ ").append(costStr).append(" | CostDesc$ ").append(sbCost); + sb.append(" | MorphUp$ True | Secondary$ True | IsPresent$ Card.Self+faceDown"); if (mega) { - ab += " | Mega$ True"; + sb.append(" | Mega$ True"); } + sb.append(" | Mode$ TurnFace | SpellDescription$ (Turn this face up any time for its morph cost.)"); - final SpellAbility morphUp = AbilityFactory.getAbility(ab, sourceCard); + final SpellAbility morphUp = AbilityFactory.getAbility(sb.toString(), sourceCard); final StringBuilder sbStack = new StringBuilder(); sbStack.append(sourceCard.getName()).append(" - turn this card face up."); morphUp.setStackDescription(sbStack.toString()); - morphUp.setIsMorphUp(true); return morphUp; } @@ -166,18 +166,17 @@ public class CardFactoryUtil { String costDesc = manaCost.toString(); // Cost need to be set later - String ab = "ST$ SetState | Cost$ 0 | CostDesc$ Unmanifest " + costDesc - + " | ManifestUp$ True" - + " | ConditionDefined$ Self | ConditionPresent$ Card.faceDown+manifested" - + " | Mode$ TurnFace | SpellDescription$ (Turn this face up any time for its mana cost.)"; + StringBuilder sb = new StringBuilder(); + sb.append("ST$ SetState | Cost$ 0 | CostDesc$ Unmanifest ").append(costDesc); + sb.append(" | ManifestUp$ True | Secondary$ True | IsPresent$ Card.Self+faceDown+manifested"); + sb.append(" | Mode$ TurnFace | SpellDescription$ (Turn this face up any time for its mana cost.)"); - final SpellAbility manifestUp = AbilityFactory.getAbility(ab, sourceCard); + final SpellAbility manifestUp = AbilityFactory.getAbility(sb.toString(), sourceCard); manifestUp.setPayCosts(new Cost(manaCost, true)); final StringBuilder sbStack = new StringBuilder(); sbStack.append(sourceCard.getName()).append(" - turn this card face up."); manifestUp.setStackDescription(sbStack.toString()); - manifestUp.setIsManifestUp(true); return manifestUp; } @@ -4037,22 +4036,12 @@ public class CardFactoryUtil { final String[] k = keyword.split(":"); inst.addSpellAbility(abilityMorphDown(card)); - - CardState state = card.getState(CardStateName.FaceDown); - state.setSVars(card.getSVars()); - KeywordInterface facedownKeyword = Keyword.getInstance(""); - facedownKeyword.addSpellAbility(abilityMorphUp(card, k[1], false)); - state.addIntrinsicKeywords(Lists.newArrayList(facedownKeyword)); + inst.addSpellAbility(abilityMorphUp(card, k[1], false)); } else if (keyword.startsWith("Megamorph")){ final String[] k = keyword.split(":"); inst.addSpellAbility(abilityMorphDown(card)); - - CardState state = card.getState(CardStateName.FaceDown); - state.setSVars(card.getSVars()); - KeywordInterface facedownKeyword = Keyword.getInstance(""); - facedownKeyword.addSpellAbility(abilityMorphUp(card, k[1], true)); - state.addIntrinsicKeywords(Lists.newArrayList(facedownKeyword)); + inst.addSpellAbility(abilityMorphUp(card, k[1], true)); } else if (keyword.startsWith("Multikicker")) { final String[] n = keyword.split(":"); final SpellAbility sa = card.getFirstSpellAbility(); diff --git a/forge-game/src/main/java/forge/game/card/CardState.java b/forge-game/src/main/java/forge/game/card/CardState.java index 5372ddfa18e..97bfad4ff04 100644 --- a/forge-game/src/main/java/forge/game/card/CardState.java +++ b/forge-game/src/main/java/forge/game/card/CardState.java @@ -69,6 +69,10 @@ public class CardState extends GameObject { private final CardStateView view; private final Card card; + public CardState(Card card, CardStateName name) { + this(card.getView().createAlternateState(name), card); + } + public CardState(CardStateView view0, Card card0) { view = view0; card = card0; diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java index 853c29b21f4..818aa487a9a 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -107,8 +107,6 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit private boolean spectacle = false; private boolean offering = false; private boolean emerge = false; - private boolean morphup = false; - private boolean manifestUp = false; private boolean cumulativeupkeep = false; private boolean outlast = false; private boolean blessing = false; @@ -372,22 +370,15 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit public boolean isAbility() { return true; } public boolean isMorphUp() { - return morphup; + return this.hasParam("MorphUp"); } public boolean isCastFaceDown() { return false; } - public final void setIsMorphUp(final boolean b) { - morphup = b; - } - public boolean isManifestUp() { - return manifestUp; - } - public final void setIsManifestUp(final boolean b) { - manifestUp = b; + return hasParam("ManifestUp"); } public boolean isCycling() {