From e2edeb9fcd332332015dcd55ed19c422c3064822 Mon Sep 17 00:00:00 2001 From: drmDev Date: Mon, 28 Mar 2016 14:04:09 -0400 Subject: [PATCH 01/13] Briarbridge Patrol bug fix and test added --- .../BriarbridgePatrol.java | 2 +- .../single/soi/BriarbridgePatrolTest.java | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/soi/BriarbridgePatrolTest.java diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/BriarbridgePatrol.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/BriarbridgePatrol.java index 3e08fbe3d2..500bda7d4a 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/BriarbridgePatrol.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/BriarbridgePatrol.java @@ -91,7 +91,7 @@ class BriarbridgePatrolCondition implements Condition { PermanentsSacrificedWatcher watcher = (PermanentsSacrificedWatcher) game.getState().getWatchers().get(PermanentsSacrificedWatcher.class.getName()); if (watcher != null) { List sacrificedPermanents = watcher.getThisTurnSacrificedPermanents(source.getControllerId()); - if (!sacrificedPermanents.isEmpty()) { + if (sacrificedPermanents != null && !sacrificedPermanents.isEmpty()) { int amountOfClues = 0; for (Permanent permanent : sacrificedPermanents) { if (permanent.getSubtype().contains("Clue")) { diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/BriarbridgePatrolTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/BriarbridgePatrolTest.java new file mode 100644 index 0000000000..7c13b144ca --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/BriarbridgePatrolTest.java @@ -0,0 +1,38 @@ +package org.mage.test.cards.single.soi; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * 3G +Creature - Human Warrior +Whenever Briarbridge Patrol deals damage to one or more creatures, investigate. (Put a colorless Clue artifact token onto the battlefield with "2, Sacrifice this artifact: Draw a card.") + +At the beginning of each end step, if you sacrificed three or more clues this turn, you may put a creature card from your hand onto the battlefield. + * @author escplan9 (Derek Monturo - dmontur1 at gmail dot com) + */ +public class BriarbridgePatrolTest extends CardTestPlayerBase { + + /** + * Deals damage to creature test. + */ + @Test + public void dealtDamageToCreatureInvestigate() { + + addCard(Zone.BATTLEFIELD, playerA, "Briarbridge Patrol", 1); + addCard(Zone.BATTLEFIELD, playerB, "Elite Vanguard", 1); + + attack(1, playerA, "Briarbridge Patrol"); + block(1, playerB, "Elite Vanguard", "Briarbridge Patrol"); + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, "Clue", 1); + assertPermanentCount(playerA, "Briarbridge Patrol", 1); + assertPermanentCount(playerB, "Elite Vanguard", 0); + assertGraveyardCount(playerB, "Elite Vanguard", 1); + } +} From 9b89ccfd21e1f5b703f455ce8ac00a55d4d47600 Mon Sep 17 00:00:00 2001 From: Jared Hall Date: Mon, 28 Mar 2016 14:38:33 -0400 Subject: [PATCH 02/13] [SOI] Implemented Neglected Heirloom --- .../shadowsoverinnistrad/AshmouthBlade.java | 15 ++- .../NeglectedHeirloom.java | 116 ++++++++++++++++++ 2 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/shadowsoverinnistrad/NeglectedHeirloom.java diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/AshmouthBlade.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/AshmouthBlade.java index c87dff1819..a4c27292a9 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/AshmouthBlade.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/AshmouthBlade.java @@ -28,11 +28,16 @@ package mage.sets.shadowsoverinnistrad; import java.util.UUID; +import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; import mage.abilities.keyword.EquipAbility; +import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.CardImpl; +import mage.constants.AttachmentType; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Rarity; @@ -52,8 +57,14 @@ public class AshmouthBlade extends CardImpl { // this card is the second face of double-faced card this.nightCard = true; - // Equipped creature gets +3/+3. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(3, 3))); + // Equipped creature gets +3/+3 + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(3, 3)); + this.addAbility(ability); + + // and has first strike. + Effect effect = new GainAbilityAttachedEffect(FirstStrikeAbility.getInstance(), AttachmentType.EQUIPMENT); + effect.setText("and has first strike"); + ability.addEffect(effect); // Equip {3} this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(3))); diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/NeglectedHeirloom.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/NeglectedHeirloom.java new file mode 100644 index 0000000000..ce24fbb9dd --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/NeglectedHeirloom.java @@ -0,0 +1,116 @@ +/* + * 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.sets.shadowsoverinnistrad; + +import java.util.UUID; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.effects.common.continuous.BoostEquippedEffect; +import mage.abilities.keyword.EquipAbility; +import mage.abilities.keyword.TransformAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * + * @author halljared + */ +public class NeglectedHeirloom extends CardImpl { + + public NeglectedHeirloom(UUID ownerId) { + super(ownerId, 260, "Neglected Heirloom", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT}, "{1}"); + this.expansionSetCode = "SOI"; + this.subtype.add("Equipment"); + + this.canTransform = true; + this.secondSideCard = new AshmouthBlade(ownerId); + + // Equipped creature gets +1/+1. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(1, 1))); + // Equip {1} + this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(1))); + + // When equipped creature transforms, transform Neglected Heirloom. + this.addAbility(new TransformAbility()); + this.addAbility(new NeglectedHeirloomTriggeredAbility()); + + } + + public NeglectedHeirloom(final NeglectedHeirloom card) { + super(card); + } + + @Override + public NeglectedHeirloom copy() { + return new NeglectedHeirloom(this); + } + +} + +class NeglectedHeirloomTriggeredAbility extends TriggeredAbilityImpl { + + public NeglectedHeirloomTriggeredAbility() { + super(Zone.BATTLEFIELD, new TransformSourceEffect(true), false); + } + + public NeglectedHeirloomTriggeredAbility(final NeglectedHeirloomTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.TRANSFORMED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.TRANSFORMED) { + if (game.getPermanent(event.getTargetId()).getAttachments().contains(this.getSourceId())) { + return true; + } + } + return false; + } + + @Override + public NeglectedHeirloomTriggeredAbility copy() { + return new NeglectedHeirloomTriggeredAbility(this); + } + + @Override + public String getRule() { + return "When equipped creature transforms, transform Neglected Heirloom."; + } +} \ No newline at end of file From 4a29ae762c39a2cb3f0ad9636e9f8ed6b7ed1872 Mon Sep 17 00:00:00 2001 From: drmDev Date: Mon, 28 Mar 2016 20:20:19 -0400 Subject: [PATCH 03/13] Welcome to the fold bug fix and tests --- .../WelcomeToTheFold.java | 2 +- .../cards/control/WelcomeToTheFoldTest.java | 49 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/control/WelcomeToTheFoldTest.java diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/WelcomeToTheFold.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/WelcomeToTheFold.java index 0748d69f95..010b57a928 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/WelcomeToTheFold.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/WelcomeToTheFold.java @@ -96,7 +96,7 @@ class WelcomeToTheFoldEffect extends GainControlTargetEffect { maxToughness = source.getManaCostsToPay().getX(); } Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (permanent != null && permanent.getToughness().getValue() <= maxToughness) { + if (permanent != null && permanent.getToughness().getValue() > maxToughness) { this.discard(); return; } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/control/WelcomeToTheFoldTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/control/WelcomeToTheFoldTest.java new file mode 100644 index 0000000000..ece97a98ce --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/control/WelcomeToTheFoldTest.java @@ -0,0 +1,49 @@ +package org.mage.test.cards.control; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * 2UU + Sorcery + Madness XUU (If you discard this card, discard it into exile. When you do, cast it for its madness cost or put it into your graveyard.) + + Gain control of target creature if its toughness is 2 or less. + * If Welcome to the Fold's madness cost was paid, instead gain control of that creature if its toughness is X or less. + * @author escplan9 (Derek Monturo - dmontur1 at gmail dot com) + */ +public class WelcomeToTheFoldTest extends CardTestPlayerBase { + + /** + * Paid with regular cost, gain control of creatures with toughness <= 2 + */ + @Test + public void regularCostVariousCreatures() { + + addCard(Zone.HAND, playerA, "Welcome to the Fold", 3); + addCard(Zone.BATTLEFIELD, playerA, "Island", 12); + + addCard(Zone.BATTLEFIELD, playerB, "Arashin Cleric", 1); // 1/3 + addCard(Zone.BATTLEFIELD, playerB, "Jace, Vryn's Prodigy", 1); // 0/2 + addCard(Zone.BATTLEFIELD, playerB, "Elite Vanguard", 1); // 2/1 + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Welcome to the Fold"); + addTarget(playerA, "Arashin Cleric"); // does not gain control + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Welcome to the Fold"); + addTarget(playerA, "Jace, Vryn's Prodigy"); // gains control + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Welcome to the Fold"); + addTarget(playerA, "Elite Vanguard"); // gains control + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerA, "Welcome to the Fold", 3); + assertPermanentCount(playerA, "Arashin Cleric", 0); // should not gain control + assertPermanentCount(playerA, "Jace, Vryn's Prodigy", 1); // should gain control + assertPermanentCount(playerA, "Elite Vanguard", 1); + } + + // TODO: add a madness cost test +} From 307f59a70c8809db17d9c4ef69a837f1ed8d36a1 Mon Sep 17 00:00:00 2001 From: drmDev Date: Tue, 29 Mar 2016 09:09:35 -0400 Subject: [PATCH 04/13] Tests for still bugged Tireless Trackker and Wolf of Devils Breach --- .../cards/single/soi/TirelessTrackerTest.java | 40 ++++++++++++ .../single/soi/WolfOfDevilsBreachTest.java | 61 +++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/soi/TirelessTrackerTest.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/soi/WolfOfDevilsBreachTest.java diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/TirelessTrackerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/TirelessTrackerTest.java new file mode 100644 index 0000000000..fe4adf12e7 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/TirelessTrackerTest.java @@ -0,0 +1,40 @@ +package org.mage.test.cards.single.soi; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * 2G +Creature - Human Scout +Whenever a land enters the battlefield under your control, investigate. + +Whenever you sacrifice a Clue, put a +1/+1 counter on Tireless Tracker. +* + * @author escplan9 (Derek Monturo - dmontur1 at gmail dot com) + */ +public class TirelessTrackerTest extends CardTestPlayerBase { + + /** + * Only landfall under your control triggers first ability + */ + @Test + public void landfallUnderOwnControlTriggers() { + + addCard(Zone.BATTLEFIELD, playerA, "Tireless Tracker", 1); + addCard(Zone.HAND, playerA, "Forest", 3); + addCard(Zone.HAND, playerB, "Wastes", 3); + + playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Forest"); + playLand(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Wastes"); + setStopAt(2, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, "Forest", 1); + assertPermanentCount(playerB, "Wastes", 1); + assertPermanentCount(playerA, "Clue", 1); + } + + // TODO: add tests for 2nd ability +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/WolfOfDevilsBreachTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/WolfOfDevilsBreachTest.java new file mode 100644 index 0000000000..0223b44a08 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/WolfOfDevilsBreachTest.java @@ -0,0 +1,61 @@ +package org.mage.test.cards.single.soi; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * 3RR +Creature - Elemental Wolf + *Whenever Wolf of Devil's Breach attacks, you may pay 1R and discard a card. + * If you do, Wolf of Devil's Breach deals damage to target creature or planeswalker equal to the discarded card's converted mana cost. + * @author escplan9 (Derek Monturo - dmontur1 at gmail dot com) + */ +public class WolfOfDevilsBreachTest extends CardTestPlayerBase { + + /** + * + */ + @Test + public void attackChooseToPay() { + + addCard(Zone.BATTLEFIELD, playerA, "Wolf of Devil's Breach", 1); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2); + addCard(Zone.HAND, playerA, "Bronze Sable", 1); // (2) 2/1 + addCard(Zone.BATTLEFIELD, playerB, "Grizzly Bears", 1); // 2/2 + + attack(1, playerA, "Wolf of Devil's Breach"); + setChoice(playerA, "Yes"); + setChoice(playerA, "Bronze Sable"); + addTarget(playerA, "Grizzly Bears"); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertGraveyardCount(playerA, "Bronze Sable", 1); + assertGraveyardCount(playerB, "Grizzly Bears", 1); + } + + /** + * + */ + @Test + public void attackDoNotPay() { + + addCard(Zone.BATTLEFIELD, playerA, "Wolf of Devil's Breach", 1); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2); + addCard(Zone.HAND, playerA, "Bronze Sable", 1); // (2) 2/1 + addCard(Zone.BATTLEFIELD, playerB, "Grizzly Bears", 1); // 2/2 + + attack(1, playerA, "Wolf of Devil's Breach"); + setChoice(playerA, "No"); + setChoice(playerA, "Bronze Sable"); + addTarget(playerA, "Grizzly Bears"); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertHandCount(playerA, "Bronze Sable", 1); // never discarded + assertGraveyardCount(playerA, "Bronze Sable", 0); + assertGraveyardCount(playerB, "Grizzly Bears", 0); + } +} From 6f92850a6b520d1fac59d224146dc60aee5cc72c Mon Sep 17 00:00:00 2001 From: drmDev Date: Tue, 29 Mar 2016 11:55:11 -0400 Subject: [PATCH 05/13] Tireless tracker 2nd ability fix --- .../shadowsoverinnistrad/TirelessTracker.java | 41 +++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/TirelessTracker.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/TirelessTracker.java index 42c74f226c..027303b6e1 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/TirelessTracker.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/TirelessTracker.java @@ -29,19 +29,21 @@ package mage.sets.shadowsoverinnistrad; import java.util.UUID; import mage.MageInt; +import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; -import mage.abilities.common.SacrificeAllTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.keyword.InvestigateEffect; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; -import mage.constants.TargetController; import mage.constants.Zone; import mage.counters.CounterType; import mage.filter.common.FilterControlledLandPermanent; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; /** * @@ -67,7 +69,7 @@ public class TirelessTracker extends CardImpl { this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new InvestigateEffect(), new FilterControlledLandPermanent("a land"), false, null, true)); // Whenever you sacrifice a Clue, put a +1/+1 counter on Tireless Tracker. - this.addAbility(new SacrificeAllTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), filter, TargetController.YOU, false)); + this.addAbility(new TirelessTrackerTriggeredAbility()); } public TirelessTracker(final TirelessTracker card) { @@ -79,3 +81,36 @@ public class TirelessTracker extends CardImpl { return new TirelessTracker(this); } } + +class TirelessTrackerTriggeredAbility extends TriggeredAbilityImpl { + + public TirelessTrackerTriggeredAbility() { + super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance())); + setLeavesTheBattlefieldTrigger(true); + } + + public TirelessTrackerTriggeredAbility(final TirelessTrackerTriggeredAbility ability) { + super(ability); + } + + @Override + public TirelessTrackerTriggeredAbility copy() { + return new TirelessTrackerTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.SACRIFICED_PERMANENT; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return event.getPlayerId().equals(this.getControllerId()) + && game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD).getSubtype().contains("Clue"); + } + + @Override + public String getRule() { + return "Whenever you sacrifice a Clue, " + super.getRule(); + } +} From 1bcb5cd4f48ee1b4b4fa6efd2b408816e8b6b394 Mon Sep 17 00:00:00 2001 From: drmDev Date: Tue, 29 Mar 2016 14:19:12 -0400 Subject: [PATCH 06/13] MorkrutNecropod bug fix filter --- .../sets/shadowsoverinnistrad/MorkrutNecropod.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/MorkrutNecropod.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/MorkrutNecropod.java index 097783570a..dda372dfc3 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/MorkrutNecropod.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/MorkrutNecropod.java @@ -36,7 +36,6 @@ import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; import mage.filter.FilterPermanent; -import mage.filter.common.FilterLandPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.permanent.AnotherPredicate; @@ -49,9 +48,11 @@ public class MorkrutNecropod extends CardImpl { private static final FilterPermanent filter = new FilterPermanent("another creature or land"); - static { - filter.add(Predicates.or(Predicates.and(new AnotherPredicate(), new CardTypePredicate(CardType.CREATURE)), - new CardTypePredicate(CardType.LAND))); + static { + filter.add(Predicates.or( + new CardTypePredicate(CardType.CREATURE), + new CardTypePredicate(CardType.LAND))); + filter.add(new AnotherPredicate()); } public MorkrutNecropod(UUID ownerId) { @@ -66,7 +67,7 @@ public class MorkrutNecropod extends CardImpl { this.addAbility(new MenaceAbility()); // Whenever Morkrut Necropod attacks or blocks, sacrifice another creature or land. - this.addAbility(new AttacksOrBlocksTriggeredAbility(new SacrificeControllerEffect(new FilterLandPermanent(), 1, ""), false)); + this.addAbility(new AttacksOrBlocksTriggeredAbility(new SacrificeControllerEffect(filter, 1, ""), false)); } public MorkrutNecropod(final MorkrutNecropod card) { From 90f8e0380313bd674bb8da2ce41d122c5b1e6544 Mon Sep 17 00:00:00 2001 From: drmDev Date: Tue, 29 Mar 2016 14:52:33 -0400 Subject: [PATCH 07/13] bug fix Ulvenwald Mysteries trigger on clue sac --- .../UlvenwaldMysteries.java | 41 ++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/UlvenwaldMysteries.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/UlvenwaldMysteries.java index 08a9eb83d4..92f2aa9c73 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/UlvenwaldMysteries.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/UlvenwaldMysteries.java @@ -28,20 +28,24 @@ package mage.sets.shadowsoverinnistrad; import java.util.UUID; +import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.DiesCreatureTriggeredAbility; -import mage.abilities.common.SacrificeAllTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.keyword.InvestigateEffect; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; import mage.constants.TargetController; +import mage.constants.Zone; import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.filter.predicate.permanent.ControllerPredicate; import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; /** * @@ -66,7 +70,7 @@ public class UlvenwaldMysteries extends CardImpl { this.addAbility(new DiesCreatureTriggeredAbility(new InvestigateEffect(), false, filter)); // Whenever you sacrifice a Clue, put a 1/1 white Human Soldier creature token onto the battlefield. - this.addAbility(new SacrificeAllTriggeredAbility(new CreateTokenEffect(new HumanSoldierToken()), filterClue, TargetController.YOU, false)); + this.addAbility(new UlvenwaldMysteriesTriggeredAbility()); } public UlvenwaldMysteries(final UlvenwaldMysteries card) { @@ -78,3 +82,36 @@ public class UlvenwaldMysteries extends CardImpl { return new UlvenwaldMysteries(this); } } + +class UlvenwaldMysteriesTriggeredAbility extends TriggeredAbilityImpl { + + public UlvenwaldMysteriesTriggeredAbility() { + super(Zone.BATTLEFIELD, new CreateTokenEffect(new HumanSoldierToken())); + setLeavesTheBattlefieldTrigger(true); + } + + public UlvenwaldMysteriesTriggeredAbility(final UlvenwaldMysteriesTriggeredAbility ability) { + super(ability); + } + + @Override + public UlvenwaldMysteriesTriggeredAbility copy() { + return new UlvenwaldMysteriesTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.SACRIFICED_PERMANENT; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return event.getPlayerId().equals(this.getControllerId()) + && game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD).getSubtype().contains("Clue"); + } + + @Override + public String getRule() { + return "Whenever you sacrifice a Clue, " + super.getRule(); + } +} \ No newline at end of file From 5b96b6ccb1fe47a4808955159a8640990d7080c2 Mon Sep 17 00:00:00 2001 From: drmDev Date: Tue, 29 Mar 2016 20:18:38 -0400 Subject: [PATCH 08/13] bug fixes for ConfrontTheUnknown, RelenlessDead. Card implementation HarvestHand and nightside fix for it --- .../ConfrontTheUnknown.java | 2 +- .../shadowsoverinnistrad/HarvestHand.java | 108 ++++++++++++++++++ .../shadowsoverinnistrad/RelentlessDead.java | 6 +- .../shadowsoverinnistrad/ScroungedScythe.java | 5 +- 4 files changed, 117 insertions(+), 4 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/shadowsoverinnistrad/HarvestHand.java diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/ConfrontTheUnknown.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/ConfrontTheUnknown.java index cefff87aa9..0d76511976 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/ConfrontTheUnknown.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/ConfrontTheUnknown.java @@ -60,7 +60,7 @@ public class ConfrontTheUnknown extends CardImpl { Effect effect = new InvestigateEffect(); effect.setText("Investigate"); getSpellAbility().addEffect(effect); - effect = new BoostTargetEffect(new PermanentsOnBattlefieldCount(filter), new PermanentsOnBattlefieldCount(filter), Duration.EndOfTurn); + effect = new BoostTargetEffect(new PermanentsOnBattlefieldCount(filter), new PermanentsOnBattlefieldCount(filter), Duration.EndOfTurn, true); effect.setText(", then target creature gets +1/+1 until end of turn for each Clue you control. (To investigate, " + "put a colorless Clue artifact token onto the battlefield with \"{2}, Sacrifice this artifact: Draw a card.\")"); getSpellAbility().addEffect(effect); diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/HarvestHand.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/HarvestHand.java new file mode 100644 index 0000000000..c1a20316fa --- /dev/null +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/HarvestHand.java @@ -0,0 +1,108 @@ +/* + * 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.sets.shadowsoverinnistrad; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.TransformAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author halljared + */ +public class HarvestHand extends CardImpl { + + public HarvestHand(UUID ownerId) { + super(ownerId, 256, "Harvest Hand", Rarity.UNCOMMON, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}"); + this.expansionSetCode = "SOI"; + this.subtype.add("Scarecrow"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + this.canTransform = true; + this.secondSideCard = new ScroungedScythe(ownerId); + + // When Harvest Hand dies, return it to the battlefield transformed under your control. + this.addAbility(new TransformAbility()); + this.addAbility(new DiesTriggeredAbility(new HarvestHandReturnTransformedEffect())); + } + + public HarvestHand(final HarvestHand card) { + super(card); + } + + @Override + public HarvestHand copy() { + return new HarvestHand(this); + } +} + +class HarvestHandReturnTransformedEffect extends OneShotEffect { + + public HarvestHandReturnTransformedEffect() { + super(Outcome.PutCardInPlay); + this.staticText = "Return {this} to the battlefield transformed under your control"; + } + + public HarvestHandReturnTransformedEffect(final HarvestHandReturnTransformedEffect effect) { + super(effect); + } + + @Override + public HarvestHandReturnTransformedEffect copy() { + return new HarvestHandReturnTransformedEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + if (game.getState().getZone(source.getSourceId()).equals(Zone.GRAVEYARD)) { + game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE); + Card card = game.getCard(source.getSourceId()); + if (card != null) { + controller.moveCards(card, Zone.BATTLEFIELD, source, game); + } + } + return true; + } + return false; + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/RelentlessDead.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/RelentlessDead.java index f768d83ec1..2b6fc10eb7 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/RelentlessDead.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/RelentlessDead.java @@ -46,6 +46,7 @@ import mage.constants.Rarity; import mage.constants.Zone; import mage.filter.Filter; import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.AnotherCardPredicate; import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.game.Game; @@ -105,13 +106,14 @@ class RelentlessDeadEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - if (controller.chooseUse(Outcome.BoostCreature, "Do you want to to pay {X}?", source, game)) { + if (controller.chooseUse(Outcome.BoostCreature, "Do you want to pay {X}?", source, game)) { int costX = controller.announceXMana(0, Integer.MAX_VALUE, "Announce the value for {X}", game, source); Cost cost = new GenericManaCost(costX); if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false, null)) { - FilterCard filter = new FilterCard("Zombie card with converted mana cost " + costX); + FilterCard filter = new FilterCard("Another target Zombie card with converted mana cost " + costX); filter.add(new SubtypePredicate("Zombie")); filter.add(new ConvertedManaCostPredicate(Filter.ComparisonType.Equal, costX)); + filter.add(new AnotherCardPredicate()); TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(filter); if (controller.chooseTarget(outcome, target, source, game)) { Card card = game.getCard(target.getFirstTarget()); diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/ScroungedScythe.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/ScroungedScythe.java index 620779982e..627cb3be78 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/ScroungedScythe.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/ScroungedScythe.java @@ -1,3 +1,4 @@ + /* * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. * @@ -56,6 +57,8 @@ public class ScroungedScythe extends CardImpl { this.expansionSetCode = "SOI"; this.subtype.add("Equipment"); + this.nightCard = true; + // Equipped creature gets +1/+1. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(1, 1))); @@ -76,4 +79,4 @@ public class ScroungedScythe extends CardImpl { public ScroungedScythe copy() { return new ScroungedScythe(this); } -} +} \ No newline at end of file From 8b1737b266c95fe390fca6403ea261f154d21c87 Mon Sep 17 00:00:00 2001 From: drmDev Date: Tue, 29 Mar 2016 20:45:03 -0400 Subject: [PATCH 09/13] colors set for DFC night --- .../src/mage/sets/shadowsoverinnistrad/FlameheartWerewolf.java | 1 + .../src/mage/sets/shadowsoverinnistrad/GatstafRavagers.java | 2 ++ Mage.Sets/src/mage/sets/shadowsoverinnistrad/IncitedRabble.java | 1 + .../sets/shadowsoverinnistrad/LoneWolfOfTheNatterknolls.java | 1 + Mage.Sets/src/mage/sets/shadowsoverinnistrad/OneOfThePack.java | 1 + .../src/mage/sets/shadowsoverinnistrad/PersistentNightmare.java | 1 + .../src/mage/sets/shadowsoverinnistrad/VildinPackAlpha.java | 1 + 7 files changed, 8 insertions(+) diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/FlameheartWerewolf.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/FlameheartWerewolf.java index 46184da9a7..bc1092c346 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/FlameheartWerewolf.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/FlameheartWerewolf.java @@ -54,6 +54,7 @@ public class FlameheartWerewolf extends CardImpl { this.subtype.add("Werewolf"); this.power = new MageInt(3); this.toughness = new MageInt(2); + this.color.setRed(true); // this card is the second face of double-faced card this.nightCard = true; diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/GatstafRavagers.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/GatstafRavagers.java index d2e94c23b6..b6d9a6c1f8 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/GatstafRavagers.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/GatstafRavagers.java @@ -53,6 +53,8 @@ public class GatstafRavagers extends CardImpl { this.subtype.add("Werewolf"); this.power = new MageInt(6); this.toughness = new MageInt(5); + + this.color.setRed(true); this.canTransform = true; this.nightCard = true; diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/IncitedRabble.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/IncitedRabble.java index 171234af00..3f48e93493 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/IncitedRabble.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/IncitedRabble.java @@ -51,6 +51,7 @@ public class IncitedRabble extends CardImpl { this.subtype.add("Human"); this.power = new MageInt(2); this.toughness = new MageInt(3); + this.color.setRed(true); // this card is the second face of double-faced card this.nightCard = true; diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/LoneWolfOfTheNatterknolls.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/LoneWolfOfTheNatterknolls.java index 18f57bc13c..3db7714a4f 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/LoneWolfOfTheNatterknolls.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/LoneWolfOfTheNatterknolls.java @@ -56,6 +56,7 @@ public class LoneWolfOfTheNatterknolls extends CardImpl { this.subtype.add("Werewolf"); this.power = new MageInt(3); this.toughness = new MageInt(5); + this.color.setGreen(true); this.nightCard = true; this.canTransform = true; diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/OneOfThePack.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/OneOfThePack.java index 2b7cae32a1..123555415d 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/OneOfThePack.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/OneOfThePack.java @@ -52,6 +52,7 @@ public class OneOfThePack extends CardImpl { this.subtype.add("Werewolf"); this.power = new MageInt(5); this.toughness = new MageInt(6); + this.color.setGreen(true); this.nightCard = true; this.canTransform = true; diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/PersistentNightmare.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/PersistentNightmare.java index 07a99a7907..c6dc27691c 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/PersistentNightmare.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/PersistentNightmare.java @@ -48,6 +48,7 @@ public class PersistentNightmare extends CardImpl { this.subtype.add("Nightmare"); this.power = new MageInt(1); this.toughness = new MageInt(1); + this.color.setBlue(true); // this card is the second face of double-faced card this.nightCard = true; diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/VildinPackAlpha.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/VildinPackAlpha.java index aee570a799..982f8e6454 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/VildinPackAlpha.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/VildinPackAlpha.java @@ -62,6 +62,7 @@ public class VildinPackAlpha extends CardImpl { this.subtype.add("Werewolf"); this.power = new MageInt(4); this.toughness = new MageInt(3); + this.color.setRed(true); this.canTransform = true; this.nightCard = true; From 0d0bd7a8598e8c852fc678657918ffbdebce6d41 Mon Sep 17 00:00:00 2001 From: drmDev Date: Tue, 29 Mar 2016 21:15:16 -0400 Subject: [PATCH 10/13] FleetingMemories clue sac bug fix --- .../FleetingMemories.java | 42 +++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/FleetingMemories.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/FleetingMemories.java index 5d46fad9e1..39ca92a5dc 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/FleetingMemories.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/FleetingMemories.java @@ -29,16 +29,19 @@ package mage.sets.shadowsoverinnistrad; import java.util.UUID; import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.common.SacrificeAllTriggeredAbility; import mage.abilities.effects.common.PutTopCardOfLibraryIntoGraveTargetEffect; import mage.abilities.effects.keyword.InvestigateEffect; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; -import mage.constants.TargetController; +import mage.constants.Zone; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; import mage.target.TargetPlayer; /** @@ -61,7 +64,7 @@ public class FleetingMemories extends CardImpl { this.addAbility(new EntersBattlefieldTriggeredAbility(new InvestigateEffect(), false)); // Whenever you sacrifice a Clue, target player puts the top three cards of his or her graveyard into his or her graveyard. - Ability ability = new SacrificeAllTriggeredAbility(new PutTopCardOfLibraryIntoGraveTargetEffect(3), filter, TargetController.YOU, false); + Ability ability = new FleetingMemoriesTriggeredAbility(); ability.addTarget(new TargetPlayer()); this.addAbility(ability); } @@ -75,3 +78,36 @@ public class FleetingMemories extends CardImpl { return new FleetingMemories(this); } } + +class FleetingMemoriesTriggeredAbility extends TriggeredAbilityImpl { + + public FleetingMemoriesTriggeredAbility() { + super(Zone.BATTLEFIELD, new PutTopCardOfLibraryIntoGraveTargetEffect(3)); + setLeavesTheBattlefieldTrigger(true); + } + + public FleetingMemoriesTriggeredAbility(final FleetingMemoriesTriggeredAbility ability) { + super(ability); + } + + @Override + public FleetingMemoriesTriggeredAbility copy() { + return new FleetingMemoriesTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.SACRIFICED_PERMANENT; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return event.getPlayerId().equals(this.getControllerId()) + && game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD).getSubtype().contains("Clue"); + } + + @Override + public String getRule() { + return "Whenever you sacrifice a Clue, " + super.getRule(); + } +} \ No newline at end of file From 8ea813e7cdb02d09db938777ad2eb35688f99289 Mon Sep 17 00:00:00 2001 From: drmDev Date: Wed, 30 Mar 2016 04:46:33 -0400 Subject: [PATCH 11/13] fix for Prized Amalgam triggering on opponent recurring creatures. Tests added - bug remains for Gravecrawler interaction --- .../shadowsoverinnistrad/PrizedAmalgam.java | 9 +- .../cards/single/soi/PrizedAmalgamTest.java | 82 +++++++++++++++++++ 2 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/soi/PrizedAmalgamTest.java diff --git a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/PrizedAmalgam.java b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/PrizedAmalgam.java index a8cdc96a90..d747414937 100644 --- a/Mage.Sets/src/mage/sets/shadowsoverinnistrad/PrizedAmalgam.java +++ b/Mage.Sets/src/mage/sets/shadowsoverinnistrad/PrizedAmalgam.java @@ -37,9 +37,11 @@ import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffec import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Rarity; +import mage.constants.TargetController; import mage.constants.Zone; import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerPredicate; import mage.game.Game; import mage.game.events.EntersTheBattlefieldEvent; import mage.game.events.GameEvent; @@ -49,6 +51,11 @@ import mage.game.events.GameEvent; * @author LevelX2 */ public class PrizedAmalgam extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a creature"); + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + } public PrizedAmalgam(UUID ownerId) { super(ownerId, 249, "Prized Amalgam", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{U}{B}"); @@ -59,7 +66,7 @@ public class PrizedAmalgam extends CardImpl { // Whenever a creature enters the battlefield, if it entered from your graveyard or you cast it from your graveyard, return Prized Amalgam from your graveyard to the battlefield tapped at the beginning of the next end step. this.addAbility(new PrizedAmalgamTriggerdAbility(new CreateDelayedTriggeredAbilityEffect( - new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnSourceFromGraveyardToBattlefieldEffect(true))), new FilterCreaturePermanent())); + new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ReturnSourceFromGraveyardToBattlefieldEffect(true))), filter)); } public PrizedAmalgam(final PrizedAmalgam card) { diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/PrizedAmalgamTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/PrizedAmalgamTest.java new file mode 100644 index 0000000000..e2d02ad552 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/PrizedAmalgamTest.java @@ -0,0 +1,82 @@ +package org.mage.test.cards.single.soi; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + *1UB +* Creature - Zombie +* Whenever a creature enters the battlefield, if it entered from your graveyard or you cast it from your graveyard, +* return Prized Amalgam from your graveyard to the battlefield tapped at the beginning of the next end step. + * @author escplan9 (Derek Monturo - dmontur1 at gmail dot com) + */ +public class PrizedAmalgamTest extends CardTestPlayerBase { + + /** + * Reanimated creature recurs Prized Amalgam + */ + @Test + public void testReanimation() { + + addCard(Zone.HAND, playerA, "Reanimate", 1); // {B} Put target creature card from a graveyard onto the battlefield under your control. You lose life equal to its converted mana cost. + addCard(Zone.GRAVEYARD, playerA, "Bronze Sable", 1); // (2) 2/1 + addCard(Zone.GRAVEYARD, playerA, "Prized Amalgam", 1); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate"); + addTarget(playerA, "Bronze Sable"); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertLife(playerA, 18); // loss of 2 from reanimate + assertGraveyardCount(playerA, "Reanimate", 1); + assertPermanentCount(playerA, "Bronze Sable", 1); + assertPermanentCount(playerA, "Prized Amalgam", 1); + assertTapped("Prized Amalgam", true); + } + + /** + * Reported bug - Gravecrawler cast from grave does not trigger Prized Amalgam. + */ + @Test + public void testGravecrawlerCastFromGrave() { + + addCard(Zone.GRAVEYARD, playerA, "Gravecrawler", 1); + addCard(Zone.GRAVEYARD, playerA, "Prized Amalgam", 1); + addCard(Zone.BATTLEFIELD, playerA, "Gnawing Zombie", 1); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Gravecrawler"); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, "Gravecrawler", 1); + assertPermanentCount(playerA, "Prized Amalgam", 1); + assertTapped("Prized Amalgam", true); + } + + /** + * Reported bug - creature returned from opponent's graveyard to battlefield by Ojutai's Command incorrectly triggers Prized Amalgam + */ + @Test + public void testOpponentReturnsCreatureFromGrave() { + + addCard(Zone.HAND, playerA, "Reanimate", 1); + addCard(Zone.GRAVEYARD, playerA, "Hill Giant", 1); // {3}{R} 3/3 + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); + addCard(Zone.GRAVEYARD, playerB, "Prized Amalgam", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate"); + addTarget(playerA, "Hill Giant"); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertLife(playerA, 16); // lose 4 life from reanimate 4 CMC + assertPermanentCount(playerA, "Hill Giant", 1); + assertPermanentCount(playerB, "Prized Amalgam", 0); // should not recur + assertGraveyardCount(playerB, "Prized Amalgam", 1); // stays in grave + } +} From 6cfd69effb66be19f2799ba3b8aadb0b5f0fddf8 Mon Sep 17 00:00:00 2001 From: drmDev Date: Wed, 30 Mar 2016 05:21:10 -0400 Subject: [PATCH 12/13] Silkwrap test added for reported bug on Hangarback not getting exiled --- .../test/cards/triggers/SilkwrapTest.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/triggers/SilkwrapTest.java diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/SilkwrapTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/SilkwrapTest.java new file mode 100644 index 0000000000..285c6323b5 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/SilkwrapTest.java @@ -0,0 +1,39 @@ +package org.mage.test.cards.triggers; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * When Silkwrap enters the battlefield, exile target creature with converted mana cost 3 or less an opponent controls until Silkwrap leaves the battlefield. + * @author escplan9 (Derek Monturo - dmontur1 at gmail dot com) + */ +public class SilkwrapTest extends CardTestPlayerBase { + + /* + * Reported bug - Silkwrap does not exile Hangarback. + Cards with X CMC are considered 0 CMC on the battlefield. + */ + @Test + public void testHangarback() { + + addCard(Zone.HAND, playerA, "Hangarback Walker", 1); + addCard(Zone.BATTLEFIELD, playerA, "Wastes", 8); + addCard(Zone.HAND, playerB, "Silkwrap", 1); + addCard(Zone.BATTLEFIELD, playerB, "Plains", 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Hangarback Walker"); + setChoice(playerA, "X=4"); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Silkwrap"); + addTarget(playerB, "Hangarback Walker"); + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerB, "Silkwrap", 1); + assertPermanentCount(playerA, "Hangarback Walker", 0); + assertExileCount("Hangarback Walker", 1); + } +} From 5ac82e657f52d8626cf46824f6a49cfc7e27ea69 Mon Sep 17 00:00:00 2001 From: drmDev Date: Wed, 30 Mar 2016 11:55:42 -0400 Subject: [PATCH 13/13] Additional Prized amalgam test --- .../cards/single/soi/PrizedAmalgamTest.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/PrizedAmalgamTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/PrizedAmalgamTest.java index e2d02ad552..293af53834 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/PrizedAmalgamTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/PrizedAmalgamTest.java @@ -79,4 +79,25 @@ public class PrizedAmalgamTest extends CardTestPlayerBase { assertPermanentCount(playerB, "Prized Amalgam", 0); // should not recur assertGraveyardCount(playerB, "Prized Amalgam", 1); // stays in grave } + + /* + * Test opponent returning a card from your graveyard to battlefield. + */ + @Test + public void testOpponentReturnsCreatureFromYourGrave() { + + addCard(Zone.HAND, playerA, "Necromantic Summons", 1); // Put target creature card from a graveyard onto the battlefield under your control. + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5); + addCard(Zone.GRAVEYARD, playerB, "Merfolk Looter", 1); // {U} 1/1 + addCard(Zone.GRAVEYARD, playerB, "Prized Amalgam", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Necromantic Summons"); + addTarget(playerA, "Merfolk Looter"); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerA, "Merfolk Looter", 1); + assertPermanentCount(playerB, "Prized Amalgam", 0); // should not recur + assertGraveyardCount(playerB, "Prized Amalgam", 1); // stays in grave + } }