From 0e84fd02a041ccbf9c6169c9336256c8b6b3cb08 Mon Sep 17 00:00:00 2001 From: ssk97 Date: Tue, 25 Jun 2024 19:55:58 -0700 Subject: [PATCH] [MKM] implement remaining 4 Cloak cards (#12509) * EtrataDeadlyFugitive * refactor: remove need for Zone.BATTLEFIELD for DealsDamageToAPlayerAllTriggeredAbility with opponent restriction * ExposeTheCulprit * HideInPlainSight * VannifarEvolvedEnigma * Fix for not turning manifested non-permanents face-up, per 701.34g * Add comment on Etrata's unusual behavior --- Mage.Sets/src/mage/cards/c/CoastalPiracy.java | 3 +- .../mage/cards/e/EtrataDeadlyFugitive.java | 131 ++++++++++++++++++ .../src/mage/cards/e/ExposeTheCulprit.java | 114 +++++++++++++++ .../cards/f/FirkraagCunningInstigator.java | 2 - .../src/mage/cards/h/HideInPlainSight.java | 71 ++++++++++ .../mage/cards/k/KedissEmberclawFamiliar.java | 2 +- .../src/mage/cards/s/StrixhavenStadium.java | 7 +- Mage.Sets/src/mage/cards/t/TheRani.java | 21 +-- .../mage/cards/v/VannifarEvolvedEnigma.java | 92 ++++++++++++ .../src/mage/sets/MurdersAtKarlovManor.java | 4 + ...alsDamageToAPlayerAllTriggeredAbility.java | 4 + .../mage/game/permanent/PermanentCard.java | 7 + 12 files changed, 435 insertions(+), 23 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/e/EtrataDeadlyFugitive.java create mode 100644 Mage.Sets/src/mage/cards/e/ExposeTheCulprit.java create mode 100644 Mage.Sets/src/mage/cards/h/HideInPlainSight.java create mode 100644 Mage.Sets/src/mage/cards/v/VannifarEvolvedEnigma.java diff --git a/Mage.Sets/src/mage/cards/c/CoastalPiracy.java b/Mage.Sets/src/mage/cards/c/CoastalPiracy.java index ca402ee2357..d1ecb88a14b 100644 --- a/Mage.Sets/src/mage/cards/c/CoastalPiracy.java +++ b/Mage.Sets/src/mage/cards/c/CoastalPiracy.java @@ -7,7 +7,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SetTargetPointer; import mage.constants.TargetController; -import mage.constants.Zone; import mage.filter.StaticFilters; import java.util.UUID; @@ -22,7 +21,7 @@ public final class CoastalPiracy extends CardImpl { // Whenever a creature you control deals combat damage to an opponent, you may draw a card. this.addAbility(new DealsDamageToAPlayerAllTriggeredAbility( - Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), + new DrawCardSourceControllerEffect(1), StaticFilters.FILTER_CONTROLLED_A_CREATURE, true, SetTargetPointer.PLAYER, true, true, TargetController.OPPONENT )); diff --git a/Mage.Sets/src/mage/cards/e/EtrataDeadlyFugitive.java b/Mage.Sets/src/mage/cards/e/EtrataDeadlyFugitive.java new file mode 100644 index 00000000000..e445b2f6856 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EtrataDeadlyFugitive.java @@ -0,0 +1,131 @@ +package mage.cards.e; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.effects.keyword.ManifestEffect; +import mage.abilities.keyword.DeathtouchAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.card.FaceDownPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.util.CardUtil; + +import java.util.List; +import java.util.UUID; + +/** + * @author notgreat + */ +public final class EtrataDeadlyFugitive extends CardImpl { + private static final FilterPermanent filterAssassin = new FilterControlledPermanent("an Assassin you control"); + private static final FilterPermanent filterFaceDown = new FilterControlledPermanent("Face-down creatures you control"); + + static { + filterAssassin.add(SubType.ASSASSIN.getPredicate()); + filterFaceDown.add(FaceDownPredicate.instance); + } + + public EtrataDeadlyFugitive(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{B}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.VAMPIRE); + this.subtype.add(SubType.ASSASSIN); + this.power = new MageInt(1); + this.toughness = new MageInt(4); + + // Deathtouch + this.addAbility(DeathtouchAbility.getInstance()); + + // Face-down creatures you control have "{2}{U}{B}: Turn this creature face up. If you can't, exile it, then you may cast the exiled card without paying its mana cost." + this.addAbility(new SimpleStaticAbility(new GainAbilityAllEffect(new SimpleActivatedAbility( + new EtrataFlipEffect(), new ManaCostsImpl<>("{2}{U}{B}")), Duration.WhileOnBattlefield, filterFaceDown))); + + // Whenever an Assassin you control deals combat damage to an opponent, cloak the top card of that player's library. + this.addAbility(new DealsDamageToAPlayerAllTriggeredAbility(new EtrataCloakEffect(), filterAssassin, + false, SetTargetPointer.NONE, true, true, TargetController.OPPONENT)); + } + + private EtrataDeadlyFugitive(final EtrataDeadlyFugitive card) { + super(card); + } + + @Override + public EtrataDeadlyFugitive copy() { + return new EtrataDeadlyFugitive(this); + } +} + +class EtrataCloakEffect extends OneShotEffect { + EtrataCloakEffect() { + super(Outcome.PutCreatureInPlay); + staticText = "cloak the top card of that player's library"; + } + + private EtrataCloakEffect(final EtrataCloakEffect effect) { + super(effect); + } + + @Override + public EtrataCloakEffect copy() { + return new EtrataCloakEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Player opponent = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (controller == null || opponent == null) { + return false; + } + List cloakedList = ManifestEffect.doManifestCards(game, source, controller, opponent.getLibrary().getTopCards(game, 1), true); + return !cloakedList.isEmpty(); + } +} + +class EtrataFlipEffect extends OneShotEffect { + + EtrataFlipEffect() { + super(Outcome.Benefit); + staticText = "Turn this creature face up. If you can't, exile it, then you may cast the exiled card without paying its mana cost."; + } + + private EtrataFlipEffect(final EtrataFlipEffect effect) { + super(effect); + } + + @Override + public EtrataFlipEffect copy() { + return new EtrataFlipEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + Player player = game.getPlayer(source.getControllerId()); + if (permanent != null && player != null) { + boolean success = permanent.turnFaceUp(source, game, source.getControllerId()); + if (!success) { + Card card = permanent.getMainCard(); + player.moveCards(card, Zone.EXILED, source, game); + game.processAction(); + CardUtil.castSpellWithAttributesForFree(player, source, game, card); + // Not sure why, but the client asks if you want to cast a face-down creature instead of the actual spell + // It plays correctly and casts the instant/sorcery spell anyway + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/e/ExposeTheCulprit.java b/Mage.Sets/src/mage/cards/e/ExposeTheCulprit.java new file mode 100644 index 00000000000..067b28df715 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/ExposeTheCulprit.java @@ -0,0 +1,114 @@ +package mage.cards.e; + +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.TurnFaceUpTargetEffect; +import mage.abilities.effects.keyword.ManifestEffect; +import mage.abilities.keyword.DisguiseAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.card.FaceDownPredicate; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author notgreat + */ +public final class ExposeTheCulprit extends CardImpl { + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("face-down creature"); + + static { + filter.add(FaceDownPredicate.instance); + } + + public ExposeTheCulprit(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}"); + + // Choose one or both -- + this.getSpellAbility().getModes().setMinModes(1); + this.getSpellAbility().getModes().setMaxModes(2); + + // * Turn target face-down creature face up. + this.getSpellAbility().addEffect(new TurnFaceUpTargetEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + + // * Exile any number of face-up creatures you control with disguise in a face-down pile, shuffle that pile, then cloak them. + Mode mode = new Mode(new ExposeTheCulpritEffect()); + this.getSpellAbility().addMode(mode); + } + + private ExposeTheCulprit(final ExposeTheCulprit card) { + super(card); + } + + @Override + public ExposeTheCulprit copy() { + return new ExposeTheCulprit(this); + } +} + +class ExposeTheCulpritEffect extends OneShotEffect { + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("face-up creatures you control with disguise"); + + static { + filter.add(Predicates.not(FaceDownPredicate.instance)); + filter.add(new AbilityPredicate(DisguiseAbility.class)); + } + + ExposeTheCulpritEffect() { + super(Outcome.PutCreatureInPlay); + this.staticText = "Exile any number of face-up creatures you control with disguise in a face-down pile, shuffle that pile, then cloak them."; + } + + private ExposeTheCulpritEffect(final ExposeTheCulpritEffect effect) { + super(effect); + } + + @Override + public ExposeTheCulpritEffect copy() { + return new ExposeTheCulpritEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + Target creatures = new TargetPermanent(0, Integer.MAX_VALUE, filter, true); + if (controller.choose(Outcome.Neutral, creatures, source, game)) { + List cardsToCloak = creatures.getTargets().stream().map( + x -> { + Card card = game.getCard(x); + if (card != null) { + card.setFaceDown(true, game); + } + return card; + } + ).filter(Objects::nonNull).collect(Collectors.toList()); + if (controller.moveCards(new HashSet<>(cardsToCloak), Zone.EXILED, source, game)) { + Collections.shuffle(cardsToCloak); + game.informPlayers(controller.getLogName() + " shuffles the face-down pile"); + game.processAction(); + ManifestEffect.doManifestCards(game, source, controller, new LinkedHashSet<>(cardsToCloak), true); + } + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/f/FirkraagCunningInstigator.java b/Mage.Sets/src/mage/cards/f/FirkraagCunningInstigator.java index a2536853e8f..3ca9c31a2d8 100644 --- a/Mage.Sets/src/mage/cards/f/FirkraagCunningInstigator.java +++ b/Mage.Sets/src/mage/cards/f/FirkraagCunningInstigator.java @@ -23,7 +23,6 @@ import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.target.TargetPermanent; -import java.util.Collection; import java.util.UUID; /** @@ -56,7 +55,6 @@ public final class FirkraagCunningInstigator extends CardImpl { // Whenever a creature deals combat damage to one of your opponents, if that creature had to attack this combat, you put a +1/+1 counter on Firkraag, Cunning Instigator and you draw a card. Ability ability = new DealsDamageToAPlayerAllTriggeredAbility( - Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()) .setText("you put a +1/+1 counter on {this}"), filter, false, SetTargetPointer.NONE, diff --git a/Mage.Sets/src/mage/cards/h/HideInPlainSight.java b/Mage.Sets/src/mage/cards/h/HideInPlainSight.java new file mode 100644 index 00000000000..03b47a9201d --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HideInPlainSight.java @@ -0,0 +1,71 @@ +package mage.cards.h; + +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.abilities.effects.keyword.ManifestEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.constants.CardType; +import mage.constants.PutCards; +import mage.game.Game; +import mage.players.Player; + +import java.util.Objects; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * + * @author notgreat + */ +public final class HideInPlainSight extends CardImpl { + + public HideInPlainSight(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}"); + + // Look at the top five cards of your library, cloak two of them, and put the rest on the bottom of your library in a random order. + this.getSpellAbility().addEffect(new HideInPlainSightEffect()); + + } + + private HideInPlainSight(final HideInPlainSight card) { + super(card); + } + + @Override + public HideInPlainSight copy() { + return new HideInPlainSight(this); + } +} + +class HideInPlainSightEffect extends LookLibraryAndPickControllerEffect { + HideInPlainSightEffect() { + super(5, 2, PutCards.BATTLEFIELD, PutCards.BOTTOM_RANDOM); + } + + private HideInPlainSightEffect(final HideInPlainSightEffect effect) { + super(effect); + } + + @Override + public HideInPlainSightEffect copy() { + return new HideInPlainSightEffect(this); + } + + @Override + public boolean actionWithPickedCards(Game game, Ability source, Player player, Cards pickedCards, Cards otherCards) { + Set cards = pickedCards.stream().map(game::getCard).filter(Objects::nonNull).collect(Collectors.toSet()); + boolean result = !(ManifestEffect.doManifestCards(game, source, player, cards, true)).isEmpty(); + result |= putLookedCards.moveCards(player, otherCards, source, game); + return result; + } + + @Override + public String getText(Mode mode) { + return "Look at the top five cards of your library, cloak two of them, and put the rest on the bottom of your library in a random order"; + } +} diff --git a/Mage.Sets/src/mage/cards/k/KedissEmberclawFamiliar.java b/Mage.Sets/src/mage/cards/k/KedissEmberclawFamiliar.java index 1a18d68eff0..8ae1a65e895 100644 --- a/Mage.Sets/src/mage/cards/k/KedissEmberclawFamiliar.java +++ b/Mage.Sets/src/mage/cards/k/KedissEmberclawFamiliar.java @@ -38,7 +38,7 @@ public final class KedissEmberclawFamiliar extends CardImpl { // Whenever a commander you control deals combat damage to an opponent, it deals that much damage to each other opponent. this.addAbility(new DealsDamageToAPlayerAllTriggeredAbility( - Zone.BATTLEFIELD, new KedissEmberclawFamiliarEffect(), filter, false, + new KedissEmberclawFamiliarEffect(), filter, false, SetTargetPointer.PLAYER, true, true, TargetController.OPPONENT )); diff --git a/Mage.Sets/src/mage/cards/s/StrixhavenStadium.java b/Mage.Sets/src/mage/cards/s/StrixhavenStadium.java index 467728d4681..a257f4f0c1e 100644 --- a/Mage.Sets/src/mage/cards/s/StrixhavenStadium.java +++ b/Mage.Sets/src/mage/cards/s/StrixhavenStadium.java @@ -9,7 +9,10 @@ import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; import mage.abilities.mana.ColorlessManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SetTargetPointer; +import mage.constants.TargetController; import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.game.Game; @@ -37,7 +40,7 @@ public final class StrixhavenStadium extends CardImpl { // Whenever a creature you control deals combat damage to an opponent, put a point counter on Strixhaven Stadium. Then if it has ten or more point counters on it, remove them all and that player loses the game. ability = new DealsDamageToAPlayerAllTriggeredAbility( - Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.POINT.createInstance()), + new AddCountersSourceEffect(CounterType.POINT.createInstance()), StaticFilters.FILTER_CONTROLLED_A_CREATURE, false, SetTargetPointer.PLAYER, true, true, TargetController.OPPONENT ); diff --git a/Mage.Sets/src/mage/cards/t/TheRani.java b/Mage.Sets/src/mage/cards/t/TheRani.java index 189f0d21692..ee7a0524a4d 100644 --- a/Mage.Sets/src/mage/cards/t/TheRani.java +++ b/Mage.Sets/src/mage/cards/t/TheRani.java @@ -1,32 +1,22 @@ package mage.cards.t; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.DealsCombatDamageTriggeredAbility; import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility; import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.CreateTokenEffect; -import mage.abilities.effects.common.DrawCardSourceControllerEffect; -import mage.abilities.effects.common.combat.GoadTargetEffect; -import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.keyword.InvestigateEffect; -import mage.constants.SubType; -import mage.constants.SuperType; -import mage.constants.TargetController; -import mage.constants.Zone; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.GoadedPredicate; import mage.game.Game; import mage.game.permanent.token.MarkOfTheRaniToken; import mage.target.common.TargetCreaturePermanent; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.SetTargetPointer; + +import java.util.UUID; /** * @@ -57,7 +47,6 @@ public final class TheRani extends CardImpl { // Whenever a goaded creature deals combat damage to one of your opponents, investigate. Ability damageDealtAbility = new DealsDamageToAPlayerAllTriggeredAbility( - Zone.BATTLEFIELD, new InvestigateEffect(), filter, false, SetTargetPointer.NONE, true, false, TargetController.OPPONENT) diff --git a/Mage.Sets/src/mage/cards/v/VannifarEvolvedEnigma.java b/Mage.Sets/src/mage/cards/v/VannifarEvolvedEnigma.java new file mode 100644 index 00000000000..a9c628fc471 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VannifarEvolvedEnigma.java @@ -0,0 +1,92 @@ +package mage.cards.v; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.common.BeginningOfCombatTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.AddCountersAllEffect; +import mage.abilities.effects.keyword.ManifestEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.*; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.ColorlessPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInHand; + +import java.util.UUID; + +/** + * @author notgreat + */ +public final class VannifarEvolvedEnigma extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("colorless creature you control"); + + static { + filter.add(ColorlessPredicate.instance); + } + + public VannifarEvolvedEnigma(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{U}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.ELF); + this.subtype.add(SubType.OOZE); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // At the beginning of combat on your turn, choose one -- + // * Cloak a card from your hand. + // * Put a +1/+1 counter on each colorless creature you control. + Ability ability = new BeginningOfCombatTriggeredAbility(new VannifarCloakAbility(), TargetController.YOU, false); + ability.addMode(new Mode(new AddCountersAllEffect(CounterType.P1P1.createInstance(), filter))); + this.addAbility(ability); + } + + private VannifarEvolvedEnigma(final VannifarEvolvedEnigma card) { + super(card); + } + + @Override + public VannifarEvolvedEnigma copy() { + return new VannifarEvolvedEnigma(this); + } +} + +class VannifarCloakAbility extends OneShotEffect { + VannifarCloakAbility() { + super(Outcome.PutCreatureInPlay); + staticText = "cloak a card from your hand"; + } + + private VannifarCloakAbility(final VannifarCloakAbility effect) { + super(effect); + } + + @Override + public VannifarCloakAbility copy() { + return new VannifarCloakAbility(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + TargetCardInHand target = new TargetCardInHand(); + if (controller.choose(Outcome.PutCardInPlay, target, source, game)) { + Cards cards = new CardsImpl(target.getTargets()); + return !ManifestEffect.doManifestCards(game, source, controller, cards.getCards(game), true).isEmpty(); + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/MurdersAtKarlovManor.java b/Mage.Sets/src/mage/sets/MurdersAtKarlovManor.java index 0018e3baabc..de7475c3240 100644 --- a/Mage.Sets/src/mage/sets/MurdersAtKarlovManor.java +++ b/Mage.Sets/src/mage/sets/MurdersAtKarlovManor.java @@ -113,9 +113,11 @@ public final class MurdersAtKarlovManor extends ExpansionSet { cards.add(new SetCardInfo("Eliminate the Impossible", 54, Rarity.UNCOMMON, mage.cards.e.EliminateTheImpossible.class)); cards.add(new SetCardInfo("Escape Tunnel", 261, Rarity.COMMON, mage.cards.e.EscapeTunnel.class)); cards.add(new SetCardInfo("Essence of Antiquity", 15, Rarity.UNCOMMON, mage.cards.e.EssenceOfAntiquity.class)); + cards.add(new SetCardInfo("Etrata, Deadly Fugitive", 200, Rarity.MYTHIC, mage.cards.e.EtrataDeadlyFugitive.class)); cards.add(new SetCardInfo("Evidence Examiner", 201, Rarity.UNCOMMON, mage.cards.e.EvidenceExaminer.class)); cards.add(new SetCardInfo("Exit Specialist", 55, Rarity.UNCOMMON, mage.cards.e.ExitSpecialist.class)); cards.add(new SetCardInfo("Expedited Inheritance", 123, Rarity.MYTHIC, mage.cards.e.ExpeditedInheritance.class)); + cards.add(new SetCardInfo("Expose the Culprit", 124, Rarity.UNCOMMON, mage.cards.e.ExposeTheCulprit.class)); cards.add(new SetCardInfo("Extract a Confession", 84, Rarity.COMMON, mage.cards.e.ExtractAConfession.class)); cards.add(new SetCardInfo("Ezrim, Agency Chief", 202, Rarity.RARE, mage.cards.e.EzrimAgencyChief.class)); cards.add(new SetCardInfo("Fae Flight", 56, Rarity.UNCOMMON, mage.cards.f.FaeFlight.class)); @@ -150,6 +152,7 @@ public final class MurdersAtKarlovManor extends ExpansionSet { cards.add(new SetCardInfo("Harried Dronesmith", 131, Rarity.UNCOMMON, mage.cards.h.HarriedDronesmith.class)); cards.add(new SetCardInfo("Hedge Maze", 262, Rarity.RARE, mage.cards.h.HedgeMaze.class)); cards.add(new SetCardInfo("Hedge Whisperer", 165, Rarity.UNCOMMON, mage.cards.h.HedgeWhisperer.class)); + cards.add(new SetCardInfo("Hide in Plain Sight", 166, Rarity.RARE, mage.cards.h.HideInPlainSight.class)); cards.add(new SetCardInfo("Homicide Investigator", 86, Rarity.RARE, mage.cards.h.HomicideInvestigator.class)); cards.add(new SetCardInfo("Hotshot Investigators", 60, Rarity.COMMON, mage.cards.h.HotshotInvestigators.class)); cards.add(new SetCardInfo("Hunted Bonebrute", 87, Rarity.RARE, mage.cards.h.HuntedBonebrute.class)); @@ -294,6 +297,7 @@ public final class MurdersAtKarlovManor extends ExpansionSet { cards.add(new SetCardInfo("Unyielding Gatekeeper", 35, Rarity.RARE, mage.cards.u.UnyieldingGatekeeper.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Unyielding Gatekeeper", 392, Rarity.RARE, mage.cards.u.UnyieldingGatekeeper.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Urgent Necropsy", 240, Rarity.MYTHIC, mage.cards.u.UrgentNecropsy.class)); + cards.add(new SetCardInfo("Vannifar, Evolved Enigma", 241, Rarity.MYTHIC, mage.cards.v.VannifarEvolvedEnigma.class)); cards.add(new SetCardInfo("Vein Ripper", 110, Rarity.MYTHIC, mage.cards.v.VeinRipper.class)); cards.add(new SetCardInfo("Vengeful Creeper", 182, Rarity.COMMON, mage.cards.v.VengefulCreeper.class)); cards.add(new SetCardInfo("Vengeful Tracker", 147, Rarity.UNCOMMON, mage.cards.v.VengefulTracker.class)); diff --git a/Mage/src/main/java/mage/abilities/common/DealsDamageToAPlayerAllTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DealsDamageToAPlayerAllTriggeredAbility.java index c01dee10210..025c405e9e5 100644 --- a/Mage/src/main/java/mage/abilities/common/DealsDamageToAPlayerAllTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/DealsDamageToAPlayerAllTriggeredAbility.java @@ -32,6 +32,10 @@ public class DealsDamageToAPlayerAllTriggeredAbility extends TriggeredAbilityImp this(Zone.BATTLEFIELD, effect, filter, optional, setTargetPointer, onlyCombat, affectsDefendingPlayer); } + public DealsDamageToAPlayerAllTriggeredAbility(Effect effect, FilterPermanent filter, boolean optional, SetTargetPointer setTargetPointer, boolean onlyCombat, boolean affectsDefendingPlayer, TargetController targetController) { + this(Zone.BATTLEFIELD, effect, filter, optional, setTargetPointer, onlyCombat, affectsDefendingPlayer, targetController); + } + public DealsDamageToAPlayerAllTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional, SetTargetPointer setTargetPointer, boolean onlyCombat, boolean affectsDefendingPlayer) { this(zone, effect, filter, optional, setTargetPointer, onlyCombat, affectsDefendingPlayer, TargetController.ANY); } diff --git a/Mage/src/main/java/mage/game/permanent/PermanentCard.java b/Mage/src/main/java/mage/game/permanent/PermanentCard.java index ec70a4df82a..7242b774892 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentCard.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentCard.java @@ -181,6 +181,13 @@ public class PermanentCard extends PermanentImpl { @Override public boolean turnFaceUp(Ability source, Game game, UUID playerId) { + if (!this.getBasicMageObject().isPermanent()){ + // 701.34g. If a manifested permanent that's represented by an instant or sorcery card would turn face up, + // its controller reveals it and leaves it face down. Abilities that trigger whenever a permanent + // is turned face up won't trigger. + // TODO: add reveal effect + return false; + } if (super.turnFaceUp(source, game, playerId)) { // TODO: miss types, abilities, color and other things for restore?! power.setModifiedBaseValue(power.getBaseValue());