From 9a61a66aaba5e38d973f2373d0e36bb81a9b42ec Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 30 Dec 2014 20:37:22 +0100 Subject: [PATCH] [FRF] Added Manifast Effect. --- Mage.Common/src/mage/view/PermanentView.java | 9 +- .../BecomesFaceDownCreatureEffect.java | 184 ++++++++++++++++++ .../effects/keyword/ManifestEffect.java | 111 +++++++++++ .../mage/abilities/keyword/MorphAbility.java | 105 +--------- .../mage/game/permanent/PermanentCard.java | 2 +- Mage/src/mage/players/PlayerImpl.java | 3 +- 6 files changed, 306 insertions(+), 108 deletions(-) create mode 100644 Mage/src/mage/abilities/effects/common/continious/BecomesFaceDownCreatureEffect.java create mode 100644 Mage/src/mage/abilities/effects/keyword/ManifestEffect.java diff --git a/Mage.Common/src/mage/view/PermanentView.java b/Mage.Common/src/mage/view/PermanentView.java index 5b7476a1f8..a3d0de3b4c 100644 --- a/Mage.Common/src/mage/view/PermanentView.java +++ b/Mage.Common/src/mage/view/PermanentView.java @@ -31,7 +31,6 @@ package mage.view; import mage.abilities.Ability; import mage.abilities.common.TurnFaceUpAbility; import mage.cards.Card; -import mage.constants.Rarity; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.PermanentToken; @@ -135,6 +134,14 @@ public class PermanentView extends CardView { } } else{ if (controlled && card != null) { + for (Ability permanentAbility : permanent.getAbilities()) { + if (permanentAbility instanceof TurnFaceUpAbility && !permanentAbility.getRuleVisible()) { + this.rules.add(permanentAbility.getRule(true)); + } + if (permanentAbility.getWorksFaceDown()) { + this.rules.add(permanentAbility.getRule()); + } + } this.name = card.getName(); this.displayName = card.getName(); } diff --git a/Mage/src/mage/abilities/effects/common/continious/BecomesFaceDownCreatureEffect.java b/Mage/src/mage/abilities/effects/common/continious/BecomesFaceDownCreatureEffect.java new file mode 100644 index 0000000000..07e69e3631 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/continious/BecomesFaceDownCreatureEffect.java @@ -0,0 +1,184 @@ +/* + * 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.effects.common.continious; + +import java.util.ArrayList; +import java.util.List; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.TurnFaceUpAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.Costs; +import mage.abilities.costs.CostsImpl; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.cards.Card; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import static mage.constants.Layer.AbilityAddingRemovingEffects_6; +import static mage.constants.Layer.ColorChangingEffects_5; +import static mage.constants.Layer.PTChangingEffects_7; +import static mage.constants.Layer.TypeChangingEffects_4; +import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * This effect lets the card be a 2/2 face-down creature, with no text, + * no name, no subtypes, and no mana cost, if it's face down on the battlefield. + * And it adds the a TurnFaceUpAbility ability. + * + * @author LevelX2 + */ + +public class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implements SourceEffect { + + protected int zoneChangeCounter; + protected Ability turnFaceUpAbility = null; + protected boolean useTargetPointer; + + + public BecomesFaceDownCreatureEffect(Costs morphCosts) { + this(morphCosts, false); + } + + public BecomesFaceDownCreatureEffect(Costs morphCosts, boolean useTargetPointer) { + this(morphCosts, useTargetPointer, Duration.WhileOnBattlefield); + } + + public BecomesFaceDownCreatureEffect(Cost cost, boolean useTargetPointer, Duration duration) { + this(createCosts(cost), useTargetPointer, duration); + } + + public BecomesFaceDownCreatureEffect(Costs morphCosts, boolean useTargetPointer, Duration duration) { + super(duration, Outcome.BecomeCreature); + this.useTargetPointer = useTargetPointer; + this.zoneChangeCounter = Integer.MIN_VALUE; + if (morphCosts != null) { + this.turnFaceUpAbility = new TurnFaceUpAbility(morphCosts); + } + staticText = "{this} becomes a 2/2 face-down creature, with no text, no name, no subtypes, and no mana cost"; + } + + + public BecomesFaceDownCreatureEffect(final BecomesFaceDownCreatureEffect effect) { + super(effect); + this.zoneChangeCounter = effect.zoneChangeCounter; + if (effect.turnFaceUpAbility != null) { + this.turnFaceUpAbility = effect.turnFaceUpAbility.copy(); + } + this.useTargetPointer = effect.useTargetPointer; + } + + @Override + public BecomesFaceDownCreatureEffect copy() { + return new BecomesFaceDownCreatureEffect(this); + } + + private static Costs createCosts(Cost cost) { + if (cost == null) { + return null; + } + Costs costs = new CostsImpl<>(); + costs.add(cost); + return costs; + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + Permanent permanent; + if (useTargetPointer) { + permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + } else { + permanent = game.getPermanent(source.getSourceId()); + } + + if (permanent != null && permanent.isFaceDown()) { + switch (layer) { + case TypeChangingEffects_4: + permanent.setName(""); + permanent.getSupertype().clear(); + permanent.getCardType().clear(); + permanent.getCardType().add(CardType.CREATURE); + permanent.getSubtype().clear(); + permanent.getManaCost().clear(); + break; + case ColorChangingEffects_5: + permanent.getColor().setColor(new ObjectColor()); + break; + case AbilityAddingRemovingEffects_6: + Card card = game.getCard(permanent.getId()); // + List abilities = new ArrayList<>(); + for (Ability ability : permanent.getAbilities()) { + if (card != null && !card.getAbilities().contains(ability)) { + // gained abilities from other sources won't be removed + continue; + } + if (ability.getWorksFaceDown()) { + ability.setRuleVisible(false); + continue; + } else { + if (!ability.getRuleVisible() && !ability.getEffects().isEmpty()) { + if (ability.getEffects().get(0) instanceof BecomesFaceDownCreatureEffect) { + continue; + } + } + } + abilities.add(ability); + } + permanent.getAbilities().removeAll(abilities); + if (turnFaceUpAbility != null) { + permanent.addAbility(turnFaceUpAbility, game); + } + break; + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + permanent.getPower().setValue(2); + permanent.getToughness().setValue(2); + } + } + } else { + if (duration.equals(Duration.Custom)) { + discard(); + } + } + return true; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean hasLayer(Layer layer) { + return layer == Layer.PTChangingEffects_7 || layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.ColorChangingEffects_5 || layer == Layer.TypeChangingEffects_4; + } + +} diff --git a/Mage/src/mage/abilities/effects/keyword/ManifestEffect.java b/Mage/src/mage/abilities/effects/keyword/ManifestEffect.java new file mode 100644 index 0000000000..3c7e54f9df --- /dev/null +++ b/Mage/src/mage/abilities/effects/keyword/ManifestEffect.java @@ -0,0 +1,111 @@ +/* + * 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.effects.keyword; + +import java.util.List; +import mage.abilities.Ability; +import mage.abilities.costs.mana.ManaCosts; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continious.BecomesFaceDownCreatureEffect; +import mage.cards.Card; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; +import mage.util.CardUtil; + +/** + * + * @author LevelX2 + */ +public class ManifestEffect extends OneShotEffect { + + private final int amount; + + public ManifestEffect(int amount) { + super(Outcome.PutCreatureInPlay); + this.amount = amount; + this.staticText = setText(); + } + + public ManifestEffect(final ManifestEffect effect) { + super(effect); + this.amount = effect.amount; + } + + @Override + public ManifestEffect copy() { + return new ManifestEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + List cards = controller.getLibrary().getTopCards(game, amount); + for (Card card: cards) { + card.setFaceDown(true); + controller.putOntoBattlefieldWithInfo(card, game, Zone.LIBRARY, source.getSourceId()); + ManaCosts manaCosts = null; + if (card.getCardType().contains(CardType.CREATURE)) { + manaCosts = card.getSpellAbility().getManaCosts(); + if (manaCosts == null) { + manaCosts = new ManaCostsImpl("{0}"); + } + } + ContinuousEffect effect = new BecomesFaceDownCreatureEffect(manaCosts, true, Duration.Custom); + effect.setTargetPointer(new FixedTarget(card.getId())); + game.addEffect(effect, source); + } + return true; + } + return false; + } + + private String setText() { + StringBuilder sb = new StringBuilder("Manifest the top "); + if (amount > 1) { + sb.append(CardUtil.numberToText(amount)).append(" cards "); + } else { + sb.append("card "); + } + sb.append("of your library. "); + if (amount > 1) { + sb.append("(To manifest a card, put it onto the battlefield face down as a 2/2 creature. You may turn it face up at any time for its mana cost if it's a creature card.)"); + } else { + sb.append("(Put it onto the battlefield face down as a 2/2 creature. Turn it face up at any time for its mana cost if it's a creature card.)"); + } + return sb.toString(); + } +} diff --git a/Mage/src/mage/abilities/keyword/MorphAbility.java b/Mage/src/mage/abilities/keyword/MorphAbility.java index 355c71d820..55c0bc013a 100644 --- a/Mage/src/mage/abilities/keyword/MorphAbility.java +++ b/Mage/src/mage/abilities/keyword/MorphAbility.java @@ -28,14 +28,11 @@ package mage.abilities.keyword; -import java.util.ArrayList; import java.util.Iterator; -import java.util.List; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.StaticAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.common.TurnFaceUpAbility; import mage.abilities.costs.AlternativeCost2Impl; import mage.abilities.costs.AlternativeSourceCosts; import mage.abilities.costs.Cost; @@ -44,16 +41,12 @@ import mage.abilities.costs.CostsImpl; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCosts; -import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.effects.common.continious.SourceEffect; +import mage.abilities.effects.common.continious.BecomesFaceDownCreatureEffect; import mage.cards.Card; import mage.constants.AbilityType; import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Layer; import mage.constants.Outcome; import mage.constants.Rarity; -import mage.constants.SubLayer; import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; @@ -293,102 +286,6 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost } } -/** - * This effect lets the creature always be a 2/2 face-down creature, with no text, - * no name, no subtypes, and no mana cost, if it's face down on the battlefield. - * And it adds the MorphTurnFaceUpAbility ability. - * TODO: Check if it's better to create this effect always as a creature on the battelfield turns face down or - * a creature enters the battlefield face down. Then the effect could be removed as the permanent turns face up. - * - * @author LevelX2 - */ -class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implements SourceEffect { - protected int zoneChangeCounter; - protected Ability turnFaceUpAbility = null; - - public BecomesFaceDownCreatureEffect(Costs morphCosts) { - super(Duration.WhileOnBattlefield, Outcome.BecomeCreature); - this.zoneChangeCounter = Integer.MIN_VALUE; - if (morphCosts != null) { - this.turnFaceUpAbility = new TurnFaceUpAbility(morphCosts); - } - staticText = "{this} becomes a 2/2 face-down creature, with no text, no name, no subtypes, and no mana cost"; - } - - public BecomesFaceDownCreatureEffect(final BecomesFaceDownCreatureEffect effect) { - super(effect); - this.zoneChangeCounter = effect.zoneChangeCounter; - this.turnFaceUpAbility = effect.turnFaceUpAbility.copy(); - } - - @Override - public BecomesFaceDownCreatureEffect copy() { - return new BecomesFaceDownCreatureEffect(this); - } - - @Override - public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null && permanent.isFaceDown()) { - switch (layer) { - case TypeChangingEffects_4: - permanent.setName(""); - permanent.getSupertype().clear(); - permanent.getCardType().clear(); - permanent.getCardType().add(CardType.CREATURE); - permanent.getSubtype().clear(); - permanent.getManaCost().clear(); - break; - case ColorChangingEffects_5: - permanent.getColor().setColor(new ObjectColor()); - break; - case AbilityAddingRemovingEffects_6: - Card card = game.getCard(permanent.getId()); // - List abilities = new ArrayList<>(); - for (Ability ability : permanent.getAbilities()) { - if (card != null && !card.getAbilities().contains(ability)) { - // gained abilities from other sources won't be removed - continue; - } - if (ability.getWorksFaceDown()) { - ability.setRuleVisible(false); - continue; - } else { - if (!ability.getRuleVisible() && !ability.getEffects().isEmpty()) { - if (ability.getEffects().get(0) instanceof BecomesFaceDownCreatureEffect) { - continue; - } - } - } - abilities.add(ability); - } - permanent.getAbilities().removeAll(abilities); - if (turnFaceUpAbility != null) { - permanent.addAbility(turnFaceUpAbility, game); - } - break; - case PTChangingEffects_7: - if (sublayer == SubLayer.SetPT_7b) { - permanent.getPower().setValue(2); - permanent.getToughness().setValue(2); - } - - } - } - return true; - } - - @Override - public boolean apply(Game game, Ability source) { - return false; - } - - @Override - public boolean hasLayer(Layer layer) { - return layer == Layer.PTChangingEffects_7 || layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.ColorChangingEffects_5 || layer == Layer.TypeChangingEffects_4; - } - -} diff --git a/Mage/src/mage/game/permanent/PermanentCard.java b/Mage/src/mage/game/permanent/PermanentCard.java index 98a19a6217..4c0c45b58b 100644 --- a/Mage/src/mage/game/permanent/PermanentCard.java +++ b/Mage/src/mage/game/permanent/PermanentCard.java @@ -133,7 +133,7 @@ public class PermanentCard extends PermanentImpl { Zone fromZone = game.getState().getZone(objectId); Player controller = game.getPlayer(controllerId); if (controller != null && controller.removeFromBattlefield(this, game)) { - if (isFaceDown() && isMorphCard()) { + if (isFaceDown()) { setFaceDown(false); game.getCard(this.getId()).setFaceDown(false); //TODO: Do this in a better way } diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index 9c350a7149..5f6fcbf839 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -2716,13 +2716,12 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean moveCardToHandWithInfo(Card card, UUID sourceId, Game game, Zone fromZone) { boolean result = false; - boolean faceDown = card.isFaceDown(); // move sets card to face up if (card.moveToZone(Zone.HAND, sourceId, game, false)) { if (card instanceof PermanentCard) { card = game.getCard(card.getId()); } game.informPlayers(new StringBuilder(this.getName()) - .append(" puts ").append(faceDown ? " a face down card":card.getLogName()).append(" ") + .append(" puts ").append(card.getLogName()).append(" ") .append(fromZone != null ? new StringBuilder("from ").append(fromZone.toString().toLowerCase(Locale.ENGLISH)).append(" "):"") .append(card.getOwnerId().equals(this.getId()) ? "into his or her hand":"into its owner's hand").toString()); result = true;