From e7bb796d48a647daac9dff5f23843f506dd598bc Mon Sep 17 00:00:00 2001 From: magenoxx Date: Sat, 17 Sep 2011 16:47:28 +0400 Subject: [PATCH] Double-faced cards support --- .../src/main/java/mage/client/cards/Card.java | 5 + .../java/org/mage/card/arcane/CardPanel.java | 46 +- Mage.Common/src/mage/cards/MageCard.java | 1 + Mage.Common/src/mage/view/CardView.java | 467 ++++++++------- Mage.Common/src/mage/view/PermanentView.java | 1 + Mage/src/mage/Constants.java | 1 + .../effects/common/TransformSourceEffect.java | 81 +++ .../abilities/keyword/TransformAbility.java | 122 ++++ Mage/src/mage/cards/Card.java | 4 + Mage/src/mage/cards/CardImpl.java | 561 +++++++++--------- Mage/src/mage/cards/ExpansionSet.java | 7 +- Mage/src/mage/game/events/GameEvent.java | 1 + Mage/src/mage/game/permanent/Permanent.java | 4 + .../mage/game/permanent/PermanentCard.java | 6 + .../mage/game/permanent/PermanentImpl.java | 23 + Mage/src/mage/game/stack/Spell.java | 17 +- 16 files changed, 847 insertions(+), 500 deletions(-) create mode 100644 Mage/src/mage/abilities/effects/common/TransformSourceEffect.java create mode 100644 Mage/src/mage/abilities/keyword/TransformAbility.java diff --git a/Mage.Client/src/main/java/mage/client/cards/Card.java b/Mage.Client/src/main/java/mage/client/cards/Card.java index 9820594010c..fec25cc8409 100644 --- a/Mage.Client/src/main/java/mage/client/cards/Card.java +++ b/Mage.Client/src/main/java/mage/client/cards/Card.java @@ -521,4 +521,9 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis @Override public void toggleTransformed() { } + + @Override + public boolean isTransformed() { + return false; + } } diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanel.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanel.java index 4d6c5572094..d931a7f346e 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/CardPanel.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardPanel.java @@ -57,8 +57,12 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti static private final int DEFAULT_DELAY_PERIOD = 300; public CardView gameCard; - //public List attachedPanels = new ArrayList(); + + // for two faced cards + public CardView temporary; + private List links = new ArrayList(); + public double tappedAngle = 0; public double flippedAngle = 0; public ScaledImagePanel imagePanel; @@ -110,13 +114,14 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti buttonPanel = new JPanel(); buttonPanel.setLayout(null); buttonPanel.setOpaque(false); - buttonPanel.setVisible(false); add(buttonPanel); dayNightButton = new JButton(""); dayNightButton.setLocation(2, 2); dayNightButton.setSize(25, 25); + buttonPanel.setVisible(this.gameCard.canTransform()); + BufferedImage day = ImageManagerImpl.getInstance().getDayImage(); dayNightButton.setIcon(new ImageIcon(day)); @@ -125,10 +130,13 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti dayNightButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - if (animationInProgress) { - return; - } - if (isTapped()) { + // if card is being rotated, ignore action performed + // if card is tapped, no visual transforming is possible (implementation limitation) + // if card is permanent, it will be rotated by Mage, so manual rotate should be possible + if (animationInProgress || isTapped() || isPermanent) { + if (isPermanent) { + JOptionPane.showMessageDialog(null, "You can't transform cards on battlefield."); + } return; } Animation.transformCard(CardPanel.this, CardPanel.this, true); @@ -569,6 +577,14 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti return false; } + @Override + public boolean isTransformed() { + if (isPermanent) { + return gameCard.isTransformed(); + } + return false; + } + @Override public void onBeginAnimation() { animationInProgress = true; @@ -587,6 +603,10 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti if (needsTapping || needsFlipping) { Animation.tapCardToggle(this, this, needsTapping, needsFlipping); } + boolean needsTranforming = isTransformed() != card.isTransformed(); + if (needsTranforming) { + Animation.transformCard(this, this, card.isTransformed()); + } } if (CardUtil.isCreature(card) && CardUtil.isPlaneswalker(card)) { ptText.setText(card.getPower() + "/" + card.getToughness() + " (" + card.getLoyalty() + ")"); @@ -821,9 +841,23 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti if (transformed) { BufferedImage night = ImageManagerImpl.getInstance().getNightImage(); dayNightButton.setIcon(new ImageIcon(night)); + this.temporary = this.gameCard; + if (this.gameCard.getSecondCardFace() == null) { + return; + } + if (!isPermanent) { + update(this.gameCard.getSecondCardFace()); + } + updateImage(); } else { BufferedImage day = ImageManagerImpl.getInstance().getDayImage(); dayNightButton.setIcon(new ImageIcon(day)); + this.gameCard = this.temporary; + this.temporary = null; + if (!isPermanent) { + update(this.gameCard); + } + updateImage(); } } } diff --git a/Mage.Common/src/mage/cards/MageCard.java b/Mage.Common/src/mage/cards/MageCard.java index 321c45baa46..d7ed7f5eb33 100644 --- a/Mage.Common/src/mage/cards/MageCard.java +++ b/Mage.Common/src/mage/cards/MageCard.java @@ -28,4 +28,5 @@ public abstract class MageCard extends JPanel { abstract public String getZone(); abstract public void updateCallback(ActionCallback callback, UUID gameId); abstract public void toggleTransformed(); + abstract public boolean isTransformed(); } diff --git a/Mage.Common/src/mage/view/CardView.java b/Mage.Common/src/mage/view/CardView.java index 7fbffdb6b3e..d84800c1c2a 100644 --- a/Mage.Common/src/mage/view/CardView.java +++ b/Mage.Common/src/mage/view/CardView.java @@ -28,14 +28,10 @@ package mage.view; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -import mage.MageObject; -import mage.ObjectColor; import mage.Constants.CardType; import mage.Constants.Rarity; +import mage.MageObject; +import mage.ObjectColor; import mage.cards.Card; import mage.counters.CounterType; import mage.game.permanent.Permanent; @@ -45,157 +41,170 @@ import mage.game.stack.Spell; import mage.target.Target; import mage.target.Targets; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + /** * @author BetaSteward_at_googlemail.com */ public class CardView extends SimpleCardView { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - protected UUID parentId; - protected String name; - protected List rules; - protected String power; - protected String toughness; - protected String loyalty; - protected List cardTypes; - protected List subTypes; - protected List superTypes; - protected ObjectColor color; - protected List manaCost; - protected int convertedManaCost; - protected Rarity rarity; - protected boolean isAbility; - protected CardView ability; + protected UUID parentId; + protected String name; + protected List rules; + protected String power; + protected String toughness; + protected String loyalty; + protected List cardTypes; + protected List subTypes; + protected List superTypes; + protected ObjectColor color; + protected List manaCost; + protected int convertedManaCost; + protected Rarity rarity; + protected boolean isAbility; + protected CardView ability; - public List targets; + protected boolean canTransform; + protected CardView secondCardFace; + protected boolean transformed; + + public List targets; public CardView(Card card, UUID cardId) { this(card); this.id = cardId; } - - public CardView(Card card) { + + public CardView(Card card) { super(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.isFaceDown()); - // no information available for face down cards - if (this.faceDown) { - fillEmpty(); - return; - } + // no information available for face down cards + if (this.faceDown) { + fillEmpty(); + return; + } - this.name = card.getName(); - this.rules = card.getRules(); - if (card instanceof Permanent) { - this.power = Integer.toString(card.getPower().getValue()); - this.toughness = Integer.toString(card.getToughness().getValue()); - this.loyalty = Integer.toString(((Permanent) card).getCounters().getCount(CounterType.LOYALTY)); - } else { - this.power = card.getPower().toString(); - this.toughness = card.getToughness().toString(); - this.loyalty = ""; - } - this.cardTypes = card.getCardType(); - this.subTypes = card.getSubtype(); - this.superTypes = card.getSupertype(); - this.color = card.getColor(); - this.manaCost = card.getManaCost().getSymbols(); - this.convertedManaCost = card.getManaCost().convertedManaCost(); - if (card instanceof PermanentToken) { - this.rarity = Rarity.COMMON; - } else { - this.rarity = card.getRarity(); - } + this.name = card.getName(); + this.rules = card.getRules(); + if (card instanceof Permanent) { + this.power = Integer.toString(card.getPower().getValue()); + this.toughness = Integer.toString(card.getToughness().getValue()); + this.loyalty = Integer.toString(((Permanent) card).getCounters().getCount(CounterType.LOYALTY)); + } else { + this.power = card.getPower().toString(); + this.toughness = card.getToughness().toString(); + this.loyalty = ""; + } + this.cardTypes = card.getCardType(); + this.subTypes = card.getSubtype(); + this.superTypes = card.getSupertype(); + this.color = card.getColor(); + this.manaCost = card.getManaCost().getSymbols(); + this.convertedManaCost = card.getManaCost().convertedManaCost(); + this.canTransform = card.canTransform(); + if (card instanceof PermanentToken) { + this.rarity = Rarity.COMMON; + } else { + this.rarity = card.getRarity(); + } - if (card instanceof Spell) { - Spell spell = (Spell) card; - if (spell.getSpellAbility().getTargets().size() > 0) { - setTargets(spell.getSpellAbility().getTargets()); - } - } - } + if (card.getSecondCardFace() != null) { + this.secondCardFace = new CardView(card.getSecondCardFace()); + } - public CardView(MageObject card) { - super(card.getId(), "", 0, false); + if (card instanceof Spell) { + Spell spell = (Spell) card; + if (spell.getSpellAbility().getTargets().size() > 0) { + setTargets(spell.getSpellAbility().getTargets()); + } + } + } - this.name = card.getName(); - if (card instanceof Permanent) { - this.power = Integer.toString(card.getPower().getValue()); - this.toughness = Integer.toString(card.getToughness().getValue()); - this.loyalty = Integer.toString(((Permanent) card).getCounters().getCount(CounterType.LOYALTY)); - } else { - this.power = card.getPower().toString(); - this.toughness = card.getToughness().toString(); - this.loyalty = ""; - } - this.cardTypes = card.getCardType(); - this.subTypes = card.getSubtype(); - this.superTypes = card.getSupertype(); - this.color = card.getColor(); - this.manaCost = card.getManaCost().getSymbols(); - this.convertedManaCost = card.getManaCost().convertedManaCost(); - if (card instanceof PermanentToken) { - this.rarity = Rarity.COMMON; - this.expansionSetCode = ((PermanentToken)card).getExpansionSetCode(); - this.rules = ((PermanentToken)card).getRules(); - } - } + public CardView(MageObject card) { + super(card.getId(), "", 0, false); - protected CardView() { + this.name = card.getName(); + if (card instanceof Permanent) { + this.power = Integer.toString(card.getPower().getValue()); + this.toughness = Integer.toString(card.getToughness().getValue()); + this.loyalty = Integer.toString(((Permanent) card).getCounters().getCount(CounterType.LOYALTY)); + } else { + this.power = card.getPower().toString(); + this.toughness = card.getToughness().toString(); + this.loyalty = ""; + } + this.cardTypes = card.getCardType(); + this.subTypes = card.getSubtype(); + this.superTypes = card.getSupertype(); + this.color = card.getColor(); + this.manaCost = card.getManaCost().getSymbols(); + this.convertedManaCost = card.getManaCost().convertedManaCost(); + if (card instanceof PermanentToken) { + this.rarity = Rarity.COMMON; + this.expansionSetCode = ((PermanentToken) card).getExpansionSetCode(); + this.rules = ((PermanentToken) card).getRules(); + } + } + + protected CardView() { super(null, "", 0, false); - } + } - public CardView(boolean empty) { - super(null, "", 0, false); - if (!empty) { - throw new IllegalArgumentException("Not supported."); - } - fillEmpty(); - } + public CardView(boolean empty) { + super(null, "", 0, false); + if (!empty) { + throw new IllegalArgumentException("Not supported."); + } + fillEmpty(); + } private void fillEmpty() { - this.name = "Face Down"; - this.rules = new ArrayList(); - this.power = ""; - this.toughness = ""; - this.loyalty = ""; - this.cardTypes = new ArrayList(); - this.subTypes = new ArrayList(); - this.superTypes = new ArrayList(); - this.color = new ObjectColor(); - this.manaCost = new ArrayList(); - this.convertedManaCost = 0; - this.rarity = Rarity.COMMON; - this.expansionSetCode = ""; - this.cardNumber = 0; - } + this.name = "Face Down"; + this.rules = new ArrayList(); + this.power = ""; + this.toughness = ""; + this.loyalty = ""; + this.cardTypes = new ArrayList(); + this.subTypes = new ArrayList(); + this.superTypes = new ArrayList(); + this.color = new ObjectColor(); + this.manaCost = new ArrayList(); + this.convertedManaCost = 0; + this.rarity = Rarity.COMMON; + this.expansionSetCode = ""; + this.cardNumber = 0; + } - CardView(Token token) { + CardView(Token token) { super(token.getId(), "", 0, false); - this.id = token.getId(); - this.name = token.getName(); - this.rules = token.getAbilities().getRules(this.name); - this.power = token.getPower().toString(); - this.toughness = token.getToughness().toString(); - this.loyalty = ""; - this.cardTypes = token.getCardType(); - this.subTypes = token.getSubtype(); - this.superTypes = token.getSupertype(); - this.color = token.getColor(); - this.manaCost = token.getManaCost().getSymbols(); - this.rarity = Rarity.NA; - //this.expansionSetCode = ""; - } + this.id = token.getId(); + this.name = token.getName(); + this.rules = token.getAbilities().getRules(this.name); + this.power = token.getPower().toString(); + this.toughness = token.getToughness().toString(); + this.loyalty = ""; + this.cardTypes = token.getCardType(); + this.subTypes = token.getSubtype(); + this.superTypes = token.getSupertype(); + this.color = token.getColor(); + this.manaCost = token.getManaCost().getSymbols(); + this.rarity = Rarity.NA; + //this.expansionSetCode = ""; + } - protected void setTargets(Targets targets) { - for (Target target : targets) { - if (target.isChosen()) { - for (UUID targetUUID : target.getTargets()) { - if (this.targets == null) this.targets = new ArrayList(); - this.targets.add(targetUUID); - } - } - } - } + protected void setTargets(Targets targets) { + for (Target target : targets) { + if (target.isChosen()) { + for (UUID targetUUID : target.getTargets()) { + if (this.targets == null) this.targets = new ArrayList(); + this.targets.add(targetUUID); + } + } + } + } // protected List formatRules(List rules) { // List newRules = new ArrayList(); @@ -211,120 +220,132 @@ public class CardView extends SimpleCardView { // return replace; // } - public String getName() { - return name; - } + public String getName() { + return name; + } - public List getRules() { - return rules; - } + public List getRules() { + return rules; + } - public void overrideRules(List rules) { - this.rules = rules; - } + public void overrideRules(List rules) { + this.rules = rules; + } - public void setIsAbility(boolean isAbility) { - this.isAbility = isAbility; - } + public void setIsAbility(boolean isAbility) { + this.isAbility = isAbility; + } - public boolean isAbility() { - return isAbility; - } + public boolean isAbility() { + return isAbility; + } - public String getPower() { - return power; - } + public String getPower() { + return power; + } - public String getToughness() { - return toughness; - } + public String getToughness() { + return toughness; + } - public String getLoyalty() { - return loyalty; - } + public String getLoyalty() { + return loyalty; + } - public List getCardTypes() { - return cardTypes; - } + public List getCardTypes() { + return cardTypes; + } - public List getSubTypes() { - return subTypes; - } + public List getSubTypes() { + return subTypes; + } - public List getSuperTypes() { - return superTypes; - } + public List getSuperTypes() { + return superTypes; + } - public ObjectColor getColor() { - return color; - } + public ObjectColor getColor() { + return color; + } - public List getManaCost() { - return manaCost; - } + public List getManaCost() { + return manaCost; + } - public int getConvertedManaCost() { - return convertedManaCost; - } + public int getConvertedManaCost() { + return convertedManaCost; + } - public Rarity getRarity() { - return rarity; - } + public Rarity getRarity() { + return rarity; + } - public String getExpansionSetCode() { - return expansionSetCode; - } + public String getExpansionSetCode() { + return expansionSetCode; + } - public UUID getId() { - return id; - } + public UUID getId() { + return id; + } - public int getCardNumber() { - return cardNumber; - } + public int getCardNumber() { + return cardNumber; + } - /** - * Returns UUIDs for targets. - * Can be null if there is no target selected. - * - * @return - */ - public List getTargets() { - return targets; - } + /** + * Returns UUIDs for targets. + * Can be null if there is no target selected. + * + * @return + */ + public List getTargets() { + return targets; + } - public void overrideTargets(List newTargets) { - this.targets = newTargets; - } + public void overrideTargets(List newTargets) { + this.targets = newTargets; + } - public void overrideId(UUID id) { - if (parentId == null) { - parentId = this.id; - } - this.id = id; - } + public void overrideId(UUID id) { + if (parentId == null) { + parentId = this.id; + } + this.id = id; + } - public UUID getParentId() { - if (parentId != null) { - return parentId; - } - return id; - } + public UUID getParentId() { + if (parentId != null) { + return parentId; + } + return id; + } - public void setAbility(CardView ability) { - this.ability = ability; - } + public void setAbility(CardView ability) { + this.ability = ability; + } - public CardView getAbility() { - return this.ability; - } + public CardView getAbility() { + return this.ability; + } - @Override - public String toString() { - return getName() + " [" + getId() + "]"; - } + @Override + public String toString() { + return getName() + " [" + getId() + "]"; + } - public boolean isFaceDown() { - return faceDown; - } + public boolean isFaceDown() { + return faceDown; + } + + public boolean canTransform() { + return this.canTransform; + } + + public CardView getSecondCardFace() { + return this.secondCardFace; + } + + public boolean isTransformed() { + return this.transformed; + } } diff --git a/Mage.Common/src/mage/view/PermanentView.java b/Mage.Common/src/mage/view/PermanentView.java index 0f6c6449bfa..099594406c1 100644 --- a/Mage.Common/src/mage/view/PermanentView.java +++ b/Mage.Common/src/mage/view/PermanentView.java @@ -79,6 +79,7 @@ public class PermanentView extends CardView { else { original = new CardView(card); } + this.transformed = permanent.isTransformed(); } public boolean isTapped() { diff --git a/Mage/src/mage/Constants.java b/Mage/src/mage/Constants.java index d0a5a287b1c..f3bc032a429 100644 --- a/Mage/src/mage/Constants.java +++ b/Mage/src/mage/Constants.java @@ -323,6 +323,7 @@ public final class Constants { PreventDamage(true), RedirectDamage(true), Tap(false), + Transform(true), Untap(true), Win(true), Copy(true), diff --git a/Mage/src/mage/abilities/effects/common/TransformSourceEffect.java b/Mage/src/mage/abilities/effects/common/TransformSourceEffect.java new file mode 100644 index 00000000000..334421497ef --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/TransformSourceEffect.java @@ -0,0 +1,81 @@ +/* +* Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.abilities.effects.common; + +import mage.Constants.Outcome; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author nantuko + */ +public class TransformSourceEffect extends OneShotEffect { + + private boolean withoutTrigger; + + public TransformSourceEffect() { + this(false); + } + + public TransformSourceEffect(boolean withoutTrigger) { + super(Outcome.Transform); + this.withoutTrigger = withoutTrigger; + staticText = "transform {this}"; + } + + public TransformSourceEffect(final TransformSourceEffect effect) { + super(effect); + this.withoutTrigger = effect.withoutTrigger; + } + + @Override + public TransformSourceEffect copy() { + return new TransformSourceEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + if (withoutTrigger) { + if (permanent.canTransform()) { + permanent.setTransformed(!permanent.isTransformed()); + } + } else { + permanent.transform(game); + } + return true; + } + return false; + } + +} diff --git a/Mage/src/mage/abilities/keyword/TransformAbility.java b/Mage/src/mage/abilities/keyword/TransformAbility.java new file mode 100644 index 00000000000..dde131f7aa0 --- /dev/null +++ b/Mage/src/mage/abilities/keyword/TransformAbility.java @@ -0,0 +1,122 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.abilities.keyword; + +import mage.Constants; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.cards.Card; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * @author nantuko + */ +public class TransformAbility extends SimpleStaticAbility { + + public TransformAbility() { + super(Constants.Zone.BATTLEFIELD, new TransformEffect()); + } + + public TransformAbility(final TransformAbility ability) { + super(ability); + } + + @Override + public SimpleStaticAbility copy() { + return new TransformAbility(this); + } + + @Override + public String getRule() { + return "Transform"; + } +} + +class TransformEffect extends ContinuousEffectImpl { + + public TransformEffect() { + super(Constants.Duration.WhileOnBattlefield, Constants.Layer.CopyEffects_1, Constants.SubLayer.NA, Constants.Outcome.BecomeCreature); + staticText = ""; + } + + public TransformEffect(final TransformEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (!permanent.isTransformed()) { + // keep original card + return true; + } + + Card card = permanent.getSecondCardFace(); + + permanent.setName(card.getName()); + permanent.getColor().setColor(card.getColor()); + permanent.getManaCost().clear(); + permanent.getManaCost().add(card.getManaCost()); + permanent.getCardType().clear(); + for (Constants.CardType type : card.getCardType()) { + permanent.getCardType().add(type); + } + permanent.getSubtype().clear(); + for (String type : card.getSubtype()) { + permanent.getSubtype().add(type); + } + permanent.getSupertype().clear(); + for (String type : card.getSupertype()) { + permanent.getSupertype().add(type); + } + permanent.setExpansionSetCode(card.getExpansionSetCode()); + permanent.getAbilities().clear(); + for (Ability ability : card.getAbilities()) { + permanent.addAbility(ability); + } + permanent.getPower().setValue(card.getPower().getValue()); + permanent.getToughness().setValue(card.getToughness().getValue()); + + return true; + + } + + @Override + public TransformEffect copy() { + return new TransformEffect(this); + } + + @Override + public String getText(Mode mode) { + return "You may have {this} enter the battlefield as a copy of any " + mode.getTargets().get(0).getTargetName() + " on the battlefield"; + } + +} diff --git a/Mage/src/mage/cards/Card.java b/Mage/src/mage/cards/Card.java index 6f2d31aa28c..e612d5084ac 100644 --- a/Mage/src/mage/cards/Card.java +++ b/Mage/src/mage/cards/Card.java @@ -60,6 +60,10 @@ public interface Card extends MageObject { public void setFaceDown(boolean value); public boolean isFaceDown(); + public boolean canTransform(); + public Card getSecondCardFace(); + public boolean isNightCard(); + public void assignNewId(); /** * Moves the card to the specified zone diff --git a/Mage/src/mage/cards/CardImpl.java b/Mage/src/mage/cards/CardImpl.java index d69a444ce48..397b027888c 100644 --- a/Mage/src/mage/cards/CardImpl.java +++ b/Mage/src/mage/cards/CardImpl.java @@ -33,6 +33,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.UUID; + import mage.Constants.CardType; import mage.Constants.Rarity; import mage.Constants.Zone; @@ -53,308 +54,330 @@ import mage.watchers.Watchers; import org.apache.log4j.Logger; public abstract class CardImpl> extends MageObjectImpl implements Card { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - private final static Logger logger = Logger.getLogger(CardImpl.class); + private final static Logger logger = Logger.getLogger(CardImpl.class); - protected UUID ownerId; - protected int cardNumber; - protected Watchers watchers = new Watchers(); - protected String expansionSetCode; - protected Rarity rarity; - protected boolean faceDown; + protected UUID ownerId; + protected int cardNumber; + protected Watchers watchers = new Watchers(); + protected String expansionSetCode; + protected Rarity rarity; + protected boolean faceDown; + protected boolean canTransform; + protected Card secondSideCard; + protected boolean nightCard; - public CardImpl(UUID ownerId, int cardNumber, String name, Rarity rarity, CardType[] cardTypes, String costs) { - this(ownerId, name); - this.rarity = rarity; - this.cardNumber = cardNumber; - this.cardType.addAll(Arrays.asList(cardTypes)); - this.manaCost.load(costs); - if (cardType.contains(CardType.LAND)) - addAbility(new PlayLandAbility(name)); - else - addAbility(new SpellAbility(manaCost, name)); - } + public CardImpl(UUID ownerId, int cardNumber, String name, Rarity rarity, CardType[] cardTypes, String costs) { + this(ownerId, name); + this.rarity = rarity; + this.cardNumber = cardNumber; + this.cardType.addAll(Arrays.asList(cardTypes)); + this.manaCost.load(costs); + if (cardType.contains(CardType.LAND)) + addAbility(new PlayLandAbility(name)); + else + addAbility(new SpellAbility(manaCost, name)); + } - protected CardImpl(UUID ownerId, String name) { - this.ownerId = ownerId; - this.name = name; - } + protected CardImpl(UUID ownerId, String name) { + this.ownerId = ownerId; + this.name = name; + } - protected CardImpl(UUID id, UUID ownerId, String name) { - super(id); - this.ownerId = ownerId; - this.name = name; - } + protected CardImpl(UUID id, UUID ownerId, String name) { + super(id); + this.ownerId = ownerId; + this.name = name; + } - public CardImpl(final CardImpl card) { - super(card); - ownerId = card.ownerId; - cardNumber = card.cardNumber; - expansionSetCode = card.expansionSetCode; - rarity = card.rarity; - watchers = card.watchers.copy(); - faceDown = card.faceDown; - } + public CardImpl(final CardImpl card) { + super(card); + ownerId = card.ownerId; + cardNumber = card.cardNumber; + expansionSetCode = card.expansionSetCode; + rarity = card.rarity; + watchers = card.watchers.copy(); + faceDown = card.faceDown; - @Override - public void assignNewId() { - this.objectId = UUID.randomUUID(); - this.abilities.newId(); - this.abilities.setSourceId(objectId); + canTransform = card.canTransform; + if (canTransform) { + secondSideCard = card.secondSideCard; + nightCard = card.nightCard; + } + } + + @Override + public void assignNewId() { + this.objectId = UUID.randomUUID(); + this.abilities.newId(); + this.abilities.setSourceId(objectId); this.watchers.setSourceId(objectId); - } + } - public static Card createCard(String name) { - try { - Class theClass = Class.forName(name); - Constructor con = theClass.getConstructor(new Class[]{UUID.class}); - Card card = (Card) con.newInstance(new Object[] {null}); - return card; - } - catch (Exception e) { - logger.fatal("Error loading card: " + name, e); - return null; - } - } + public static Card createCard(String name) { + try { + Class theClass = Class.forName(name); + Constructor con = theClass.getConstructor(new Class[]{UUID.class}); + Card card = (Card) con.newInstance(new Object[]{null}); + return card; + } catch (Exception e) { + logger.fatal("Error loading card: " + name, e); + return null; + } + } - @Override - public UUID getOwnerId() { - return ownerId; - } + @Override + public UUID getOwnerId() { + return ownerId; + } - @Override - public int getCardNumber() { - return cardNumber; - } + @Override + public int getCardNumber() { + return cardNumber; + } - @Override - public Rarity getRarity() { - return rarity; - } + @Override + public Rarity getRarity() { + return rarity; + } - @Override - public void setRarity(Rarity rarity) { - this.rarity = rarity; - } + @Override + public void setRarity(Rarity rarity) { + this.rarity = rarity; + } - @Override - public List getRules() { - List rules = abilities.getRules(this.name); - if (cardType.contains(CardType.INSTANT) || cardType.contains(CardType.SORCERY)) { - rules.add(0, getSpellAbility().getRule(this.name)); - } - return rules; - } + @Override + public List getRules() { + List rules = abilities.getRules(this.name); + if (cardType.contains(CardType.INSTANT) || cardType.contains(CardType.SORCERY)) { + rules.add(0, getSpellAbility().getRule(this.name)); + } + return rules; + } + + @Override + public void addAbility(Ability ability) { + ability.setSourceId(this.getId()); + abilities.add(ability); + } - @Override - public void addAbility(Ability ability) { - ability.setSourceId(this.getId()); - abilities.add(ability); - } - @Override public void addWatcher(Watcher watcher) { watcher.setSourceId(this.getId()); watcher.setControllerId(this.ownerId); watchers.add(watcher); } - - @Override - public SpellAbility getSpellAbility() { - for (Ability ability: abilities.getActivatedAbilities(Zone.HAND)) { - if (ability instanceof SpellAbility) - return (SpellAbility)ability; - } - return null; - } - @Override - public void setControllerId(UUID controllerId) { - abilities.setControllerId(controllerId); - } + @Override + public SpellAbility getSpellAbility() { + for (Ability ability : abilities.getActivatedAbilities(Zone.HAND)) { + if (ability instanceof SpellAbility) + return (SpellAbility) ability; + } + return null; + } - @Override - public void setOwnerId(UUID ownerId) { - this.ownerId = ownerId; - abilities.setControllerId(ownerId); - } + @Override + public void setControllerId(UUID controllerId) { + abilities.setControllerId(controllerId); + } - @Override - public Watchers getWatchers() { - return watchers; - } + @Override + public void setOwnerId(UUID ownerId) { + this.ownerId = ownerId; + abilities.setControllerId(ownerId); + } - @Override - public void checkTriggers(Zone zone, GameEvent event, Game game) { - for (TriggeredAbility ability: abilities.getTriggeredAbilities(zone)) { - if (ability.checkTrigger(event, game)) { - ability.trigger(game, ownerId); - } - } - } + @Override + public Watchers getWatchers() { + return watchers; + } - @Override - public String getExpansionSetCode() { - return expansionSetCode; - } + @Override + public void checkTriggers(Zone zone, GameEvent event, Game game) { + for (TriggeredAbility ability : abilities.getTriggeredAbilities(zone)) { + if (ability.checkTrigger(event, game)) { + ability.trigger(game, ownerId); + } + } + } - @Override - public void setExpansionSetCode(String expansionSetCode) { - this.expansionSetCode = expansionSetCode; - } + @Override + public String getExpansionSetCode() { + return expansionSetCode; + } - @Override - public List getMana() { - List mana = new ArrayList(); - for (ManaAbility ability: this.abilities.getManaAbilities(Zone.BATTLEFIELD)) { - mana.add(ability.getNetMana(null)); - } - return mana; - } + @Override + public void setExpansionSetCode(String expansionSetCode) { + this.expansionSetCode = expansionSetCode; + } - @Override - public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag) { - Zone fromZone = game.getZone(objectId); - ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, toZone); - if (!game.replaceEvent(event)) { - if (event.getFromZone() != null) { - switch (event.getFromZone()) { - case GRAVEYARD: - game.getPlayer(ownerId).removeFromGraveyard(this, game); - break; - case HAND: - game.getPlayer(ownerId).removeFromHand(this, game); - break; - case LIBRARY: - game.getPlayer(ownerId).removeFromLibrary(this, game); - break; - default: - //logger.warning("moveToZone, not fully implemented: from="+event.getFromZone() + ", to="+event.getToZone()); - } - game.rememberLKI(objectId, event.getFromZone(), this); - } - switch (event.getToZone()) { - case GRAVEYARD: - game.getPlayer(ownerId).putInGraveyard(this, game, !flag); - break; - case HAND: - game.getPlayer(ownerId).getHand().add(this); - break; - case STACK: - game.getStack().push(new Spell(this, this.getSpellAbility().copy(), ownerId)); - break; - case EXILED: - game.getExile().getPermanentExile().add(this); - break; - case LIBRARY: - if (flag) - game.getPlayer(ownerId).getLibrary().putOnTop(this, game); - else - game.getPlayer(ownerId).getLibrary().putOnBottom(this, game); - break; - case BATTLEFIELD: - PermanentCard permanent = new PermanentCard(this, ownerId); - game.getBattlefield().addPermanent(permanent); - permanent.entersBattlefield(sourceId, game); - game.applyEffects(); - if (flag) - permanent.setTapped(true); - break; - } - game.setZone(objectId, event.getToZone()); - game.fireEvent(event); - return game.getZone(objectId) == toZone; - } - return false; - } + @Override + public List getMana() { + List mana = new ArrayList(); + for (ManaAbility ability : this.abilities.getManaAbilities(Zone.BATTLEFIELD)) { + mana.add(ability.getNetMana(null)); + } + return mana; + } - @Override - public boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId) { - ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, ability.getId(), controllerId, fromZone, Zone.STACK); - if (!game.replaceEvent(event)) { - if (event.getFromZone() != null) { - switch (event.getFromZone()) { - case GRAVEYARD: - game.getPlayer(ownerId).removeFromGraveyard(this, game); - break; - case HAND: - game.getPlayer(ownerId).removeFromHand(this, game); - break; - case LIBRARY: - game.getPlayer(ownerId).removeFromLibrary(this, game); - break; - default: - //logger.warning("moveToZone, not fully implemented: from="+event.getFromZone() + ", to="+event.getToZone()); - } - game.rememberLKI(objectId, event.getFromZone(), this); - } - game.getStack().push(new Spell(this, ability.copy(), controllerId)); - game.setZone(objectId, event.getToZone()); - game.fireEvent(event); - return game.getZone(objectId) == Zone.STACK; - } - return false; - } + @Override + public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag) { + Zone fromZone = game.getZone(objectId); + ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, toZone); + if (!game.replaceEvent(event)) { + if (event.getFromZone() != null) { + switch (event.getFromZone()) { + case GRAVEYARD: + game.getPlayer(ownerId).removeFromGraveyard(this, game); + break; + case HAND: + game.getPlayer(ownerId).removeFromHand(this, game); + break; + case LIBRARY: + game.getPlayer(ownerId).removeFromLibrary(this, game); + break; + default: + //logger.warning("moveToZone, not fully implemented: from="+event.getFromZone() + ", to="+event.getToZone()); + } + game.rememberLKI(objectId, event.getFromZone(), this); + } + switch (event.getToZone()) { + case GRAVEYARD: + game.getPlayer(ownerId).putInGraveyard(this, game, !flag); + break; + case HAND: + game.getPlayer(ownerId).getHand().add(this); + break; + case STACK: + game.getStack().push(new Spell(this, this.getSpellAbility().copy(), ownerId)); + break; + case EXILED: + game.getExile().getPermanentExile().add(this); + break; + case LIBRARY: + if (flag) + game.getPlayer(ownerId).getLibrary().putOnTop(this, game); + else + game.getPlayer(ownerId).getLibrary().putOnBottom(this, game); + break; + case BATTLEFIELD: + PermanentCard permanent = new PermanentCard(this, ownerId); + game.getBattlefield().addPermanent(permanent); + permanent.entersBattlefield(sourceId, game); + game.applyEffects(); + if (flag) + permanent.setTapped(true); + break; + } + game.setZone(objectId, event.getToZone()); + game.fireEvent(event); + return game.getZone(objectId) == toZone; + } + return false; + } - @Override - public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game) { - Zone fromZone = game.getZone(objectId); - ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, Zone.EXILED); - if (!game.replaceEvent(event)) { - if (fromZone != null) { - switch (fromZone) { - case GRAVEYARD: - game.getPlayer(ownerId).removeFromGraveyard(this, game); - break; - case HAND: - game.getPlayer(ownerId).removeFromHand(this, game); - break; - case LIBRARY: - game.getPlayer(ownerId).removeFromLibrary(this, game); - break; - default: - //logger.warning("moveToExile, not fully implemented: from="+fromZone); - } - game.rememberLKI(objectId, event.getFromZone(), this); - } - - if (exileId == null) { - game.getExile().getPermanentExile().add(this); - } - else { - game.getExile().createZone(exileId, name).add(this); - } - game.setZone(objectId, event.getToZone()); - game.fireEvent(event); - return true; - } - return false; - } + @Override + public boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId) { + ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, ability.getId(), controllerId, fromZone, Zone.STACK); + if (!game.replaceEvent(event)) { + if (event.getFromZone() != null) { + switch (event.getFromZone()) { + case GRAVEYARD: + game.getPlayer(ownerId).removeFromGraveyard(this, game); + break; + case HAND: + game.getPlayer(ownerId).removeFromHand(this, game); + break; + case LIBRARY: + game.getPlayer(ownerId).removeFromLibrary(this, game); + break; + default: + //logger.warning("moveToZone, not fully implemented: from="+event.getFromZone() + ", to="+event.getToZone()); + } + game.rememberLKI(objectId, event.getFromZone(), this); + } + game.getStack().push(new Spell(this, ability.copy(), controllerId)); + game.setZone(objectId, event.getToZone()); + game.fireEvent(event); + return game.getZone(objectId) == Zone.STACK; + } + return false; + } - @Override - public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId) { - PermanentCard permanent = new PermanentCard(this, controllerId); - game.getBattlefield().addPermanent(permanent); - game.setZone(objectId, Zone.BATTLEFIELD); - game.applyEffects(); - permanent.entersBattlefield(sourceId, game); - game.fireEvent(new ZoneChangeEvent(permanent, controllerId, fromZone, Zone.BATTLEFIELD)); - return true; - } + @Override + public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game) { + Zone fromZone = game.getZone(objectId); + ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, Zone.EXILED); + if (!game.replaceEvent(event)) { + if (fromZone != null) { + switch (fromZone) { + case GRAVEYARD: + game.getPlayer(ownerId).removeFromGraveyard(this, game); + break; + case HAND: + game.getPlayer(ownerId).removeFromHand(this, game); + break; + case LIBRARY: + game.getPlayer(ownerId).removeFromLibrary(this, game); + break; + default: + //logger.warning("moveToExile, not fully implemented: from="+fromZone); + } + game.rememberLKI(objectId, event.getFromZone(), this); + } - @Override - public void setCardNumber(int cid) { - this.cardNumber = cid; - } + if (exileId == null) { + game.getExile().getPermanentExile().add(this); + } else { + game.getExile().createZone(exileId, name).add(this); + } + game.setZone(objectId, event.getToZone()); + game.fireEvent(event); + return true; + } + return false; + } - @Override - public void setFaceDown(boolean value) { - this.faceDown = value; - } + @Override + public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId) { + PermanentCard permanent = new PermanentCard(this, controllerId); + game.getBattlefield().addPermanent(permanent); + game.setZone(objectId, Zone.BATTLEFIELD); + game.applyEffects(); + permanent.entersBattlefield(sourceId, game); + game.fireEvent(new ZoneChangeEvent(permanent, controllerId, fromZone, Zone.BATTLEFIELD)); + return true; + } - @Override - public boolean isFaceDown() { - return this.faceDown; - } + @Override + public void setCardNumber(int cid) { + this.cardNumber = cid; + } + + @Override + public void setFaceDown(boolean value) { + this.faceDown = value; + } + + @Override + public boolean isFaceDown() { + return this.faceDown; + } + + @Override + public boolean canTransform() { + return this.canTransform; + } + + @Override + public Card getSecondCardFace() { + return this.secondSideCard; + } + + @Override + public boolean isNightCard() { + return this.nightCard; + } } diff --git a/Mage/src/mage/cards/ExpansionSet.java b/Mage/src/mage/cards/ExpansionSet.java index c7fe8b0d869..f305905e546 100644 --- a/Mage/src/mage/cards/ExpansionSet.java +++ b/Mage/src/mage/cards/ExpansionSet.java @@ -221,7 +221,12 @@ public abstract class ExpansionSet implements Serializable { List newCards = new ArrayList(); for (Class clazz : classes) { if (clazz.getPackage().getName().equals(packageName)) { - newCards.add(createCard(clazz)); + Card card = createCard(clazz); + if (card.isNightCard()) { + // skip second face of double-faced cards + continue; + } + newCards.add(card); } } return newCards; diff --git a/Mage/src/mage/game/events/GameEvent.java b/Mage/src/mage/game/events/GameEvent.java index a6ffb2ce5ea..ebf16a705b3 100644 --- a/Mage/src/mage/game/events/GameEvent.java +++ b/Mage/src/mage/game/events/GameEvent.java @@ -104,6 +104,7 @@ public class GameEvent { UNTAP, UNTAPPED, FLIP, FLIPPED, UNFLIP, UNFLIPPED, + TRANSFORM, TRANSFORMED, PHASE_OUT, PHASED_OUT, PHASE_IN, PHASED_IN, TURNFACEUP, TURNEDFACEUP, diff --git a/Mage/src/mage/game/permanent/Permanent.java b/Mage/src/mage/game/permanent/Permanent.java index 2141aa46d15..26ec552f2a4 100644 --- a/Mage/src/mage/game/permanent/Permanent.java +++ b/Mage/src/mage/game/permanent/Permanent.java @@ -54,6 +54,10 @@ public interface Permanent extends Card { public boolean unflip(Game game); public boolean flip(Game game); + public boolean transform(Game game); + public boolean isTransformed(); + public void setTransformed(boolean value); + public boolean isPhasedIn(); public boolean phaseIn(Game game); public boolean phaseOut(Game game); diff --git a/Mage/src/mage/game/permanent/PermanentCard.java b/Mage/src/mage/game/permanent/PermanentCard.java index d5638d2d845..689a7dabf2a 100644 --- a/Mage/src/mage/game/permanent/PermanentCard.java +++ b/Mage/src/mage/game/permanent/PermanentCard.java @@ -111,6 +111,12 @@ public class PermanentCard extends PermanentImpl { this.expansionSetCode = card.getExpansionSetCode(); this.rarity = card.getRarity(); this.cardNumber = card.getCardNumber(); + + canTransform = card.canTransform(); + if (canTransform) { + secondSideCard = card.getSecondCardFace(); + nightCard = card.isNightCard(); + } } public void checkPermanentOnlyTriggers(ZoneChangeEvent event, Game game) { diff --git a/Mage/src/mage/game/permanent/PermanentImpl.java b/Mage/src/mage/game/permanent/PermanentImpl.java index 2e8d3ebb5cb..f4321a442d9 100644 --- a/Mage/src/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/mage/game/permanent/PermanentImpl.java @@ -55,6 +55,7 @@ public abstract class PermanentImpl> extends CardImpl protected boolean tapped; protected boolean flipped; + protected boolean transformed; protected UUID originalControllerId; protected UUID controllerId; protected UUID beforeResetControllerId; @@ -318,6 +319,18 @@ public abstract class PermanentImpl> extends CardImpl return false; } + @Override + public boolean transform(Game game) { + if (canTransform) { + if (!replaceEvent(EventType.TRANSFORM, game)) { + setTransformed(!transformed); + fireEvent(EventType.TRANSFORMED, game); + return true; + } + } + return false; + } + @Override public boolean isPhasedIn() { return phasedIn; @@ -790,4 +803,14 @@ public abstract class PermanentImpl> extends CardImpl } return dealtDamageByThisTurn; } + + @Override + public boolean isTransformed() { + return this.transformed; + } + + @Override + public void setTransformed(boolean value) { + this.transformed = value; + } } diff --git a/Mage/src/mage/game/stack/Spell.java b/Mage/src/mage/game/stack/Spell.java index 09515a338d4..1d1d10c5058 100644 --- a/Mage/src/mage/game/stack/Spell.java +++ b/Mage/src/mage/game/stack/Spell.java @@ -347,7 +347,22 @@ public class Spell> implements StackObject, Card { return false; } - @Override + @Override + public boolean canTransform() { + return false; + } + + @Override + public Card getSecondCardFace() { + return null; + } + + @Override + public boolean isNightCard() { + return false; + } + + @Override public Spell copy() { return new Spell(this); }