diff --git a/Mage.Sets/src/mage/cards/b/BrutalCathar.java b/Mage.Sets/src/mage/cards/b/BrutalCathar.java index 9a811563bc6..842eafb3735 100644 --- a/Mage.Sets/src/mage/cards/b/BrutalCathar.java +++ b/Mage.Sets/src/mage/cards/b/BrutalCathar.java @@ -1,7 +1,8 @@ package mage.cards.b; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; +import mage.abilities.common.TransformsOrEntersTriggeredAbility; import mage.abilities.common.delayed.OnLeaveReturnExiledToBattlefieldAbility; import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; import mage.abilities.effects.common.ExileUntilSourceLeavesEffect; @@ -10,10 +11,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; import mage.target.common.TargetOpponentsCreaturePermanent; import java.util.UUID; @@ -34,7 +31,12 @@ public final class BrutalCathar extends CardImpl { this.secondSideCardClazz = mage.cards.m.MoonrageBrute.class; // When this creature enters the battlefield or transforms into Brutal Cathar, exile target creature an opponent controls until this creature leaves the battlefield. - this.addAbility(new BrutalCatharTriggeredAbility()); + Ability ability = new TransformsOrEntersTriggeredAbility( + new ExileUntilSourceLeavesEffect("creature an opponent controls"), false + ); + ability.addTarget(new TargetOpponentsCreaturePermanent()); + ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility())); + this.addAbility(ability); // Daybound this.addAbility(new DayboundAbility()); @@ -49,48 +51,3 @@ public final class BrutalCathar extends CardImpl { return new BrutalCathar(this); } } - -class BrutalCatharTriggeredAbility extends TriggeredAbilityImpl { - - public BrutalCatharTriggeredAbility() { - super(Zone.BATTLEFIELD, new ExileUntilSourceLeavesEffect("creature an opponent controls"), false); - this.addTarget(new TargetOpponentsCreaturePermanent()); - this.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility())); - } - - public BrutalCatharTriggeredAbility(final BrutalCatharTriggeredAbility ability) { - super(ability); - } - - @Override - public BrutalCatharTriggeredAbility copy() { - return new BrutalCatharTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.TRANSFORMED - || event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (!event.getTargetId().equals(this.getSourceId())) { - return false; - } - switch (event.getType()) { - case TRANSFORMED: - Permanent permanent = getSourcePermanentIfItStillExists(game); - return permanent != null && !permanent.isTransformed(); - case ENTERS_THE_BATTLEFIELD: - return true; - } - return false; - } - - @Override - public String getRule() { - return "When this creature enters the battlefield or transforms into {this}, " + - "exile target creature an opponent controls until this creature leaves the battlefield."; - } -} diff --git a/Mage.Sets/src/mage/cards/h/HowlpackPiper.java b/Mage.Sets/src/mage/cards/h/HowlpackPiper.java new file mode 100644 index 00000000000..e70c753569c --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HowlpackPiper.java @@ -0,0 +1,105 @@ +package mage.cards.h; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.ActivateAsSorceryActivatedAbility; +import mage.abilities.common.CantBeCounteredSourceAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.DayboundAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.common.TargetCardInHand; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class HowlpackPiper extends CardImpl { + + public HowlpackPiper(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WEREWOLF); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + this.secondSideCardClazz = mage.cards.w.WildsongHowler.class; + + // This spell can't be countered. + this.addAbility(new CantBeCounteredSourceAbility()); + + // {1}{G}, {T}: You may put a creature card from your hand onto the battlefield. If it's a Wolf or Werewolf, untap Howlpack Piper. Activate only as a sorcery. + Ability ability = new ActivateAsSorceryActivatedAbility( + new HowlpackPiperEffect(), new ManaCostsImpl<>("{1}{G}") + ); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + + // Daybound + this.addAbility(new DayboundAbility()); + } + + private HowlpackPiper(final HowlpackPiper card) { + super(card); + } + + @Override + public HowlpackPiper copy() { + return new HowlpackPiper(this); + } +} + +class HowlpackPiperEffect extends OneShotEffect { + + HowlpackPiperEffect() { + super(Outcome.PutCreatureInPlay); + staticText = "you may put a creature card from your hand onto the battlefield. " + + "If it's a Wolf or Werewolf, untap {this}"; + } + + private HowlpackPiperEffect(final HowlpackPiperEffect effect) { + super(effect); + } + + @Override + public HowlpackPiperEffect copy() { + return new HowlpackPiperEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null || player.getHand().count(StaticFilters.FILTER_CARD_CREATURE, game) < 1) { + return false; + } + TargetCard target = new TargetCardInHand(0, 1, StaticFilters.FILTER_CARD_CREATURE); + player.choose(outcome, player.getHand(), target, game); + Card card = game.getCard(target.getFirstTarget()); + if (card == null) { + return false; + } + player.moveCards(card, Zone.BATTLEFIELD, source, game); + Permanent permanent = game.getPermanent(card.getId()); + Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game); + if (permanent == null || sourcePermanent == null) { + return true; + } + if (permanent.hasSubtype(SubType.WOLF, game) || permanent.hasSubtype(SubType.WEREWOLF, game)) { + sourcePermanent.untap(game); + } + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/h/HuntmasterOfTheFells.java b/Mage.Sets/src/mage/cards/h/HuntmasterOfTheFells.java index b2ab1b638ea..e5f0763e5a2 100644 --- a/Mage.Sets/src/mage/cards/h/HuntmasterOfTheFells.java +++ b/Mage.Sets/src/mage/cards/h/HuntmasterOfTheFells.java @@ -1,7 +1,8 @@ package mage.cards.h; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; +import mage.abilities.common.TransformsOrEntersTriggeredAbility; import mage.abilities.common.WerewolfFrontTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.GainLifeEffect; @@ -10,10 +11,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; import mage.game.permanent.token.WolfToken; import java.util.UUID; @@ -34,7 +31,11 @@ public final class HuntmasterOfTheFells extends CardImpl { this.toughness = new MageInt(2); // Whenever this creature enters the battlefield or transforms into Huntmaster of the Fells, create a 2/2 green Wolf creature token and you gain 2 life. - this.addAbility(new HuntmasterOfTheFellsAbility()); + Ability ability = new TransformsOrEntersTriggeredAbility( + new CreateTokenEffect(new WolfToken()), false, true + ); + ability.addEffect(new GainLifeEffect(2).concatBy("and")); + this.addAbility(ability); // At the beginning of each upkeep, if no spells were cast last turn, transform Huntmaster of the Fells. this.addAbility(new TransformAbility()); @@ -50,44 +51,3 @@ public final class HuntmasterOfTheFells extends CardImpl { return new HuntmasterOfTheFells(this); } } - -class HuntmasterOfTheFellsAbility extends TriggeredAbilityImpl { - - public HuntmasterOfTheFellsAbility() { - super(Zone.BATTLEFIELD, new CreateTokenEffect(new WolfToken()), false); - this.addEffect(new GainLifeEffect(2)); - } - - public HuntmasterOfTheFellsAbility(final HuntmasterOfTheFellsAbility ability) { - super(ability); - } - - @Override - public HuntmasterOfTheFellsAbility copy() { - return new HuntmasterOfTheFellsAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.TRANSFORMED || event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.TRANSFORMED && event.getTargetId().equals(this.getSourceId())) { - Permanent permanent = game.getPermanent(sourceId); - if (permanent != null && !permanent.isTransformed()) { - return true; - } - } - if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD && event.getTargetId().equals(this.getSourceId())) { - return true; - } - return false; - } - - @Override - public String getRule() { - return "Whenever this creature enters the battlefield or transforms into {this}, create a 2/2 green Wolf creature token and you gain 2 life."; - } -} diff --git a/Mage.Sets/src/mage/cards/u/UlrichOfTheKrallenhorde.java b/Mage.Sets/src/mage/cards/u/UlrichOfTheKrallenhorde.java index 5d575350b44..27611324325 100644 --- a/Mage.Sets/src/mage/cards/u/UlrichOfTheKrallenhorde.java +++ b/Mage.Sets/src/mage/cards/u/UlrichOfTheKrallenhorde.java @@ -1,16 +1,16 @@ package mage.cards.u; import mage.MageInt; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.Ability; +import mage.abilities.common.TransformsOrEntersTriggeredAbility; import mage.abilities.common.WerewolfFrontTriggeredAbility; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.abilities.keyword.TransformAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -28,11 +28,14 @@ public final class UlrichOfTheKrallenhorde extends CardImpl { this.power = new MageInt(4); this.toughness = new MageInt(4); - this.secondSideCardClazz = UlrichUncontestedAlpha.class; // Whenever this creature enters the battlefield or transforms into Ulrich of the Krallenhorde, target creature gets +4/+4 until end of turn. - this.addAbility(new UlrichOfTheKrallenhordeAbility()); + Ability ability = new TransformsOrEntersTriggeredAbility( + new BoostTargetEffect(4, 4), false, true + ); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); // At the beginning of each upkeep, if no spells were cast last turn, transform Ulrich of the Krallenhorde. this.addAbility(new TransformAbility()); @@ -48,44 +51,3 @@ public final class UlrichOfTheKrallenhorde extends CardImpl { return new UlrichOfTheKrallenhorde(this); } } - -class UlrichOfTheKrallenhordeAbility extends TriggeredAbilityImpl { - - public UlrichOfTheKrallenhordeAbility() { - super(Zone.BATTLEFIELD, new BoostTargetEffect(4, 4, Duration.EndOfTurn), false); - this.addTarget(new TargetCreaturePermanent()); - } - - public UlrichOfTheKrallenhordeAbility(final UlrichOfTheKrallenhordeAbility ability) { - super(ability); - } - - @Override - public UlrichOfTheKrallenhordeAbility copy() { - return new UlrichOfTheKrallenhordeAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.TRANSFORMED || event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.TRANSFORMED && event.getTargetId().equals(this.getSourceId())) { - Permanent permanent = game.getPermanent(sourceId); - if (permanent != null && !permanent.isTransformed()) { - return true; - } - } - if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD && event.getTargetId().equals(this.getSourceId())) { - return true; - } - return false; - } - - @Override - public String getRule() { - return "Whenever this creature enters the battlefield or transforms into Ulrich of the Krallenhorde, target creature gets +4/+4 until end of turn."; - } -} diff --git a/Mage.Sets/src/mage/cards/w/WildsongHowler.java b/Mage.Sets/src/mage/cards/w/WildsongHowler.java new file mode 100644 index 00000000000..39ef19a7e50 --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WildsongHowler.java @@ -0,0 +1,50 @@ +package mage.cards.w; + +import mage.MageInt; +import mage.abilities.common.TransformsOrEntersTriggeredAbility; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.abilities.keyword.NightboundAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.StaticFilters; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class WildsongHowler extends CardImpl { + + public WildsongHowler(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, ""); + + this.subtype.add(SubType.WEREWOLF); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + this.color.setGreen(true); + this.nightCard = true; + + // Whenever this creature enters the battlefield or transforms into Wildsong Howler, look at the top six cards of your library. You may reveal a creature card from among them and put it into your hand. Put the rest on the bottom of your library in a random order. + this.addAbility(new TransformsOrEntersTriggeredAbility(new LookLibraryAndPickControllerEffect( + StaticValue.get(5), false, StaticValue.get(1), + StaticFilters.FILTER_CARD_CREATURE, Zone.LIBRARY, false, + true, false, Zone.HAND, true, false, false + ).setText("look at the top six cards of your library. You may reveal a creature card from among them and put it into your hand. Put the rest on the bottom of your library in a random order"), false)); + + // Nightbound + this.addAbility(new NightboundAbility()); + } + + private WildsongHowler(final WildsongHowler card) { + super(card); + } + + @Override + public WildsongHowler copy() { + return new WildsongHowler(this); + } +} diff --git a/Mage.Sets/src/mage/sets/InnistradCrimsonVow.java b/Mage.Sets/src/mage/sets/InnistradCrimsonVow.java index c77f206c2b9..265b52234f0 100644 --- a/Mage.Sets/src/mage/sets/InnistradCrimsonVow.java +++ b/Mage.Sets/src/mage/sets/InnistradCrimsonVow.java @@ -171,6 +171,7 @@ public final class InnistradCrimsonVow extends ExpansionSet { cards.add(new SetCardInfo("Hookhand Mariner", 203, Rarity.COMMON, mage.cards.h.HookhandMariner.class)); cards.add(new SetCardInfo("Hopeful Initiate", 20, Rarity.RARE, mage.cards.h.HopefulInitiate.class)); cards.add(new SetCardInfo("Howling Moon", 204, Rarity.RARE, mage.cards.h.HowlingMoon.class)); + cards.add(new SetCardInfo("Howlpack Piper", 205, Rarity.RARE, mage.cards.h.HowlpackPiper.class)); cards.add(new SetCardInfo("Hullbreaker Horror", 63, Rarity.RARE, mage.cards.h.HullbreakerHorror.class)); cards.add(new SetCardInfo("Hungry Ridgewolf", 161, Rarity.COMMON, mage.cards.h.HungryRidgewolf.class)); cards.add(new SetCardInfo("Infestation Expert", 206, Rarity.UNCOMMON, mage.cards.i.InfestationExpert.class)); @@ -319,6 +320,7 @@ public final class InnistradCrimsonVow extends ExpansionSet { cards.add(new SetCardInfo("Wedding Security", 138, Rarity.UNCOMMON, mage.cards.w.WeddingSecurity.class)); cards.add(new SetCardInfo("Welcoming Vampire", 46, Rarity.RARE, mage.cards.w.WelcomingVampire.class)); cards.add(new SetCardInfo("Whispering Wizard", 88, Rarity.UNCOMMON, mage.cards.w.WhisperingWizard.class)); + cards.add(new SetCardInfo("Wildsong Howler", 205, Rarity.RARE, mage.cards.w.WildsongHowler.class)); cards.add(new SetCardInfo("Winged Portent", 89, Rarity.RARE, mage.cards.w.WingedPortent.class)); cards.add(new SetCardInfo("Witch's Web", 227, Rarity.COMMON, mage.cards.w.WitchsWeb.class)); cards.add(new SetCardInfo("Witness the Future", 90, Rarity.UNCOMMON, mage.cards.w.WitnessTheFuture.class)); diff --git a/Mage/src/main/java/mage/abilities/common/TransformsOrEntersTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/TransformsOrEntersTriggeredAbility.java new file mode 100644 index 00000000000..bd5cda7396e --- /dev/null +++ b/Mage/src/main/java/mage/abilities/common/TransformsOrEntersTriggeredAbility.java @@ -0,0 +1,61 @@ +package mage.abilities.common; + +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; + +/** + * @author TheElk801 + */ +public class TransformsOrEntersTriggeredAbility extends TriggeredAbilityImpl { + + private final boolean whenever; + + public TransformsOrEntersTriggeredAbility(Effect effect, boolean optional) { + this(effect, optional, false); + } + + public TransformsOrEntersTriggeredAbility(Effect effect, boolean optional, boolean whenever) { + super(Zone.BATTLEFIELD, effect, optional); + this.whenever = whenever; + } + + private TransformsOrEntersTriggeredAbility(final TransformsOrEntersTriggeredAbility ability) { + super(ability); + this.whenever = ability.whenever; + } + + @Override + public TransformsOrEntersTriggeredAbility copy() { + return new TransformsOrEntersTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.TRANSFORMED + || event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (!event.getTargetId().equals(this.getSourceId())) { + return false; + } + switch (event.getType()) { + case TRANSFORMED: + Permanent permanent = getSourcePermanentIfItStillExists(game); + return permanent != null && !permanent.isTransformed(); + case ENTERS_THE_BATTLEFIELD: + return true; + } + return false; + } + + @Override + public String getTriggerPhrase() { + return "When" + (whenever ? "ever" : "") + " this creature enters the battlefield or transforms into {this}, "; + } +}