implement [M3C] Wonderscape Sage

closes #12375
This commit is contained in:
xenohedron 2024-09-06 23:06:12 -04:00
parent 64aeba659e
commit eb0ed8d630
3 changed files with 142 additions and 4 deletions

View file

@ -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<SubType> 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<SubType> 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);
}
}
}

View file

@ -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));

View file

@ -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<Permanent> 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<Permanent> getPermanents() {
return permanents;
}
}