diff --git a/Mage.Sets/src/mage/cards/p/PerimeterEnforcer.java b/Mage.Sets/src/mage/cards/p/PerimeterEnforcer.java new file mode 100644 index 00000000000..1829d1b45da --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PerimeterEnforcer.java @@ -0,0 +1,66 @@ +package mage.cards.p; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.TurnedFaceUpAllTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.LifelinkAbility; +import mage.abilities.meta.OrTriggeredAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.AnotherPredicate; + +import java.util.UUID; + +/** + * @author Susucr + */ +public final class PerimeterEnforcer extends CardImpl { + + private static final FilterPermanent filter1 = new FilterPermanent(SubType.DETECTIVE, "another Detective"); + private static final FilterPermanent filter2 = new FilterPermanent(SubType.DETECTIVE, "a Detective you control"); + + static { + filter1.add(AnotherPredicate.instance); + filter2.add(TargetController.YOU.getControllerPredicate()); + } + + + public PerimeterEnforcer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.DETECTIVE); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Lifelink + this.addAbility(LifelinkAbility.getInstance()); + + // Whenever another Detective enters the battlefield under your control and whenever a Detective you control is turned face up, Perimeter Enforcer gets +1/+1 until end of turn. + this.addAbility(new OrTriggeredAbility( + Zone.BATTLEFIELD, + new BoostSourceEffect(1, 1, Duration.EndOfTurn), + false, + "Whenever another Detective enters the battlefield under your control and " + + "whenever a Detective you control is turned face up, ", + new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, null, filter1, false), + new TurnedFaceUpAllTriggeredAbility(null, filter2) + )); + } + + private PerimeterEnforcer(final PerimeterEnforcer card) { + super(card); + } + + @Override + public PerimeterEnforcer copy() { + return new PerimeterEnforcer(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/ProjektorInspector.java b/Mage.Sets/src/mage/cards/p/ProjektorInspector.java new file mode 100644 index 00000000000..6379faa8fe5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/ProjektorInspector.java @@ -0,0 +1,62 @@ +package mage.cards.p; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.TurnedFaceUpAllTriggeredAbility; +import mage.abilities.effects.common.DrawDiscardControllerEffect; +import mage.abilities.meta.OrTriggeredAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.AnotherPredicate; + +import java.util.UUID; + +/** + * @author Susucr + */ +public final class ProjektorInspector extends CardImpl { + + private static final FilterPermanent filter1 = new FilterPermanent(SubType.DETECTIVE, "another Detective"); + private static final FilterPermanent filter2 = new FilterPermanent(SubType.DETECTIVE, "a Detective you control"); + + static { + filter1.add(AnotherPredicate.instance); + filter2.add(TargetController.YOU.getControllerPredicate()); + } + + public ProjektorInspector(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.DETECTIVE); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Whenever Projektor Inspector or another Detective enters the battlefield under your control and whenever a Detective you control is turned face up, you may draw a card. If you do, discard a card. + this.addAbility(new OrTriggeredAbility( + Zone.BATTLEFIELD, + new DrawDiscardControllerEffect(true), + false, + "Whenever {this} or another Detective enters the battlefield under your control and " + + "whenever a Detective you control is turned face up, ", + new EntersBattlefieldTriggeredAbility(null), + new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, null, filter1, false), + new TurnedFaceUpAllTriggeredAbility(null, filter2) + )); + } + + private ProjektorInspector(final ProjektorInspector card) { + super(card); + } + + @Override + public ProjektorInspector copy() { + return new ProjektorInspector(this); + } +} diff --git a/Mage.Sets/src/mage/sets/MurdersAtKarlovManor.java b/Mage.Sets/src/mage/sets/MurdersAtKarlovManor.java index 52af4072c47..73a31beb756 100644 --- a/Mage.Sets/src/mage/sets/MurdersAtKarlovManor.java +++ b/Mage.Sets/src/mage/sets/MurdersAtKarlovManor.java @@ -209,6 +209,7 @@ public final class MurdersAtKarlovManor extends ExpansionSet { cards.add(new SetCardInfo("On the Job", 30, Rarity.COMMON, mage.cards.o.OnTheJob.class)); cards.add(new SetCardInfo("Out Cold", 66, Rarity.COMMON, mage.cards.o.OutCold.class)); cards.add(new SetCardInfo("Outrageous Robbery", 97, Rarity.RARE, mage.cards.o.OutrageousRobbery.class)); + cards.add(new SetCardInfo("Perimeter Enforcer", 31, Rarity.UNCOMMON, mage.cards.p.PerimeterEnforcer.class)); cards.add(new SetCardInfo("Person of Interest", 139, Rarity.COMMON, mage.cards.p.PersonOfInterest.class)); cards.add(new SetCardInfo("Persuasive Interrogators", 98, Rarity.UNCOMMON, mage.cards.p.PersuasiveInterrogators.class)); cards.add(new SetCardInfo("Pick Your Poison", 170, Rarity.COMMON, mage.cards.p.PickYourPoison.class)); @@ -218,6 +219,7 @@ public final class MurdersAtKarlovManor extends ExpansionSet { cards.add(new SetCardInfo("Presumed Dead", 100, Rarity.UNCOMMON, mage.cards.p.PresumedDead.class)); cards.add(new SetCardInfo("Private Eye", 223, Rarity.UNCOMMON, mage.cards.p.PrivateEye.class)); cards.add(new SetCardInfo("Proft's Eidetic Memory", 67, Rarity.RARE, mage.cards.p.ProftsEideticMemory.class)); + cards.add(new SetCardInfo("Projektor Inspector", 68, Rarity.COMMON, mage.cards.p.ProjektorInspector.class)); cards.add(new SetCardInfo("Public Thoroughfare", 265, Rarity.COMMON, mage.cards.p.PublicThoroughfare.class)); cards.add(new SetCardInfo("Push // Pull", 250, Rarity.UNCOMMON, mage.cards.p.PushPull.class)); cards.add(new SetCardInfo("Pyrotechnic Performer", 140, Rarity.RARE, mage.cards.p.PyrotechnicPerformer.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/mkm/ProjektorInspectorTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/mkm/ProjektorInspectorTest.java new file mode 100644 index 00000000000..04feb3bd06d --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/mkm/ProjektorInspectorTest.java @@ -0,0 +1,41 @@ +package org.mage.test.cards.single.mkm; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class ProjektorInspectorTest extends CardTestPlayerBase { + + /** + * {@link mage.cards.p.ProjektorInspector} {U} + * Creature — Human Detective + * Whenever Projektor Inspector or another Detective enters the battlefield under your control and + * whenever a Detective you control is turned face up, you may draw a card. If you do, discard a card. + * 3/2 + */ + private static final String inspector = "Projektor Inspector"; + + @Test + public void test_Trigger_FaceUp() { + setStrictChooseMode(true); + skipInitShuffling(); + + addCard(Zone.LIBRARY, playerA, "Healing Salve"); // for discard + addCard(Zone.BATTLEFIELD, playerA, inspector); + addCard(Zone.HAND, playerA, "Basilica Stalker"); // Disguise {4}{B}, detective + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 8); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Basilica Stalker using Disguise", true); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{4}{B}:"); + setChoice(playerA, true); // yes to loot + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA, "Healing Salve", 1); + } +} diff --git a/Mage/src/main/java/mage/cards/CardImpl.java b/Mage/src/main/java/mage/cards/CardImpl.java index 87c2305f867..1ec3d688aab 100644 --- a/Mage/src/main/java/mage/cards/CardImpl.java +++ b/Mage/src/main/java/mage/cards/CardImpl.java @@ -605,6 +605,14 @@ public abstract class CardImpl extends MageObjectImpl implements Card { ability.setRuleVisible(true); } } + // The current face down implementation is just setting a boolean, so any trigger checking for a + // permanent property once being turned face up is not seeing the right face up data. + // For instance triggers looking for specific subtypes being turned face up (Detectives in MKM set) + // are broken without that processAction call. + // This is somewhat a band-aid on the special action nature of turning a permanent face up. + // 708.8. As a face-down permanent is turned face up, its copiable values revert to its normal copiable values. + // Any effects that have been applied to the face-down permanent still apply to the face-up permanent. + game.getState().processAction(game); game.fireEvent(GameEvent.getEvent(GameEvent.EventType.TURNED_FACE_UP, getId(), source, playerId)); return true; }