From 5b5344a1a0b90a16a9568577c48a0693a09d1db1 Mon Sep 17 00:00:00 2001 From: LevelX2 <ludwig.hirth@online.de> Date: Tue, 23 Sep 2014 17:01:09 +0200 Subject: [PATCH] * MorphAbility - Fixed copying a face-down creature (fixes #566). Morph cards are indicated as playable now if you have the needed mana to play it by Morph. Cast of Morph spell is now colorless (fixes #569). --- .../cards/abilities/keywords/MorphTest.java | 179 ++++++++++++++++++ .../common/FaceDownSourceCondition.java | 63 ++++++ ...OrMoreSpellsWereCastLastTurnCondition.java | 2 +- .../costs/AlternativeSourceCosts.java | 4 +- .../mage/abilities/keyword/EvokeAbility.java | 8 + .../mage/abilities/keyword/MorphAbility.java | 80 +++++--- Mage/src/mage/game/GameImpl.java | 4 + Mage/src/mage/players/PlayerImpl.java | 43 +++-- .../common/CastSpellLastTurnWatcher.java | 6 +- 9 files changed, 340 insertions(+), 49 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java create mode 100644 Mage/src/mage/abilities/condition/common/FaceDownSourceCondition.java diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java new file mode 100644 index 0000000000..1c8325675d --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java @@ -0,0 +1,179 @@ +/* + * 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 org.mage.test.cards.abilities.keywords; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author levelX2 + */ + +public class MorphTest extends CardTestPlayerBase { + + /** + * Tests if a creature with Morph is cast normal, it behaves as normal creature + * + */ + @Test + public void testCastMoprhCreatureWithoutMorph() { + /* + Pine Walker + Creature - Elemental + 5/5 + Morph {4}{G} (You may cast this card face down as a 2/2 creature for . Turn it face up any time for its morph cost.) + Whenever Pine Walker or another creature you control is turned face up, untap that creature. + */ + addCard(Zone.HAND, playerA, "Pine Walker"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 5); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pine Walker"); + setChoice(playerA, "No"); // cast it normal as 5/5 + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Pine Walker", 1); + assertPowerToughness(playerA, "Pine Walker", 5, 5); + + } + + + /** + * Cast the creature face down as a 2/2 + */ + @Test + public void testCastFaceDown() { + addCard(Zone.HAND, playerA, "Pine Walker"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 3); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pine Walker"); + setChoice(playerA, "Yes"); // cast it face down as 2/2 creature + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "", 1); + assertPowerToughness(playerA, "", 2, 2); + + } + /** + * Test triggered turn face up ability of Pine Walker + */ + @Test + public void testCopyFaceDwonMorphCreature() { + addCard(Zone.HAND, playerA, "Pine Walker"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 5); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pine Walker"); + setChoice(playerA, "Yes"); // cast it face down as 2/2 creature + + attack(3, playerA, ""); + + activateAbility(3, PhaseStep.POSTCOMBAT_MAIN, playerA, "{4}{G}: Turn this face-down permanent face up."); + setStopAt(3, PhaseStep.END_TURN); + execute(); + + assertLife(playerB, 18); + + assertPermanentCount(playerA, "", 0); + assertPermanentCount(playerA, "Pine Walker", 1); + assertPowerToughness(playerA, "Pine Walker", 5, 5); + assertTapped("Pine Walker", false); + + } + /** + * Test that Morph creature do not trigger abilities with their face up attributes + * + */ + @Test + public void testMorphedRemovesAttributesCreature() { + // Ponyback Brigade {3}{R}{W}{B} + // Creature - Goblin Warrior + // 2/2 + // When Ponyback Brigade enters the battlefield or is turned face up, put three 1/1 red Goblin creature tokens onto the battlefield. + // Morph {2}{R}{W}{B}(You may cast this card face down as a 2/2 creature for . Turn it face up any time for its morph cost.) + addCard(Zone.HAND, playerA, "Ponyback Brigade"); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2); + + addCard(Zone.BATTLEFIELD, playerB, "Soldier of the Pantheon", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Ponyback Brigade"); + setChoice(playerA, "Yes"); // cast it face down as 2/2 creature + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerB, 20); // and not 21 + + assertPermanentCount(playerA, "", 1); + assertPermanentCount(playerB, "Soldier of the Pantheon", 1); + + } + + /** + * Test to copy a morphed 2/2 creature + * + */ + @Test + public void testCopyAMorphedCreature() { + addCard(Zone.HAND, playerA, "Pine Walker"); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); + + // Clever Impersonator {2}{U}{U} + // Creature - Shapeshifter + // 0/0 + // You may have Clever Impersonator enter the battlefield as a copy of any nonland permanent on the battlefield. + addCard(Zone.HAND, playerB, "Clever Impersonator", 1); + addCard(Zone.BATTLEFIELD, playerB, "Island", 4); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pine Walker"); + setChoice(playerA, "Yes"); // cast it face down as 2/2 creature + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Clever Impersonator"); + setChoice(playerB, "Yes"); // use to copy a nonland permanent + addTarget(playerB, ""); // Morphed creature + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerB, 20); + + assertPermanentCount(playerA, "", 1); + assertPowerToughness(playerA, "", 2,2); + assertPermanentCount(playerB, "", 1); + assertPowerToughness(playerB, "", 2,2); + + } + +} diff --git a/Mage/src/mage/abilities/condition/common/FaceDownSourceCondition.java b/Mage/src/mage/abilities/condition/common/FaceDownSourceCondition.java new file mode 100644 index 0000000000..b2918d048c --- /dev/null +++ b/Mage/src/mage/abilities/condition/common/FaceDownSourceCondition.java @@ -0,0 +1,63 @@ +/* + * 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.condition.common; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.condition.Condition; +import mage.cards.Card; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ + +public class FaceDownSourceCondition implements Condition { + + private final static FaceDownSourceCondition fInstance = new FaceDownSourceCondition(); + + public static Condition getInstance() { + return fInstance; + } + + @Override + public boolean apply(Game game, Ability source) { + MageObject mageObject = game.getObject(source.getSourceId()); + if (mageObject != null) { + if (mageObject instanceof Permanent) { + return ((Permanent)mageObject).isFaceDown(); + } + if (mageObject instanceof Card) { + return ((Card)mageObject).isFaceDown(); + } + } + return false; + } +} diff --git a/Mage/src/mage/abilities/condition/common/TwoOrMoreSpellsWereCastLastTurnCondition.java b/Mage/src/mage/abilities/condition/common/TwoOrMoreSpellsWereCastLastTurnCondition.java index 78d7c09619..c716ebf8a3 100644 --- a/Mage/src/mage/abilities/condition/common/TwoOrMoreSpellsWereCastLastTurnCondition.java +++ b/Mage/src/mage/abilities/condition/common/TwoOrMoreSpellsWereCastLastTurnCondition.java @@ -52,7 +52,7 @@ public class TwoOrMoreSpellsWereCastLastTurnCondition implements Condition { return true; } } - // no one cast two or more spells this turn + // no one cast two or more spells last turn return false; } } diff --git a/Mage/src/mage/abilities/costs/AlternativeSourceCosts.java b/Mage/src/mage/abilities/costs/AlternativeSourceCosts.java index 71b136d0ca..5e9087feb3 100644 --- a/Mage/src/mage/abilities/costs/AlternativeSourceCosts.java +++ b/Mage/src/mage/abilities/costs/AlternativeSourceCosts.java @@ -70,6 +70,6 @@ public interface AlternativeSourceCosts { * @param game * @return */ - String getCastMessageSuffix(Game game); - + String getCastMessageSuffix(Game game); + } \ No newline at end of file diff --git a/Mage/src/mage/abilities/keyword/EvokeAbility.java b/Mage/src/mage/abilities/keyword/EvokeAbility.java index 1569db6ccb..fd32438b0e 100644 --- a/Mage/src/mage/abilities/keyword/EvokeAbility.java +++ b/Mage/src/mage/abilities/keyword/EvokeAbility.java @@ -41,6 +41,7 @@ import mage.abilities.costs.AlternativeCost2Impl; import mage.abilities.costs.AlternativeSourceCosts; import mage.abilities.costs.Cost; import mage.abilities.costs.Costs; +import mage.abilities.costs.CostsImpl; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.SacrificeSourceEffect; @@ -190,4 +191,11 @@ public class EvokeAbility extends StaticAbility implements AlternativeSourceCost } return sb.toString(); } + + @Override + public Costs<Cost> getCosts() { + Costs<Cost> alterCosts = new CostsImpl<>(); + alterCosts.addAll(evokeCosts); + return alterCosts; + } } diff --git a/Mage/src/mage/abilities/keyword/MorphAbility.java b/Mage/src/mage/abilities/keyword/MorphAbility.java index bdd6f6e508..b1886aa7da 100644 --- a/Mage/src/mage/abilities/keyword/MorphAbility.java +++ b/Mage/src/mage/abilities/keyword/MorphAbility.java @@ -30,7 +30,6 @@ package mage.abilities.keyword; import java.util.ArrayList; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import mage.ObjectColor; import mage.abilities.Ability; @@ -38,13 +37,13 @@ import mage.abilities.SpellAbility; import mage.abilities.StaticAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.TurnFaceUpAbility; -import mage.abilities.costs.AlternativeCost2; import mage.abilities.costs.AlternativeCost2Impl; import mage.abilities.costs.AlternativeSourceCosts; import mage.abilities.costs.Cost; import mage.abilities.costs.Costs; 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.costs.mana.ManaCostsImpl; import mage.abilities.effects.ContinuousEffectImpl; @@ -54,6 +53,7 @@ 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; @@ -105,7 +105,7 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost protected static final String ABILITY_KEYWORD = "Morph"; protected static final String REMINDER_TEXT = "(You may cast this card face down as a 2/2 creature for {3}. Turn it face up any time for its morph cost.)"; protected String ruleText; - protected List<AlternativeCost2> alternateCosts = new LinkedList<>(); + protected AlternativeCost2Impl alternateCosts = new AlternativeCost2Impl(ABILITY_KEYWORD, REMINDER_TEXT, new GenericManaCost(3)); // needed to check activation status, if card changes zone after casting it private int zoneChangeCounter = 0; @@ -131,8 +131,7 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost sb.append(REMINDER_TEXT); ruleText = sb.toString(); - alternateCosts.add(new AlternativeCost2Impl(ABILITY_KEYWORD, REMINDER_TEXT, new GenericManaCost(3))); - + // alternateCosts.add(new AlternativeCost2Impl(ABILITY_KEYWORD, REMINDER_TEXT, new GenericManaCost(3))); Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BecomesFaceDownCreatureEffect(morphCosts)); ability.setRuleVisible(false); card.addAbility(ability); @@ -141,13 +140,13 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost public MorphAbility(final MorphAbility ability) { super(ability); - this.alternateCosts.addAll(ability.alternateCosts); this.zoneChangeCounter = ability.zoneChangeCounter; this.ruleText = ability.ruleText; + this.alternateCosts = ability.alternateCosts.copy(); } - private static Costs createCosts(Cost cost) { - Costs costs = new CostsImpl(); + private static Costs<Cost> createCosts(Cost cost) { + Costs<Cost> costs = new CostsImpl<>(); costs.add(cost); return costs; } @@ -158,9 +157,7 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost } public void resetMorph() { - for (AlternativeCost2 cost: alternateCosts) { - cost.reset(); - } + alternateCosts.reset(); zoneChangeCounter = 0; } @@ -168,11 +165,7 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost public boolean isActivated(Ability ability, Game game) { Card card = game.getCard(sourceId); if (card != null && card.getZoneChangeCounter() <= zoneChangeCounter +1) { - for (AlternativeCost2 cost: alternateCosts) { - if(cost.isActivated(game)) { - return true; - } - } + return alternateCosts.isActivated(game); } return false; } @@ -190,20 +183,27 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost if (player != null && spell != null) { this.resetMorph(); spell.setFaceDown(true); // so only the back is visible - for (AlternativeCost2 alternateCastingCost: alternateCosts) { - if (alternateCastingCost.canPay(ability, sourceId, controllerId, game) && - player.chooseUse(Outcome.Benefit, new StringBuilder("Cast this card as a 2/2 face-down creature for ").append(alternateCastingCost.getText(true)).append(" ?").toString(), game)) { - activateMorph(alternateCastingCost, game); + if (alternateCosts.canPay(ability, sourceId, controllerId, game)) { + if (player.chooseUse(Outcome.Benefit, new StringBuilder("Cast this card as a 2/2 face-down creature for ").append(getCosts().getText()).append(" ?").toString(), game)) { + activateMorph(game); + // change mana costs ability.getManaCostsToPay().clear(); ability.getCosts().clear(); - for (Iterator it = ((Costs) alternateCastingCost).iterator(); it.hasNext();) { + for (Iterator it = this.alternateCosts.iterator(); it.hasNext();) { Cost cost = (Cost) it.next(); - if (cost instanceof ManaCosts) { - ability.getManaCostsToPay().add((ManaCostsImpl) cost.copy()); + if (cost instanceof ManaCost) { + ability.getManaCostsToPay().add((ManaCost)cost.copy()); } else { ability.getCosts().add(cost.copy()); } } + // change spell colors + ObjectColor spellColor = spell.getColor(); + spellColor.setBlack(false); + spellColor.setRed(false); + spellColor.setGreen(false); + spellColor.setWhite(false); + spellColor.setBlue(false); } else { spell.setFaceDown(false); } @@ -213,8 +213,8 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost return isActivated(ability, game); } - private void activateMorph(AlternativeCost2 cost, Game game) { - cost.activate(); + private void activateMorph(Game game) { + alternateCosts.activate(); // remember zone change counter if (zoneChangeCounter == 0) { Card card = game.getCard(getSourceId()); @@ -240,14 +240,31 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost public String getCastMessageSuffix(Game game) { StringBuilder sb = new StringBuilder(); int position = 0; - for (AlternativeCost2 cost : alternateCosts) { - if (cost.isActivated(game)) { - sb.append(cost.getCastSuffixMessage(position)); - ++position; - } - } + sb.append(alternateCosts.getCastSuffixMessage(position)); return sb.toString(); } + + @Override + @SuppressWarnings({"unchecked"}) + public Costs<Cost> getCosts() { + return alternateCosts; + } + + public static void setPermanentToMorph(Permanent permanent) { + permanent.getPower().initValue(2); + permanent.getToughness().initValue(2); + permanent.getAbilities().clear(); + permanent.getColor().setColor(new ObjectColor()); + permanent.setName(""); + permanent.getCardType().clear(); + permanent.getCardType().add(CardType.CREATURE); + permanent.getSubtype().clear(); + permanent.getSupertype().clear(); + permanent.getManaCost().clear(); + permanent.setExpansionSetCode("KTK"); + permanent.setRarity(Rarity.NA); + + } } /** @@ -348,3 +365,4 @@ class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implements Sour } } + diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index 802242ecd5..3481dd5799 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -93,6 +93,7 @@ import java.io.IOException; import java.io.Serializable; import java.util.*; import java.util.Map.Entry; +import mage.abilities.keyword.MorphAbility; public abstract class GameImpl implements Game, Serializable { @@ -1237,6 +1238,9 @@ public abstract class GameImpl implements Game, Serializable { //getState().addCard(permanent); permanent.reset(this); + if (copyFromPermanent.isMorphCard()) { + MorphAbility.setPermanentToMorph(permanent); + } permanent.assignNewId(); if (copyFromPermanent.isTransformed()) { TransformAbility.transform(permanent, copyFromPermanent.getSecondCardFace(), this); diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index 8154f974c9..e3c69893d7 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -1907,7 +1907,7 @@ public abstract class PlayerImpl implements Player, Serializable { return result; } - protected boolean canPlay(ActivatedAbility ability, ManaOptions available, Game game) { + protected boolean canPlay(ActivatedAbility ability, ManaOptions available, MageObject sourceObject, Game game) { if (!(ability instanceof ManaAbility)) { ActivatedAbility copy = ability.copy(); copy.setCheckPlayableMode(); // prevents from endless loops for asking player to use effects by checking this mode @@ -1956,6 +1956,20 @@ public abstract class PlayerImpl implements Player, Serializable { return true; } } + + if (!(sourceObject instanceof Permanent)) { + for (Ability alternateSourceCostsAbility : sourceObject.getAbilities()) { + // if cast for noMana no Alternative costs are allowed + if (alternateSourceCostsAbility instanceof AlternativeSourceCosts) { + if (((AlternativeSourceCosts)alternateSourceCostsAbility).isAvailable(ability, game)) { + if (alternateSourceCostsAbility.getCosts().canPay(ability, playerId, playerId, game)) { + return true; + } + } + } + } + } + } return false; } @@ -1971,14 +1985,19 @@ public abstract class PlayerImpl implements Player, Serializable { if (hidden) { for (Card card : hand.getUniqueCards(game)) { - for (ActivatedAbility ability : card.getAbilities().getActivatedAbilities(Zone.HAND)) { - if (ability instanceof PlayLandAbility) { - if (game.getContinuousEffects().preventedByRuleModification(GameEvent.getEvent(GameEvent.EventType.PLAY_LAND, ability.getSourceId(), ability.getSourceId(), playerId), ability, game, true)) { - break; + for (Ability ability : card.getAbilities()) { + if (ability instanceof ActivatedAbility) { + if (ability instanceof PlayLandAbility) { + if (game.getContinuousEffects().preventedByRuleModification(GameEvent.getEvent(GameEvent.EventType.PLAY_LAND, ability.getSourceId(), ability.getSourceId(), playerId), ability, game, true)) { + break; + } + } + if (canPlay((ActivatedAbility) ability, availableMana, card, game)) { + playable.add(ability); } } - if (canPlay(ability, availableMana, game)) { - playable.add(ability); + if (ability instanceof AlternativeSourceCosts) { + } } } @@ -1994,7 +2013,7 @@ public abstract class PlayerImpl implements Player, Serializable { possible = true; } } - if (possible && canPlay(ability, availableMana, game)) { + if (possible && canPlay(ability, availableMana, card, game)) { playable.add(ability); } } @@ -2036,7 +2055,7 @@ public abstract class PlayerImpl implements Player, Serializable { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(playerId)) { for (ActivatedAbility ability : permanent.getAbilities().getActivatedAbilities(Zone.BATTLEFIELD)) { if (!playableActivated.containsKey(ability.toString())) { - if (canPlay(ability, availableMana, game)) { + if (canPlay(ability, availableMana, permanent, game)) { playableActivated.put(ability.toString(), ability); } } @@ -2049,7 +2068,7 @@ public abstract class PlayerImpl implements Player, Serializable { MageObject object = game.getObject(this.getCommanderId()); if (object != null) { for (ActivatedAbility ability : ((Commander) object).getAbilities().getActivatedAbilities(Zone.COMMAND)) { - if (canPlay(ability, availableMana, game)) { + if (canPlay(ability, availableMana, object, game)) { playableActivated.put(ability.toString(), ability); } } @@ -2082,13 +2101,13 @@ public abstract class PlayerImpl implements Player, Serializable { break; } } - if (canPlay(ability, available, game)) { + if (canPlay(ability, available, card, game)) { playable.add(card.getId()); break; } } for (ActivatedAbility ability : card.getAbilities().getActivatedAbilities(Zone.HAND)) { - if (!playable.contains(ability.getSourceId()) && canPlay(ability, available, game)) { + if (!playable.contains(ability.getSourceId()) && canPlay(ability, available, card, game)) { playable.add(card.getId()); break; } diff --git a/Mage/src/mage/watchers/common/CastSpellLastTurnWatcher.java b/Mage/src/mage/watchers/common/CastSpellLastTurnWatcher.java index 57772f2dd2..d5800980ea 100644 --- a/Mage/src/mage/watchers/common/CastSpellLastTurnWatcher.java +++ b/Mage/src/mage/watchers/common/CastSpellLastTurnWatcher.java @@ -70,9 +70,9 @@ public class CastSpellLastTurnWatcher extends Watcher { if (playerId != null) { Integer amount = amountOfSpellsCastOnCurrentTurn.get(playerId); if (amount == null) { - amount = Integer.valueOf(1); + amount = 1; } else { - amount = Integer.valueOf(amount+1); + amount = amount+1; } amountOfSpellsCastOnCurrentTurn.put(playerId, amount); } @@ -98,7 +98,7 @@ public class CastSpellLastTurnWatcher extends Watcher { public int getAmountOfSpellsPlayerCastOnCurrentTurn(UUID playerId) { Integer value = amountOfSpellsCastOnCurrentTurn.get(playerId); if (value != null) { - return value.intValue(); + return value; } else { return 0; }