diff --git a/Mage.Sets/src/mage/cards/s/ScreamingNemesis.java b/Mage.Sets/src/mage/cards/s/ScreamingNemesis.java new file mode 100644 index 00000000000..dcc1e1e2f98 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ScreamingNemesis.java @@ -0,0 +1,101 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DealtDamageToSourceTriggeredAbility; +import mage.abilities.dynamicvalue.common.SavedDamageValue; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.CantGainLifeRestOfGameTargetEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.filter.common.FilterAnyTarget; +import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetAnyTarget; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * @author Susucr + */ +public final class ScreamingNemesis extends CardImpl { + + private static final FilterAnyTarget filter = new FilterAnyTarget("any other target"); + + static { + filter.getPermanentFilter().add(AnotherPredicate.instance); + } + + public ScreamingNemesis(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); + + this.subtype.add(SubType.SPIRIT); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // Whenever Screaming Nemesis is dealt damage, it deals that much damage to any other target. If a player is dealt damage this way, they can't gain life for the rest of the game. + Ability ability = new DealtDamageToSourceTriggeredAbility(new ScreamingNemesisEffect(), false); + ability.addTarget(new TargetAnyTarget(filter)); + this.addAbility(ability); + } + + private ScreamingNemesis(final ScreamingNemesis card) { + super(card); + } + + @Override + public ScreamingNemesis copy() { + return new ScreamingNemesis(this); + } +} + +class ScreamingNemesisEffect extends OneShotEffect { + + ScreamingNemesisEffect() { + super(Outcome.Damage); + staticText = "it deals that much damage to any other target. " + + "If a player is dealt damage this way, they can't gain life for the rest of the game"; + } + + private ScreamingNemesisEffect(final ScreamingNemesisEffect effect) { + super(effect); + } + + @Override + public ScreamingNemesisEffect copy() { + return new ScreamingNemesisEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + int amount = SavedDamageValue.MUCH.calculate(game, source, this); + UUID targetId = getTargetPointer().getFirst(game, source); + if (amount <= 0 || targetId == null) { + return false; + } + Permanent permanent = game.getPermanent(targetId); + Player player = game.getPlayer(targetId); + if (permanent != null) { + permanent.damage(amount, source.getSourceId(), source, game, false, true); + return true; + } else if (player != null) { + int damageDone = player.damage(amount, source.getSourceId(), source, game, false, true); + if (damageDone > 0) { + // If a player is dealt damage this way, they can't gain life for the rest of the game. + game.addEffect(new CantGainLifeRestOfGameTargetEffect().setTargetPointer(new FixedTarget(player.getId())), source); + } + return true; + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/StigmaLasher.java b/Mage.Sets/src/mage/cards/s/StigmaLasher.java index 847b752d5c6..d72697d7da9 100644 --- a/Mage.Sets/src/mage/cards/s/StigmaLasher.java +++ b/Mage.Sets/src/mage/cards/s/StigmaLasher.java @@ -1,34 +1,27 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.DealsDamageToAPlayerTriggeredAbility; -import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.continuous.CantGainLifeRestOfGameTargetEffect; import mage.abilities.keyword.WitherAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Duration; -import mage.constants.Layer; -import mage.constants.Outcome; -import mage.constants.SubLayer; -import mage.game.Game; -import mage.players.Player; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class StigmaLasher extends CardImpl { - + public StigmaLasher(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}{R}"); this.subtype.add(SubType.ELEMENTAL); this.subtype.add(SubType.SHAMAN); - + this.power = new MageInt(2); this.toughness = new MageInt(2); @@ -37,42 +30,19 @@ public final class StigmaLasher extends CardImpl { this.addAbility(WitherAbility.getInstance()); // Whenever Stigma Lasher deals damage to a player, that player can't gain life for the rest of the game. - this.addAbility(new DealsDamageToAPlayerTriggeredAbility(new StigmaLasherEffect(), false, true)); - + this.addAbility(new DealsDamageToAPlayerTriggeredAbility( + new CantGainLifeRestOfGameTargetEffect(), + false, true + )); + } - + private StigmaLasher(final StigmaLasher card) { super(card); } - + @Override public StigmaLasher copy() { return new StigmaLasher(this); } -} - -class StigmaLasherEffect extends ContinuousEffectImpl { - - public StigmaLasherEffect() { - super(Duration.EndOfGame, Layer.PlayerEffects, SubLayer.NA, Outcome.Neutral); - staticText = "that player can't gain life for the rest of the game"; - } - - private StigmaLasherEffect(final StigmaLasherEffect effect) { - super(effect); - } - - @Override - public StigmaLasherEffect copy() { - return new StigmaLasherEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(this.getTargetPointer().getFirst(game, source)); - if (player != null) { - player.setCanGainLife(false); - } - return true; - } } \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/DuskmournHouseOfHorror.java b/Mage.Sets/src/mage/sets/DuskmournHouseOfHorror.java index 4f222b037f2..c036e1b743a 100644 --- a/Mage.Sets/src/mage/sets/DuskmournHouseOfHorror.java +++ b/Mage.Sets/src/mage/sets/DuskmournHouseOfHorror.java @@ -30,6 +30,7 @@ public final class DuskmournHouseOfHorror extends ExpansionSet { cards.add(new SetCardInfo("Leyline of Hope", 18, Rarity.RARE, mage.cards.l.LeylineOfHope.class)); cards.add(new SetCardInfo("Mountain", 275, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Plains", 272, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Screaming Nemesis", 157, Rarity.MYTHIC, mage.cards.s.ScreamingNemesis.class)); cards.add(new SetCardInfo("Swamp", 274, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("The Wandering Rescuer", 41, Rarity.MYTHIC, mage.cards.t.TheWanderingRescuer.class)); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/acr/ScreamingNemesisTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/acr/ScreamingNemesisTest.java new file mode 100644 index 00000000000..4a62e0469ba --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/acr/ScreamingNemesisTest.java @@ -0,0 +1,73 @@ +package org.mage.test.cards.single.acr; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class ScreamingNemesisTest extends CardTestPlayerBase { + + /** + * {@link mage.cards.s.ScreamingNemesis Screaming Nemesis} {2}{R} + * Creature — Spirit + * Haste + * Whenever Screaming Nemesis is dealt damage, it deals that much damage to any other target. If a player is dealt damage this way, they can’t gain life for the rest of the game. + * 3/3 + */ + private static final String nemesis = "Screaming Nemesis"; + + @Test + public void test_Trigger_PreventGainLife() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerA, nemesis); + addCard(Zone.HAND, playerA, "Shock"); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); + addCard(Zone.BATTLEFIELD, playerB, "Plains", 4); + addCard(Zone.HAND, playerB, "Angel's Mercy"); // You gain 7 life. + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shock", nemesis); + addTarget(playerA, playerB); // target for trigger + + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Angel's Mercy"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerB, 20 - 2); + assertGraveyardCount(playerB, "Angel's Mercy", 1); + assertDamageReceived(playerA, nemesis, 2); + } + + @Test + public void test_Trigger_Permanent_NoPreventGainLife() { + setStrictChooseMode(true); + + addCard(Zone.BATTLEFIELD, playerA, nemesis); + addCard(Zone.HAND, playerA, "Shock"); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); + addCard(Zone.BATTLEFIELD, playerB, "Centaur Courser"); + addCard(Zone.BATTLEFIELD, playerB, "Plains", 4); + addCard(Zone.HAND, playerB, "Angel's Mercy"); // You gain 7 life. + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shock", nemesis); + addTarget(playerA, "Centaur Courser"); // target for trigger + + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Angel's Mercy"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerB, 20 + 7); + assertGraveyardCount(playerB, "Angel's Mercy", 1); + assertDamageReceived(playerA, nemesis, 2); + assertDamageReceived(playerB, "Centaur Courser", 2); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/CantGainLifeRestOfGameTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/CantGainLifeRestOfGameTargetEffect.java new file mode 100644 index 00000000000..d2e8ef09b74 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/CantGainLifeRestOfGameTargetEffect.java @@ -0,0 +1,39 @@ +package mage.abilities.effects.common.continuous; + +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.game.Game; +import mage.players.Player; + +/** + * @author Susucr + */ +public class CantGainLifeRestOfGameTargetEffect extends ContinuousEffectImpl { + + public CantGainLifeRestOfGameTargetEffect() { + super(Duration.EndOfGame, Layer.PlayerEffects, SubLayer.NA, Outcome.Neutral); + staticText = "that player can't gain life for the rest of the game"; + } + + private CantGainLifeRestOfGameTargetEffect(final CantGainLifeRestOfGameTargetEffect effect) { + super(effect); + } + + @Override + public CantGainLifeRestOfGameTargetEffect copy() { + return new CantGainLifeRestOfGameTargetEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(this.getTargetPointer().getFirst(game, source)); + if (player != null) { + player.setCanGainLife(false); + } + return true; + } +} diff --git a/Mage/src/main/java/mage/target/common/TargetAnyTarget.java b/Mage/src/main/java/mage/target/common/TargetAnyTarget.java index ce7117c90bb..87de24a32ab 100644 --- a/Mage/src/main/java/mage/target/common/TargetAnyTarget.java +++ b/Mage/src/main/java/mage/target/common/TargetAnyTarget.java @@ -13,6 +13,10 @@ public class TargetAnyTarget extends TargetPermanentOrPlayer { this(1); } + public TargetAnyTarget(FilterAnyTarget filter) { + this(1, 1, filter); + } + public TargetAnyTarget(int numTargets) { this(numTargets, numTargets); }