diff --git a/Mage.Sets/src/mage/cards/w/WonderscapeSage.java b/Mage.Sets/src/mage/cards/w/WonderscapeSage.java new file mode 100644 index 00000000000..d45845bd93c --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WonderscapeSage.java @@ -0,0 +1,125 @@ +package mage.cards.w; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.ReturnToHandChosenControlledPermanentCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetControlledPermanent; +import mage.util.CardUtil; + +import java.util.*; + +/** + * @author grimreap124, xenohedron + */ +public final class WonderscapeSage extends CardImpl { + + public WonderscapeSage(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}"); + + this.subtype.add(SubType.MOONFOLK); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // {T}, Return a land you control to its owner's hand: Draw a card. Then discard a card unless that land had a nonbasic land type. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new WonderscapeSageEffect(), new TapSourceCost()); + ability.addCost(new WonderscapeSageReturnCost()); + this.addAbility(ability); + } + + private WonderscapeSage(final WonderscapeSage card) { + super(card); + } + + @Override + public WonderscapeSage copy() { + return new WonderscapeSage(this); + } +} + +class WonderscapeSageEffect extends OneShotEffect { + + WonderscapeSageEffect() { + super(Outcome.Benefit); + staticText = "Draw a card. Then discard a card unless that land had a nonbasic land type."; + } + + private WonderscapeSageEffect(final WonderscapeSageEffect effect) { + super(effect); + } + + @Override + public WonderscapeSageEffect copy() { + return new WonderscapeSageEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + player.drawCards(1, source, game); + if (!CardUtil + .castStream(source.getCosts().stream(), WonderscapeSageReturnCost.class) + .filter(Objects::nonNull) + .map(WonderscapeSageReturnCost::getNonBasicLandTypes) + .flatMap(Collection::stream) + .distinct() + .findAny() + .isPresent()) { + player.discardOne(false, false, source, game); + } + return true; + } +} + +class WonderscapeSageReturnCost extends ReturnToHandChosenControlledPermanentCost { + + private final Set nonBasicLandTypes = new HashSet<>(); + + WonderscapeSageReturnCost() { + super(new TargetControlledPermanent(StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND)); + setText("Return a land you control to its owner's hand"); + } + + private WonderscapeSageReturnCost(final WonderscapeSageReturnCost cost) { + super(cost); + this.nonBasicLandTypes.addAll(cost.nonBasicLandTypes); + } + + @Override + public WonderscapeSageReturnCost copy() { + return new WonderscapeSageReturnCost(this); + } + + Set getNonBasicLandTypes() { + return this.nonBasicLandTypes; + } + + @Override + protected void addReturnTarget(Game game, Permanent permanent) { + super.addReturnTarget(game, permanent); + // The Permanent's types will lose the gained/lose types after the sacrifice, so they are stored right before. + if (permanent.getCardType(game).contains(CardType.LAND)) { + permanent.getSubtype(game) + .stream() + .filter(s -> s.getSubTypeSet().equals(SubTypeSet.NonBasicLandType)) + .forEach(nonBasicLandTypes::add); + } + } +} diff --git a/Mage.Sets/src/mage/sets/ModernHorizons3Commander.java b/Mage.Sets/src/mage/sets/ModernHorizons3Commander.java index 7ab7af86874..58cd18f64ab 100644 --- a/Mage.Sets/src/mage/sets/ModernHorizons3Commander.java +++ b/Mage.Sets/src/mage/sets/ModernHorizons3Commander.java @@ -327,6 +327,7 @@ public final class ModernHorizons3Commander extends ExpansionSet { cards.add(new SetCardInfo("Wastes", 408, Rarity.COMMON, mage.cards.w.Wastes.class)); cards.add(new SetCardInfo("Wayfarer's Bauble", 315, Rarity.COMMON, mage.cards.w.WayfarersBauble.class)); cards.add(new SetCardInfo("Whirler Virtuoso", 278, Rarity.UNCOMMON, mage.cards.w.WhirlerVirtuoso.class)); + cards.add(new SetCardInfo("Wonderscape Sage", 49, Rarity.RARE, mage.cards.w.WonderscapeSage.class)); cards.add(new SetCardInfo("World Breaker", 253, Rarity.MYTHIC, mage.cards.w.WorldBreaker.class)); cards.add(new SetCardInfo("Yavimaya Coast", 410, Rarity.RARE, mage.cards.y.YavimayaCoast.class)); cards.add(new SetCardInfo("Yavimaya Elder", 254, Rarity.COMMON, mage.cards.y.YavimayaElder.class)); diff --git a/Mage/src/main/java/mage/abilities/costs/common/ReturnToHandChosenControlledPermanentCost.java b/Mage/src/main/java/mage/abilities/costs/common/ReturnToHandChosenControlledPermanentCost.java index df9acb7e687..5d2144e5244 100644 --- a/Mage/src/main/java/mage/abilities/costs/common/ReturnToHandChosenControlledPermanentCost.java +++ b/Mage/src/main/java/mage/abilities/costs/common/ReturnToHandChosenControlledPermanentCost.java @@ -13,15 +13,15 @@ import mage.players.Player; import mage.target.common.TargetControlledPermanent; import mage.util.CardUtil; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; +import java.util.*; /** * @author BetaSteward_at_googlemail.com */ public class ReturnToHandChosenControlledPermanentCost extends CostImpl { + private final List permanents = new ArrayList<>(); + public ReturnToHandChosenControlledPermanentCost(TargetControlledPermanent target) { target.withNotTarget(true); this.addTarget(target); @@ -37,8 +37,11 @@ public class ReturnToHandChosenControlledPermanentCost extends CostImpl { } } - private ReturnToHandChosenControlledPermanentCost(final ReturnToHandChosenControlledPermanentCost cost) { + protected ReturnToHandChosenControlledPermanentCost(final ReturnToHandChosenControlledPermanentCost cost) { super(cost); + for (Permanent permanent : cost.permanents) { + this.permanents.add(permanent.copy()); + } } @Override @@ -52,6 +55,7 @@ public class ReturnToHandChosenControlledPermanentCost extends CostImpl { if (permanent == null) { return false; } + addReturnTarget(game, permanent); permanentsToReturn.add(permanent); } controller.moveCards(permanentsToReturn, Zone.HAND, ability, game); @@ -61,6 +65,10 @@ public class ReturnToHandChosenControlledPermanentCost extends CostImpl { return paid; } + protected void addReturnTarget(Game game, Permanent permanent) { + permanents.add(permanent.copy()); + } + @Override public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) { return this.getTargets().canChoose(controllerId, source, game); @@ -71,4 +79,8 @@ public class ReturnToHandChosenControlledPermanentCost extends CostImpl { return new ReturnToHandChosenControlledPermanentCost(this); } + public List getPermanents() { + return permanents; + } + }