diff --git a/Mage.Sets/src/mage/cards/f/FaerieFencing.java b/Mage.Sets/src/mage/cards/f/FaerieFencing.java new file mode 100644 index 00000000000..3d3844076b1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FaerieFencing.java @@ -0,0 +1,111 @@ +package mage.cards.f; + +import java.util.HashMap; +import java.util.UUID; + +import mage.MageObject; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.WatcherScope; +import mage.filter.FilterPermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.stack.Spell; +import mage.target.common.TargetCreaturePermanent; +import mage.watchers.Watcher; + +/** + * + * @author Xanderhall + */ +public final class FaerieFencing extends CardImpl { + + public FaerieFencing(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{B}"); + + // Target creature gets -X/-X until end of turn. It gets an additional -3/-3 if you controlled a Faerie as you cast this spell. + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addEffect(new FaerieFencingEffect()); + this.getSpellAbility().addWatcher(new ControlledFaerieAsSpellCastWatcher()); + } + + private FaerieFencing(final FaerieFencing card) { + super(card); + } + + @Override + public FaerieFencing copy() { + return new FaerieFencing(this); + } +} + +class FaerieFencingEffect extends OneShotEffect { + + FaerieFencingEffect() { + super(Outcome.UnboostCreature); + this.staticText = "target creature gets -X/-X until end of turn. It gets an additional -3/-3 if you controlled a Faerie as you cast this spell."; + } + + private FaerieFencingEffect(final FaerieFencingEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + ControlledFaerieAsSpellCastWatcher watcher = game.getState().getWatcher(ControlledFaerieAsSpellCastWatcher.class); + MageObject mo = source.getSourceObject(game); + int reduction = source.getManaCostsToPay().getX(); + + if (watcher != null && mo != null && watcher.getCount(new MageObjectReference(mo, game)) > 0) { + reduction += 3; + } + game.addEffect(new BoostTargetEffect(-reduction, -reduction, Duration.EndOfTurn), source); + return true; + } + + @Override + public FaerieFencingEffect copy() { + return new FaerieFencingEffect(this); + } + +} + +class ControlledFaerieAsSpellCastWatcher extends Watcher { + + private final FilterPermanent filter = new FilterPermanent(SubType.FAERIE, ""); + + ControlledFaerieAsSpellCastWatcher() { + super(WatcherScope.GAME); + } + + private final HashMap permanentsWhenCast = new HashMap<>(); + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.SPELL_CAST) { + Spell spell = game.getSpell(event.getTargetId()); + if (spell != null) { + MageObjectReference mor = new MageObjectReference(spell, game); + permanentsWhenCast.put(mor, game.getBattlefield().countAll(filter, spell.getControllerId(), game)); + } + } + } + + @Override + public void reset() { + super.reset(); + permanentsWhenCast.clear(); + } + + public int getCount(MageObjectReference mor) { + return permanentsWhenCast.getOrDefault(mor, 0); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/WildsOfEldraine.java b/Mage.Sets/src/mage/sets/WildsOfEldraine.java index bee0cc7135e..353cc4106dc 100644 --- a/Mage.Sets/src/mage/sets/WildsOfEldraine.java +++ b/Mage.Sets/src/mage/sets/WildsOfEldraine.java @@ -48,6 +48,7 @@ public final class WildsOfEldraine extends ExpansionSet { cards.add(new SetCardInfo("Evolving Wilds", 256, Rarity.COMMON, mage.cards.e.EvolvingWilds.class)); cards.add(new SetCardInfo("Expel the Interlopers", 13, Rarity.RARE, mage.cards.e.ExpelTheInterlopers.class)); cards.add(new SetCardInfo("Faerie Dreamthief", 89, Rarity.UNCOMMON, mage.cards.f.FaerieDreamthief.class)); + cards.add(new SetCardInfo("Faerie Fencing", 90, Rarity.UNCOMMON, mage.cards.f.FaerieFencing.class)); cards.add(new SetCardInfo("Farsight Ritual", 49, Rarity.RARE, mage.cards.f.FarsightRitual.class)); cards.add(new SetCardInfo("Faunsbane Troll", 203, Rarity.RARE, mage.cards.f.FaunsbaneTroll.class)); cards.add(new SetCardInfo("Flick a Coin", 128, Rarity.COMMON, mage.cards.f.FlickACoin.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/woe/FaerieFencingTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/woe/FaerieFencingTest.java new file mode 100644 index 00000000000..8a72f86fd3d --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/woe/FaerieFencingTest.java @@ -0,0 +1,39 @@ +package org.mage.test.cards.single.woe; + +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +import mage.constants.PhaseStep; +import mage.constants.Zone; + +public class FaerieFencingTest extends CardTestPlayerBase { + + private static String SPELL = "Faerie Fencing"; + private static String FAERIE = "Faerie Miscreant"; + private static String LION = "Silvercoat Lion"; + + @Test + public void testEffect() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2); + addCard(Zone.BATTLEFIELD, playerA, FAERIE, 1); + addCard(Zone.HAND, playerA, SPELL, 1); + + addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1); + addCard(Zone.BATTLEFIELD, playerB, LION, 1); + addCard(Zone.HAND, playerB, "Lightning Bolt", 1); + + // Player A casts Faerie Fencing for 1, controls a Faerie so lion should get -4/-4 + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, SPELL, LION); + setChoice(playerA, "X=1"); + + // Player B kills Faerie in response + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", FAERIE, SPELL); + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + setStrictChooseMode(true); + execute(); + + // Lion should still have died + assertGraveyardCount(playerB, LION, 1); + } +} \ No newline at end of file