diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/LinvalaKeeperOfSilence.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/LinvalaKeeperOfSilence.java index a0940028901..d67a300c38b 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/LinvalaKeeperOfSilence.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/LinvalaKeeperOfSilence.java @@ -25,7 +25,6 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.sets.riseoftheeldrazi; import java.util.UUID; @@ -48,7 +47,7 @@ import mage.game.permanent.Permanent; */ public class LinvalaKeeperOfSilence extends CardImpl { - public LinvalaKeeperOfSilence (UUID ownerId) { + public LinvalaKeeperOfSilence(UUID ownerId) { super(ownerId, 33, "Linvala, Keeper of Silence", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, "{2}{W}{W}"); this.expansionSetCode = "ROE"; this.supertype.add("Legendary"); @@ -57,12 +56,14 @@ public class LinvalaKeeperOfSilence extends CardImpl { this.power = new MageInt(3); this.toughness = new MageInt(4); + // Flying this.addAbility(FlyingAbility.getInstance()); - + + // Activated abilities of creatures your opponents control can't be activated. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new LinvalaKeeperOfSilenceCantActivateEffect())); } - public LinvalaKeeperOfSilence (final LinvalaKeeperOfSilence card) { + public LinvalaKeeperOfSilence(final LinvalaKeeperOfSilence card) { super(card); } @@ -98,4 +99,4 @@ class LinvalaKeeperOfSilenceCantActivateEffect extends RestrictionEffect { return new LinvalaKeeperOfSilenceCantActivateEffect(this); } -} \ No newline at end of file +} 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 index 60991689d79..0e045507f55 100644 --- 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 @@ -612,4 +612,34 @@ public class MorphTest extends CardTestPlayerBase { assertPermanentCount(playerA, "", 1); } + + /** + * Linvala, Keep of Silence is preventing morph creatures from turning face + * up Turning face up is a special ability not an active ability. This + * should not be prevented by the loss of active abilities. + */ + @Test + public void testTurnFaceUpWithLinvala() { + addCard(Zone.HAND, playerA, "Pine Walker"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 5); + + addCard(Zone.BATTLEFIELD, playerB, "Linvala, Keeper of Silence", 1); + + 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); + + } } diff --git a/Mage/src/mage/abilities/keyword/MorphAbility.java b/Mage/src/mage/abilities/keyword/MorphAbility.java index cba284786e6..fbc7a76bcc2 100644 --- a/Mage/src/mage/abilities/keyword/MorphAbility.java +++ b/Mage/src/mage/abilities/keyword/MorphAbility.java @@ -237,7 +237,7 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost if (player != null) { this.resetMorph(); 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(), ability, game)) { + if (player.chooseUse(Outcome.Benefit, "Cast this card as a 2/2 face-down creature for " + getCosts().getText() + " ?", ability, game)) { activateMorph(game); // change mana costs ability.getManaCostsToPay().clear(); diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index 6aa71a4b972..7bfa31a2b01 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -1192,8 +1192,9 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public LinkedHashMap getUseableActivatedAbilities(MageObject object, Zone zone, Game game) { LinkedHashMap useable = new LinkedHashMap<>(); - if (!(object instanceof Permanent) || ((Permanent) object).canUseActivatedAbilities(game)) { - for (Ability ability : object.getAbilities()) { + boolean canUse = !(object instanceof Permanent) || ((Permanent) object).canUseActivatedAbilities(game); + for (Ability ability : object.getAbilities()) { + if (canUse || ability.getAbilityType().equals(AbilityType.SPECIAL_ACTION)) { if (ability.getZone().match(zone)) { if (ability instanceof ActivatedAbility) { if (((ActivatedAbility) ability).canActivate(playerId, game)) { @@ -1210,16 +1211,20 @@ public abstract class PlayerImpl implements Player, Serializable { } } } - if (zone != Zone.HAND) { - if (Zone.GRAVEYARD.equals(zone) && canPlayCardsFromGraveyard()) { - for (ActivatedAbility ability : object.getAbilities().getPlayableAbilities(Zone.HAND)) { + } + if (zone != Zone.HAND) { + if (Zone.GRAVEYARD.equals(zone) && canPlayCardsFromGraveyard()) { + for (ActivatedAbility ability : object.getAbilities().getPlayableAbilities(Zone.HAND)) { + if (canUse || ability.getAbilityType().equals(AbilityType.SPECIAL_ACTION)) { if (ability.canActivate(playerId, game)) { useable.put(ability.getId(), ability); } } } - if (zone != Zone.BATTLEFIELD && game.getContinuousEffects().asThough(object.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, this.getId(), game)) { - for (Ability ability : object.getAbilities()) { + } + if (zone != Zone.BATTLEFIELD && game.getContinuousEffects().asThough(object.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, this.getId(), game)) { + for (Ability ability : object.getAbilities()) { + if (canUse || ability.getAbilityType().equals(AbilityType.SPECIAL_ACTION)) { ability.setControllerId(this.getId()); if (ability instanceof ActivatedAbility && ability.getZone().match(Zone.HAND) && ((ActivatedAbility) ability).canActivate(playerId, game)) { @@ -1228,8 +1233,9 @@ public abstract class PlayerImpl implements Player, Serializable { } } } - getOtherUseableActivatedAbilities(object, zone, game, useable); } + getOtherUseableActivatedAbilities(object, zone, game, useable); + return useable; } @@ -1237,49 +1243,52 @@ public abstract class PlayerImpl implements Player, Serializable { private void getOtherUseableActivatedAbilities(MageObject object, Zone zone, Game game, Map useable) { Abilities otherAbilities = game.getState().getActivatedOtherAbilities(object.getId(), zone); if (otherAbilities != null) { + boolean canUse = !(object instanceof Permanent) || ((Permanent) object).canUseActivatedAbilities(game); for (ActivatedAbility ability : otherAbilities) { - Card card = game.getCard(ability.getSourceId()); - if (card.isSplitCard() && ability instanceof FlashbackAbility) { - FlashbackAbility flashbackAbility; - // Left Half - if (card.getCardType().contains(CardType.INSTANT)) { - flashbackAbility = new FlashbackAbility(((SplitCard) card).getLeftHalfCard().getManaCost(), TimingRule.INSTANT); - } else { - flashbackAbility = new FlashbackAbility(((SplitCard) card).getLeftHalfCard().getManaCost(), TimingRule.SORCERY); - } - flashbackAbility.setSourceId(card.getId()); - flashbackAbility.setControllerId(card.getOwnerId()); - flashbackAbility.setSpellAbilityType(SpellAbilityType.SPLIT_LEFT); - flashbackAbility.setAbilityName(((SplitCard) card).getLeftHalfCard().getName()); - if (flashbackAbility.canActivate(playerId, game)) { - useable.put(flashbackAbility.getId(), flashbackAbility); - } - // Right Half - if (card.getCardType().contains(CardType.INSTANT)) { - flashbackAbility = new FlashbackAbility(((SplitCard) card).getRightHalfCard().getManaCost(), TimingRule.INSTANT); - } else { - flashbackAbility = new FlashbackAbility(((SplitCard) card).getRightHalfCard().getManaCost(), TimingRule.SORCERY); - } - flashbackAbility.setSourceId(card.getId()); - flashbackAbility.setControllerId(card.getOwnerId()); - flashbackAbility.setSpellAbilityType(SpellAbilityType.SPLIT_RIGHT); - flashbackAbility.setAbilityName(((SplitCard) card).getRightHalfCard().getName()); - if (flashbackAbility.canActivate(playerId, game)) { - useable.put(flashbackAbility.getId(), flashbackAbility); - } + if (canUse || ability.getAbilityType().equals(AbilityType.SPECIAL_ACTION)) { + Card card = game.getCard(ability.getSourceId()); + if (card.isSplitCard() && ability instanceof FlashbackAbility) { + FlashbackAbility flashbackAbility; + // Left Half + if (card.getCardType().contains(CardType.INSTANT)) { + flashbackAbility = new FlashbackAbility(((SplitCard) card).getLeftHalfCard().getManaCost(), TimingRule.INSTANT); + } else { + flashbackAbility = new FlashbackAbility(((SplitCard) card).getLeftHalfCard().getManaCost(), TimingRule.SORCERY); + } + flashbackAbility.setSourceId(card.getId()); + flashbackAbility.setControllerId(card.getOwnerId()); + flashbackAbility.setSpellAbilityType(SpellAbilityType.SPLIT_LEFT); + flashbackAbility.setAbilityName(((SplitCard) card).getLeftHalfCard().getName()); + if (flashbackAbility.canActivate(playerId, game)) { + useable.put(flashbackAbility.getId(), flashbackAbility); + } + // Right Half + if (card.getCardType().contains(CardType.INSTANT)) { + flashbackAbility = new FlashbackAbility(((SplitCard) card).getRightHalfCard().getManaCost(), TimingRule.INSTANT); + } else { + flashbackAbility = new FlashbackAbility(((SplitCard) card).getRightHalfCard().getManaCost(), TimingRule.SORCERY); + } + flashbackAbility.setSourceId(card.getId()); + flashbackAbility.setControllerId(card.getOwnerId()); + flashbackAbility.setSpellAbilityType(SpellAbilityType.SPLIT_RIGHT); + flashbackAbility.setAbilityName(((SplitCard) card).getRightHalfCard().getName()); + if (flashbackAbility.canActivate(playerId, game)) { + useable.put(flashbackAbility.getId(), flashbackAbility); + } - } else { - useable.put(ability.getId(), ability); + } else { + useable.put(ability.getId(), ability); + } } - } } } protected LinkedHashMap getUseableManaAbilities(MageObject object, Zone zone, Game game) { LinkedHashMap useable = new LinkedHashMap<>(); - if (!(object instanceof Permanent) || ((Permanent) object).canUseActivatedAbilities(game)) { - for (ManaAbility ability : object.getAbilities().getManaAbilities(zone)) { + boolean canUse = !(object instanceof Permanent) || ((Permanent) object).canUseActivatedAbilities(game); + for (ManaAbility ability : object.getAbilities().getManaAbilities(zone)) { + if (canUse || ability.getAbilityType().equals(AbilityType.SPECIAL_ACTION)) { if (ability.canActivate(playerId, game)) { useable.put(ability.getId(), ability); }