mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 10:48:00 +00:00
CardFactoryUtil: Disguise Keyword
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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: " +
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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."),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user