From a545b29a7cf7edb194c69bd18cb20ecf552cb5a3 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Sun, 14 Apr 2019 19:32:35 -0400 Subject: [PATCH] Implemented Vivien, Champion of the Wilds --- .../cards/v/VivienChampionOfTheWilds.java | 192 ++++++++++++++++++ Mage.Sets/src/mage/sets/WarOfTheSpark.java | 1 + 2 files changed, 193 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/v/VivienChampionOfTheWilds.java diff --git a/Mage.Sets/src/mage/cards/v/VivienChampionOfTheWilds.java b/Mage.Sets/src/mage/cards/v/VivienChampionOfTheWilds.java new file mode 100644 index 00000000000..be63eb27133 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VivienChampionOfTheWilds.java @@ -0,0 +1,192 @@ +package mage.cards.v; + +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.CastAsThoughItHadFlashAllEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.ReachAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.*; +import mage.constants.*; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.common.TargetCardInLibrary; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class VivienChampionOfTheWilds extends CardImpl { + + private static final FilterCard filter = new FilterCard("creature spells"); + + static { + filter.add(new CardTypePredicate(CardType.CREATURE)); + } + + public VivienChampionOfTheWilds(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{G}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.VIVIEN); + this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4)); + + // You may cast creature spells as though they had flash. + this.addAbility(new SimpleStaticAbility(new CastAsThoughItHadFlashAllEffect( + Duration.WhileOnBattlefield, filter + ))); + + // +1: Until your next turn, up to one target creature gains vigilance and reach. + Ability ability = new LoyaltyAbility(new GainAbilityTargetEffect( + VigilanceAbility.getInstance(), Duration.UntilYourNextTurn + ).setText("Until your next turn, up to one target creature gains vigilance"), 1); + ability.addEffect(new GainAbilityTargetEffect( + ReachAbility.getInstance(), Duration.UntilYourNextTurn + ).setText("and reach")); + ability.addTarget(new TargetCreaturePermanent(0, 1)); + this.addAbility(ability); + + // -2: Look at the top three cards of your library. Exile one face down and put the rest on the bottom of your library in any order. For as long as it remains exiled, you may look at that card and you may cast it if it's a creature card. + this.addAbility(new LoyaltyAbility(new VivienChampionOfTheWildsEffect(), -2)); + } + + private VivienChampionOfTheWilds(final VivienChampionOfTheWilds card) { + super(card); + } + + @Override + public VivienChampionOfTheWilds copy() { + return new VivienChampionOfTheWilds(this); + } +} + +class VivienChampionOfTheWildsEffect extends OneShotEffect { + + VivienChampionOfTheWildsEffect() { + super(Outcome.Benefit); + staticText = "Look at the top three cards of your library. " + + "Exile one face down and put the rest on the bottom of your library in any order. " + + "For as long as it remains exiled, you may look at that card " + + "and you may cast it if it's a creature card."; + } + + private VivienChampionOfTheWildsEffect(final VivienChampionOfTheWildsEffect effect) { + super(effect); + } + + @Override + public VivienChampionOfTheWildsEffect copy() { + return new VivienChampionOfTheWildsEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 3)); + TargetCard target = new TargetCardInLibrary(); + if (!player.choose(outcome, cards, target, game)) { + return false; + } + Card card = game.getCard(target.getFirstTarget()); + if (!player.moveCards(card, Zone.EXILED, source, game)) { + return false; + } + ContinuousEffect effect = new VivienChampionOfTheWildsLookEffect(player.getId()); + effect.setTargetPointer(new FixedTarget(card, game)); + game.addEffect(effect, source); + if (card.isCreature()) { + effect = new VivienChampionOfTheWildsCastFromExileEffect(player.getId()); + effect.setTargetPointer(new FixedTarget(card, game)); + game.addEffect(effect, source); + } + return true; + } +} + +class VivienChampionOfTheWildsLookEffect extends AsThoughEffectImpl { + + private final UUID authorizedPlayerId; + + VivienChampionOfTheWildsLookEffect(UUID authorizedPlayerId) { + super(AsThoughEffectType.LOOK_AT_FACE_DOWN, Duration.EndOfGame, Outcome.Benefit); + this.authorizedPlayerId = authorizedPlayerId; + } + + private VivienChampionOfTheWildsLookEffect(final VivienChampionOfTheWildsLookEffect effect) { + super(effect); + this.authorizedPlayerId = effect.authorizedPlayerId; + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public VivienChampionOfTheWildsLookEffect copy() { + return new VivienChampionOfTheWildsLookEffect(this); + } + + @Override + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + UUID cardId = getTargetPointer().getFirst(game, source); + if (cardId == null) { + this.discard(); // card is no longer in the origin zone, effect can be discarded + } + return affectedControllerId.equals(authorizedPlayerId) + && objectId.equals(cardId); + } +} + +class VivienChampionOfTheWildsCastFromExileEffect extends AsThoughEffectImpl { + + private final UUID authorizedPlayerId; + + VivienChampionOfTheWildsCastFromExileEffect(UUID authorizedPlayerId) { + super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit); + this.authorizedPlayerId = authorizedPlayerId; + } + + private VivienChampionOfTheWildsCastFromExileEffect(final VivienChampionOfTheWildsCastFromExileEffect effect) { + super(effect); + this.authorizedPlayerId = effect.authorizedPlayerId; + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public VivienChampionOfTheWildsCastFromExileEffect copy() { + return new VivienChampionOfTheWildsCastFromExileEffect(this); + } + + @Override + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + UUID cardId = getTargetPointer().getFirst(game, source); + if (cardId == null) { + this.discard(); // card is no longer in the origin zone, effect can be discarded + } else if (objectId.equals(cardId) + && affectedControllerId.equals(authorizedPlayerId)) { + Card card = game.getCard(objectId); + // TODO: Allow to cast Zoetic Cavern face down + return card != null && !card.isLand(); + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/WarOfTheSpark.java b/Mage.Sets/src/mage/sets/WarOfTheSpark.java index 2e799ef7c69..fe581c6060a 100644 --- a/Mage.Sets/src/mage/sets/WarOfTheSpark.java +++ b/Mage.Sets/src/mage/sets/WarOfTheSpark.java @@ -214,6 +214,7 @@ public final class WarOfTheSpark extends ExpansionSet { cards.add(new SetCardInfo("Turret Ogre", 148, Rarity.COMMON, mage.cards.t.TurretOgre.class)); cards.add(new SetCardInfo("Vivien's Arkbow", 181, Rarity.RARE, mage.cards.v.ViviensArkbow.class)); cards.add(new SetCardInfo("Vivien's Grizzly", 182, Rarity.COMMON, mage.cards.v.ViviensGrizzly.class)); + cards.add(new SetCardInfo("Vivien, Champion of the Wilds", 180, Rarity.RARE, mage.cards.v.VivienChampionOfTheWilds.class)); cards.add(new SetCardInfo("Vizier of the Scorpion", 111, Rarity.UNCOMMON, mage.cards.v.VizierOfTheScorpion.class)); cards.add(new SetCardInfo("Vraska's Finisher", 112, Rarity.COMMON, mage.cards.v.VraskasFinisher.class)); cards.add(new SetCardInfo("Vraska, Swarm's Eminence", 236, Rarity.UNCOMMON, mage.cards.v.VraskaSwarmsEminence.class));