From 35100c253296637f36bbe52d84a9135f7ccb42a1 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Sat, 11 Jan 2020 17:55:03 -0500 Subject: [PATCH] Implemented Calix, Destiny's Hand --- .../src/mage/cards/c/CalixDestinysHand.java | 200 ++++++++++++++++++ .../src/mage/cards/t/TeferiTimeRaveler.java | 2 +- .../src/mage/sets/TherosBeyondDeath.java | 1 + .../src/main/java/mage/constants/SubType.java | 1 + 4 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 Mage.Sets/src/mage/cards/c/CalixDestinysHand.java diff --git a/Mage.Sets/src/mage/cards/c/CalixDestinysHand.java b/Mage.Sets/src/mage/cards/c/CalixDestinysHand.java new file mode 100644 index 0000000000..51ebc046a1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CalixDestinysHand.java @@ -0,0 +1,200 @@ +package mage.cards.c; + +import mage.MageObject; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.LookLibraryAndPickControllerEffect; +import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterCard; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledEnchantmentPermanent; +import mage.filter.common.FilterEnchantmentCard; +import mage.filter.predicate.Predicates; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; +import mage.target.targetpointer.FixedTarget; + +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +import static mage.constants.Outcome.Benefit; + +/** + * @author TheElk801 + */ +public final class CalixDestinysHand extends CardImpl { + + private static final FilterCard filter = new FilterEnchantmentCard(); + private static final FilterPermanent filter2 + = new FilterPermanent("creature or enchantment you don't control"); + + static { + filter.add(TargetController.NOT_YOU.getControllerPredicate()); + filter.add(Predicates.or( + CardType.CREATURE.getPredicate(), + CardType.ENCHANTMENT.getPredicate() + )); + } + + private static final FilterPermanent filter3 = new FilterControlledEnchantmentPermanent(); + + public CalixDestinysHand(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{G}{W}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.CALIX); + this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(4)); + + // +1: Look at the top four cards of your library. You may reveal an enchantment card from among them and put that card into your hand. Put the rest on the bottom of your library in a random order. + this.addAbility(new LoyaltyAbility(new LookLibraryAndPickControllerEffect( + StaticValue.get(4), false, StaticValue.get(1), filter, + Zone.LIBRARY, false, true, false, + Zone.HAND, true, false, false + ).setBackInRandomOrder(true).setText("Look at the top four cards of your library. " + + "You may reveal an enchantment card from among them and put that card into your hand. " + + "Put the rest on the bottom of your library in a random order."), 1 + )); + + // −3: Exile target creature or enchantment you don't control until target enchantment you control leaves the battlefield. + Ability ability = new LoyaltyAbility(new CalixDestinysHandExileEffect(), -3); + ability.addTarget(new TargetPermanent(filter2)); + ability.addTarget(new TargetPermanent(filter3)); + this.addAbility(ability); + + // −7: Return all enchantment cards from your graveyard to the battlefield. + this.addAbility(new LoyaltyAbility(new CalixDestinysHandReturnEffect(), -7)); + } + + private CalixDestinysHand(final CalixDestinysHand card) { + super(card); + } + + @Override + public CalixDestinysHand copy() { + return new CalixDestinysHand(this); + } +} + +class CalixDestinysHandExileEffect extends OneShotEffect { + + CalixDestinysHandExileEffect() { + super(Benefit); + staticText = "Exile target creature or enchantment you don't control " + + "until target enchantment you control leaves the battlefield."; + } + + private CalixDestinysHandExileEffect(final CalixDestinysHandExileEffect effect) { + super(effect); + } + + @Override + public CalixDestinysHandExileEffect copy() { + return new CalixDestinysHandExileEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + List targets = this.getTargetPointer().getTargets(game, source); + Permanent theirPerm = game.getPermanent(targets.get(0)); + Permanent myPerm = game.getPermanent(targets.get(1)); + if (player == null || theirPerm == null || myPerm == null) { + return false; + } + MageObjectReference theirMor = new MageObjectReference( + theirPerm.getId(), theirPerm.getZoneChangeCounter(game) + 1, game + ); + MageObjectReference myMor = new MageObjectReference(myPerm, game); + player.moveCards(theirPerm, Zone.EXILED, source, game); + game.addDelayedTriggeredAbility(new CalixDestinysHandDelayedTriggeredAbility(theirMor, myMor), source); + return true; + } +} + +class CalixDestinysHandDelayedTriggeredAbility extends DelayedTriggeredAbility { + + private final MageObjectReference theirMor; + private final MageObjectReference myMor; + + CalixDestinysHandDelayedTriggeredAbility(MageObjectReference theirMor, MageObjectReference myMor) { + super(null, Duration.Custom, true, false); + this.theirMor = theirMor; + this.myMor = myMor; + this.usesStack = false; + } + + private CalixDestinysHandDelayedTriggeredAbility(final CalixDestinysHandDelayedTriggeredAbility ability) { + super(ability); + this.theirMor = ability.theirMor; + this.myMor = ability.myMor; + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ZONE_CHANGE; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + if (zEvent.getFromZone() != Zone.BATTLEFIELD + || !this.myMor.refersTo(zEvent.getTarget(), game)) { + return false; + } + this.getEffects().clear(); + this.addEffect(new ReturnToBattlefieldUnderOwnerControlTargetEffect() + .setTargetPointer(new FixedTarget(this.theirMor))); + return true; + } + + @Override + public CalixDestinysHandDelayedTriggeredAbility copy() { + return new CalixDestinysHandDelayedTriggeredAbility(this); + } +} + +class CalixDestinysHandReturnEffect extends OneShotEffect { + + CalixDestinysHandReturnEffect() { + super(Benefit); + staticText = "return all enchantment cards from your graveyard to the battlefield"; + } + + private CalixDestinysHandReturnEffect(final CalixDestinysHandReturnEffect effect) { + super(effect); + } + + @Override + public CalixDestinysHandReturnEffect copy() { + return new CalixDestinysHandReturnEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + return player.moveCards( + player.getGraveyard() + .getCards(game) + .stream() + .filter(MageObject::isEnchantment) + .collect(Collectors.toSet()), + Zone.BATTLEFIELD, source, game + ); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TeferiTimeRaveler.java b/Mage.Sets/src/mage/cards/t/TeferiTimeRaveler.java index e24bd1be12..3cfed14c3f 100644 --- a/Mage.Sets/src/mage/cards/t/TeferiTimeRaveler.java +++ b/Mage.Sets/src/mage/cards/t/TeferiTimeRaveler.java @@ -28,7 +28,7 @@ import java.util.UUID; public final class TeferiTimeRaveler extends CardImpl { private static final FilterCard filter = new FilterCard("sorcery spells"); - public static final FilterPermanent filter2 = new FilterPermanent("artifact, creature, or enchantment"); + private static final FilterPermanent filter2 = new FilterPermanent("artifact, creature, or enchantment"); static { filter.add(CardType.SORCERY.getPredicate()); diff --git a/Mage.Sets/src/mage/sets/TherosBeyondDeath.java b/Mage.Sets/src/mage/sets/TherosBeyondDeath.java index 434038c842..64f56989c0 100644 --- a/Mage.Sets/src/mage/sets/TherosBeyondDeath.java +++ b/Mage.Sets/src/mage/sets/TherosBeyondDeath.java @@ -51,6 +51,7 @@ public final class TherosBeyondDeath extends ExpansionSet { cards.add(new SetCardInfo("Blood Aspirant", 128, Rarity.UNCOMMON, mage.cards.b.BloodAspirant.class)); cards.add(new SetCardInfo("Brine Giant", 44, Rarity.COMMON, mage.cards.b.BrineGiant.class)); cards.add(new SetCardInfo("Bronze Sword", 232, Rarity.COMMON, mage.cards.b.BronzeSword.class)); + cards.add(new SetCardInfo("Calix, Destiny's Hand", 211, Rarity.MYTHIC, mage.cards.c.CalixDestinysHand.class)); cards.add(new SetCardInfo("Callaphe, Beloved of the Sea", 45, Rarity.UNCOMMON, mage.cards.c.CallapheBelovedOfTheSea.class)); cards.add(new SetCardInfo("Captivating Unicorn", 6, Rarity.COMMON, mage.cards.c.CaptivatingUnicorn.class)); cards.add(new SetCardInfo("Careless Celebrant", 129, Rarity.UNCOMMON, mage.cards.c.CarelessCelebrant.class)); diff --git a/Mage/src/main/java/mage/constants/SubType.java b/Mage/src/main/java/mage/constants/SubType.java index 3aef6dae37..2fb4ea0410 100644 --- a/Mage/src/main/java/mage/constants/SubType.java +++ b/Mage/src/main/java/mage/constants/SubType.java @@ -391,6 +391,7 @@ public enum SubType { ASHIOK("Ashiok", SubTypeSet.PlaneswalkerType), AURRA("Aurra", SubTypeSet.PlaneswalkerType, true), // Star Wars BOLAS("Bolas", SubTypeSet.PlaneswalkerType), + CALIX("Calix", SubTypeSet.PlaneswalkerType), CHANDRA("Chandra", SubTypeSet.PlaneswalkerType), DACK("Dack", SubTypeSet.PlaneswalkerType), DARETTI("Daretti", SubTypeSet.PlaneswalkerType),