From 51c997a8ba08dadebde0fe87de6cfd31def3deae Mon Sep 17 00:00:00 2001 From: Cameron Merkel <44722506+cguy7777@users.noreply.github.com> Date: Thu, 22 Feb 2024 03:23:49 -0600 Subject: [PATCH 1/4] Move Cultivate search effect to common class --- Mage.Sets/src/mage/cards/c/Cultivate.java | 76 +---------------- Mage.Sets/src/mage/cards/k/KodamasReach.java | 83 +------------------ Mage.Sets/src/mage/cards/n/NavigationOrb.java | 80 +++--------------- .../src/mage/cards/n/NissasPilgrimage.java | 82 ++++-------------- Mage.Sets/src/mage/cards/p/Peregrination.java | 77 ++--------------- ...OntoBattlefieldTappedRestInHandEffect.java | 79 ++++++++++++++++++ 6 files changed, 120 insertions(+), 357 deletions(-) create mode 100644 Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect.java diff --git a/Mage.Sets/src/mage/cards/c/Cultivate.java b/Mage.Sets/src/mage/cards/c/Cultivate.java index 8f54a7e52983..db5b9a969782 100644 --- a/Mage.Sets/src/mage/cards/c/Cultivate.java +++ b/Mage.Sets/src/mage/cards/c/Cultivate.java @@ -1,20 +1,11 @@ package mage.cards.c; -import mage.MageObject; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.search.SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect; import mage.cards.*; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.filter.FilterCard; import mage.filter.StaticFilters; -import mage.game.Game; -import mage.players.Player; -import mage.target.TargetCard; import mage.target.common.TargetCardInLibrary; -import java.util.Set; import java.util.UUID; /** @@ -25,8 +16,9 @@ public final class Cultivate extends CardImpl { public Cultivate(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}"); - // Search your library for up to two basic land cards, reveal those cards, and put one onto the battlefield tapped and the other into your hand. Then shuffle your library. - this.getSpellAbility().addEffect(new CultivateEffect()); + // Search your library for up to two basic land cards, reveal those cards, put one onto the battlefield tapped and the other into your hand, then shuffle. + this.getSpellAbility().addEffect(new SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect( + new TargetCardInLibrary(0, 2, StaticFilters.FILTER_CARD_BASIC_LANDS))); } @@ -40,63 +32,3 @@ public Cultivate copy() { } } - -class CultivateEffect extends OneShotEffect { - - protected static final FilterCard filter = new FilterCard("card to put on the battlefield tapped"); - - CultivateEffect() { - super(Outcome.PutLandInPlay); - staticText = "search your library for up to two basic land cards, reveal those cards, " + - "put one onto the battlefield tapped and the other into your hand, then shuffle"; - } - - private CultivateEffect(final CultivateEffect effect) { - super(effect); - } - - @Override - public CultivateEffect copy() { - return new CultivateEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - MageObject sourceObject = game.getObject(source); - if (controller == null || sourceObject == null) { - return false; - } - TargetCardInLibrary target = new TargetCardInLibrary(0, 2, StaticFilters.FILTER_CARD_BASIC_LAND); - if (controller.searchLibrary(target, source, game)) { - if (!target.getTargets().isEmpty()) { - Cards revealed = new CardsImpl(target.getTargets()); - controller.revealCards(sourceObject.getIdName(), revealed, game); - if (target.getTargets().size() == 2) { - TargetCard target2 = new TargetCard(Zone.LIBRARY, filter); - controller.choose(Outcome.Benefit, revealed, target2, source, game); - Card card = revealed.get(target2.getFirstTarget(), game); - if (card != null) { - controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null); - revealed.remove(card); - } - Set cards = revealed.getCards(game); - card = cards.isEmpty() ? null : cards.iterator().next(); - if (card != null) { - controller.moveCards(card, Zone.HAND, source, game); - } - } else if (target.getTargets().size() == 1) { - Set cards = revealed.getCards(game); - Card card = cards.isEmpty() ? null : cards.iterator().next(); - if (card != null) { - controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null); - } - } - } - } - controller.shuffleLibrary(source, game); - return true; - - } - -} diff --git a/Mage.Sets/src/mage/cards/k/KodamasReach.java b/Mage.Sets/src/mage/cards/k/KodamasReach.java index 45d57fd0d8bf..c75441593815 100644 --- a/Mage.Sets/src/mage/cards/k/KodamasReach.java +++ b/Mage.Sets/src/mage/cards/k/KodamasReach.java @@ -1,21 +1,12 @@ package mage.cards.k; -import mage.MageObject; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.search.SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect; import mage.cards.*; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SubType; -import mage.constants.Zone; -import mage.filter.FilterCard; import mage.filter.StaticFilters; -import mage.game.Game; -import mage.players.Player; -import mage.target.TargetCard; import mage.target.common.TargetCardInLibrary; -import java.util.Set; import java.util.UUID; /** @@ -27,8 +18,9 @@ public KodamasReach(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}"); this.subtype.add(SubType.ARCANE); - // Search your library for up to two basic land cards, reveal those cards, and put one onto the battlefield tapped and the other into your hand. Then shuffle your library. - this.getSpellAbility().addEffect(new KodamasReachEffect()); + // Search your library for up to two basic land cards, reveal those cards, put one onto the battlefield tapped and the other into your hand, then shuffle. + this.getSpellAbility().addEffect(new SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect( + new TargetCardInLibrary(0, 2, StaticFilters.FILTER_CARD_BASIC_LANDS))); } private KodamasReach(final KodamasReach card) { @@ -40,70 +32,3 @@ public KodamasReach copy() { return new KodamasReach(this); } } - -class KodamasReachEffect extends OneShotEffect { - - protected static final FilterCard filter = new FilterCard("card to put on the battlefield tapped"); - - public KodamasReachEffect() { - super(Outcome.PutLandInPlay); - staticText = "search your library for up to two basic land cards, reveal those cards, " + - "put one onto the battlefield tapped and the other into your hand, then shuffle"; - } - - private KodamasReachEffect(final KodamasReachEffect effect) { - super(effect); - } - - @Override - public KodamasReachEffect copy() { - return new KodamasReachEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - MageObject sourceObject = game.getObject(source); - if (controller == null || sourceObject == null) { - return false; - } - TargetCardInLibrary target = new TargetCardInLibrary(0, 2, StaticFilters.FILTER_CARD_BASIC_LAND); - if (controller.searchLibrary(target, source, game)) { - if (!target.getTargets().isEmpty()) { - Cards revealed = new CardsImpl(); - for (UUID cardId : target.getTargets()) { - Card card = controller.getLibrary().getCard(cardId, game); - revealed.add(card); - } - controller.revealCards(sourceObject.getIdName(), revealed, game); - if (target.getTargets().size() == 2) { - TargetCard target2 = new TargetCard(Zone.LIBRARY, filter); - controller.choose(Outcome.Benefit, revealed, target2, source, game); - Card card = revealed.get(target2.getFirstTarget(), game); - if (card != null) { - controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null); - revealed.remove(card); - } - Set cards = revealed.getCards(game); - card = cards.isEmpty() ? null : cards.iterator().next(); - if (card != null) { - controller.moveCards(card, Zone.HAND, source, game); - } - } else if (target.getTargets().size() == 1) { - Set cards = revealed.getCards(game); - Card card = cards.isEmpty() ? null : cards.iterator().next(); - if (card != null) { - controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null); - } - } - - } - controller.shuffleLibrary(source, game); - return true; - } - controller.shuffleLibrary(source, game); - return false; - - } - -} diff --git a/Mage.Sets/src/mage/cards/n/NavigationOrb.java b/Mage.Sets/src/mage/cards/n/NavigationOrb.java index a82ab57dad02..799b476eba3f 100644 --- a/Mage.Sets/src/mage/cards/n/NavigationOrb.java +++ b/Mage.Sets/src/mage/cards/n/NavigationOrb.java @@ -5,15 +5,11 @@ import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.search.SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect; import mage.cards.*; import mage.constants.*; import mage.filter.FilterCard; -import mage.filter.StaticFilters; import mage.filter.predicate.Predicates; -import mage.game.Game; -import mage.players.Player; -import mage.target.TargetCard; import mage.target.common.TargetCardInLibrary; import java.util.UUID; @@ -23,11 +19,21 @@ */ public final class NavigationOrb extends CardImpl { + private static final FilterCard filter = new FilterCard("basic land cards and/or Gate cards"); + + static { + filter.add(Predicates.or(Predicates.and( + CardType.LAND.getPredicate(), + SuperType.BASIC.getPredicate() + ), SubType.GATE.getPredicate())); + } + public NavigationOrb(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); // {2}, {T}, Sacrifice Navigation Orb: Search your library for up to two basic land cards and/or Gate cards, reveal those cards, put one onto the battlefield tapped and the other into your hand, then shuffle. - Ability ability = new SimpleActivatedAbility(new NavigationOrbEffect(), new GenericManaCost(2)); + Ability ability = new SimpleActivatedAbility(new SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect( + new TargetCardInLibrary(0, 2, filter)), new GenericManaCost(2)); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); this.addAbility(ability); @@ -42,65 +48,3 @@ public NavigationOrb copy() { return new NavigationOrb(this); } } - -class NavigationOrbEffect extends OneShotEffect { - - private static final FilterCard filter = new FilterCard("basic land cards and/or Gate cards"); - - static { - filter.add(Predicates.or(Predicates.and( - CardType.LAND.getPredicate(), - SuperType.BASIC.getPredicate() - ), SubType.GATE.getPredicate())); - } - - NavigationOrbEffect() { - super(Outcome.Benefit); - staticText = "search your library for up to two basic land cards and/or Gate cards, reveal those cards, " + - "put one onto the battlefield tapped and the other into your hand, then shuffle"; - } - - private NavigationOrbEffect(final NavigationOrbEffect effect) { - super(effect); - } - - @Override - public NavigationOrbEffect copy() { - return new NavigationOrbEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player == null) { - return false; - } - TargetCardInLibrary target = new TargetCardInLibrary(0, 2, filter); - player.searchLibrary(target, source, game); - Cards cards = new CardsImpl(); - target.getTargets() - .stream() - .map(uuid -> player.getLibrary().getCard(uuid, game)) - .forEach(cards::add); - player.revealCards(source, cards, game); - Card card; - switch (cards.size()) { - case 0: - player.shuffleLibrary(source, game); - return true; - case 1: - card = cards.getRandom(game); - break; - default: - TargetCard targetCard = new TargetCardInLibrary(0, 1, StaticFilters.FILTER_CARD); - targetCard.withChooseHint("To put onto the battlefield"); - player.choose(outcome, cards, targetCard, source, game); - card = cards.get(targetCard.getFirstTarget(), game); - } - cards.remove(card); - player.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null); - player.moveCards(cards, Zone.HAND, source, game); - player.shuffleLibrary(source, game); - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/n/NissasPilgrimage.java b/Mage.Sets/src/mage/cards/n/NissasPilgrimage.java index 7fb638022079..1938a494e796 100644 --- a/Mage.Sets/src/mage/cards/n/NissasPilgrimage.java +++ b/Mage.Sets/src/mage/cards/n/NissasPilgrimage.java @@ -2,23 +2,15 @@ package mage.cards.n; import java.util.UUID; -import mage.MageObject; -import mage.abilities.Ability; import mage.abilities.condition.common.SpellMasteryCondition; -import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.search.SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.SuperType; -import mage.constants.Zone; import mage.filter.FilterCard; -import mage.game.Game; -import mage.players.Player; import mage.target.common.TargetCardInLibrary; /** @@ -27,12 +19,24 @@ */ public final class NissasPilgrimage extends CardImpl { + private static final FilterCard filter = new FilterCard("basic Forest cards"); + + static { + filter.add(SuperType.BASIC.getPredicate()); + filter.add(SubType.FOREST.getPredicate()); + } + public NissasPilgrimage(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}"); - // Search your library for up to two basic Forest cards, reveal those cards, and put one onto the battlefield tapped and the rest into your hand. Then shuffle your library. + // Search your library for up to two basic Forest cards, reveal those cards, and put one onto the battlefield tapped and the rest into your hand. Then shuffle. // Spell Mastery — If there are two or more instant and/or sorcery cards in your graveyard, search your library for up to three basic Forest cards instead of two. - this.getSpellAbility().addEffect(new NissasPilgrimageEffect()); + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect(new TargetCardInLibrary(0, 3, filter)), + new SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect(new TargetCardInLibrary(0, 2, filter)), + SpellMasteryCondition.instance, + "Search your library for up to two basic Forest cards, reveal those cards, and put one onto the battlefield tapped and the rest into your hand. Then shuffle." + + "
Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, search your library for up to three basic Forest cards instead of two.")); } private NissasPilgrimage(final NissasPilgrimage card) { @@ -44,57 +48,3 @@ public NissasPilgrimage copy() { return new NissasPilgrimage(this); } } - -class NissasPilgrimageEffect extends OneShotEffect { - - private static final FilterCard filter = new FilterCard("basic Forest card"); - - static { - filter.add(SuperType.BASIC.getPredicate()); - filter.add(SubType.FOREST.getPredicate()); - } - - public NissasPilgrimageEffect() { - super(Outcome.Benefit); - this.staticText = "Search your library for up to two basic Forest cards, reveal those cards, and put one onto the battlefield tapped and the rest into your hand. Then shuffle." - + "
Spell mastery — If there are two or more instant and/or sorcery cards in your graveyard, search your library for up to three basic Forest cards instead of two."; - } - - private NissasPilgrimageEffect(final NissasPilgrimageEffect effect) { - super(effect); - } - - @Override - public NissasPilgrimageEffect copy() { - return new NissasPilgrimageEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - MageObject sourceObject = source.getSourceObject(game); - if (controller != null && sourceObject != null) { - int number = 2; - if (SpellMasteryCondition.instance.apply(game, source)) { - number++; - } - TargetCardInLibrary target = new TargetCardInLibrary(0, number, filter); - controller.searchLibrary(target, source, game); - if (!target.getTargets().isEmpty()) { - Cards cards = new CardsImpl(target.getTargets()); - controller.revealCards(sourceObject.getIdName(), cards, game); - if (!cards.isEmpty()) { - Card card = cards.getRandom(game); - if (card != null) { - cards.remove(card); - controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null); - controller.moveCards(cards, Zone.HAND, source, game); - } - } - } - controller.shuffleLibrary(source, game); - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/p/Peregrination.java b/Mage.Sets/src/mage/cards/p/Peregrination.java index 00698583796c..8795a057aa0c 100644 --- a/Mage.Sets/src/mage/cards/p/Peregrination.java +++ b/Mage.Sets/src/mage/cards/p/Peregrination.java @@ -1,22 +1,13 @@ package mage.cards.p; -import mage.MageObject; -import mage.abilities.Ability; import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.search.SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect; import mage.abilities.effects.keyword.ScryEffect; import mage.cards.*; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.filter.FilterCard; import mage.filter.StaticFilters; -import mage.game.Game; -import mage.players.Player; -import mage.target.TargetCard; import mage.target.common.TargetCardInLibrary; -import java.util.Set; import java.util.UUID; /** @@ -27,8 +18,10 @@ public final class Peregrination extends CardImpl { public Peregrination(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}"); - // Seach your library for up to two basic land cards, reveal those cards, and put one onto the battlefield tapped and the other into your hand. Shuffle your library, then scry 1. - this.getSpellAbility().addEffect(new PeregrinationEffect()); + // Search your library for up to two basic land cards, reveal those cards, and put one onto the battlefield tapped and the other into your hand. Shuffle, then scry 1. + this.getSpellAbility().addEffect(new SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect( + new TargetCardInLibrary(0, 2, StaticFilters.FILTER_CARD_BASIC_LANDS)) + .setText("search your library for up to two basic land cards, reveal those cards, and put one onto the battlefield tapped and the other into your hand. Shuffle")); Effect effect = new ScryEffect(1); effect.concatBy(", then"); this.getSpellAbility().addEffect(effect); @@ -43,63 +36,3 @@ public Peregrination copy() { return new Peregrination(this); } } - -class PeregrinationEffect extends OneShotEffect { - - protected static final FilterCard filter = new FilterCard("card to put on the battlefield tapped"); - - public PeregrinationEffect() { - super(Outcome.PutLandInPlay); - staticText = "Search your library for up to two basic land cards, reveal those cards, and put one onto the battlefield tapped and the other into your hand. Shuffle"; - } - - private PeregrinationEffect(final PeregrinationEffect effect) { - super(effect); - } - - @Override - public PeregrinationEffect copy() { - return new PeregrinationEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - MageObject sourceObject = game.getObject(source); - if (controller == null || sourceObject == null) { - return false; - } - TargetCardInLibrary target = new TargetCardInLibrary(0, 2, StaticFilters.FILTER_CARD_BASIC_LAND); - if (controller.searchLibrary(target, source, game)) { - if (!target.getTargets().isEmpty()) { - Cards revealed = new CardsImpl(); - for (UUID cardId : target.getTargets()) { - Card card = controller.getLibrary().getCard(cardId, game); - revealed.add(card); - } - controller.revealCards(sourceObject.getIdName(), revealed, game); - if (target.getTargets().size() == 2) { - TargetCard target2 = new TargetCard(Zone.LIBRARY, filter); - controller.choose(Outcome.Benefit, revealed, target2, source, game); - Card card = revealed.get(target2.getFirstTarget(), game); - controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null); - revealed.remove(card); - Set cards = revealed.getCards(game); - card = cards.isEmpty() ? null : cards.iterator().next(); - controller.moveCards(card, Zone.HAND, source, game); - } else if (target.getTargets().size() == 1) { - Set cards = revealed.getCards(game); - Card card = cards.isEmpty() ? null : cards.iterator().next(); - controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null); - } - - } - controller.shuffleLibrary(source, game); - return true; - } - controller.shuffleLibrary(source, game); - return false; - - } - -} diff --git a/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect.java b/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect.java new file mode 100644 index 000000000000..9b7ef2fb8d90 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect.java @@ -0,0 +1,79 @@ +package mage.abilities.effects.common.search; + +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.SearchEffect; +import mage.cards.Card; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.common.TargetCardInLibrary; + +import java.util.Set; + +/** + * @author BetaSteward_at_googlemail.com, edited by Cguy7777 + */ +public class SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect extends SearchEffect { + + private static final FilterCard filter = new FilterCard("card to put on the battlefield tapped"); + + public SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect(TargetCardInLibrary target) { + super(target, Outcome.PutLandInPlay); + staticText = "search your library for " + target.getDescription() + + ", reveal those cards, put one onto the battlefield tapped and the other into your hand, then shuffle"; + } + + protected SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect(final SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect effect) { + super(effect); + } + + @Override + public SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect copy() { + return new SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getObject(source); + if (controller == null || sourceObject == null) { + return false; + } + + if (controller.searchLibrary(target, source, game)) { + if (!target.getTargets().isEmpty()) { + Cards revealed = new CardsImpl(target.getTargets()); + controller.revealCards(sourceObject.getIdName(), revealed, game); + + if (target.getTargets().size() >= 2) { + TargetCard targetCardToBattlefield = new TargetCard(Zone.LIBRARY, filter); + controller.choose(Outcome.PutLandInPlay, revealed, targetCardToBattlefield, source, game); + Card cardToBattlefield = revealed.get(targetCardToBattlefield.getFirstTarget(), game); + if (cardToBattlefield != null) { + controller.moveCards(cardToBattlefield, Zone.BATTLEFIELD, source, game, true, false, false, null); + revealed.remove(cardToBattlefield); + } + + Set cardsToHand = revealed.getCards(game); + controller.moveCards(cardsToHand, Zone.HAND, source, game); + } else if (target.getTargets().size() == 1) { + Set cards = revealed.getCards(game); + Card card = cards.isEmpty() ? null : cards.iterator().next(); + if (card != null) { + controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null); + } + } + } + controller.shuffleLibrary(source, game); + return true; + } + controller.shuffleLibrary(source, game); + return false; + } +} From be7f81d82ba06a946132b37f65ccee180b3bb2d1 Mon Sep 17 00:00:00 2001 From: Cameron Merkel <44722506+cguy7777@users.noreply.github.com> Date: Thu, 22 Feb 2024 04:21:12 -0600 Subject: [PATCH 2/4] [MKM] Implement Flourishing Bloom-Kin --- .../src/mage/cards/f/FlourishingBloomKin.java | 71 +++++++++++++++++++ .../src/mage/sets/MurdersAtKarlovManor.java | 1 + 2 files changed, 72 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/f/FlourishingBloomKin.java diff --git a/Mage.Sets/src/mage/cards/f/FlourishingBloomKin.java b/Mage.Sets/src/mage/cards/f/FlourishingBloomKin.java new file mode 100644 index 000000000000..66aa3e6824de --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FlourishingBloomKin.java @@ -0,0 +1,71 @@ +package mage.cards.f; + +import java.util.UUID; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.TurnedFaceUpSourceTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.search.SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.keyword.DisguiseAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.FilterCard; +import mage.filter.common.FilterControlledPermanent; +import mage.target.common.TargetCardInLibrary; + +/** + * @author Cguy7777 + */ +public final class FlourishingBloomKin extends CardImpl { + + private static final FilterControlledPermanent filterForests = new FilterControlledPermanent(SubType.FOREST); + private static final FilterCard filterForestCards = new FilterCard("Forest cards"); + + static { + filterForestCards.add(SubType.FOREST.getPredicate()); + } + + private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filterForests); + private static final Hint hint = new ValueHint("Forests you control", xValue); + + public FlourishingBloomKin(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); + + this.subtype.add(SubType.PLANT); + this.subtype.add(SubType.ELEMENTAL); + this.power = new MageInt(0); + this.toughness = new MageInt(0); + + // Flourishing Bloom-Kin gets +1/+1 for each Forest you control. + Ability ability = new SimpleStaticAbility(new BoostSourceEffect(xValue, xValue, Duration.WhileOnBattlefield)); + this.addAbility(ability.addHint(hint)); + + // Disguise {4}{G} + this.addAbility(new DisguiseAbility(this, new ManaCostsImpl<>("{4}{G}"))); + + // When Flourishing Bloom-Kin is turned face up, search your library for up to two Forest cards and reveal them. + // Put one of them onto the battlefield tapped and the other into your hand, then shuffle. + this.addAbility(new TurnedFaceUpSourceTriggeredAbility( + new SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect(new TargetCardInLibrary(0, 2, filterForestCards)) + .setText("search your library for up to two Forest cards and reveal them. Put one of them onto the battlefield tapped and the other into your hand, then shuffle"))); + } + + private FlourishingBloomKin(final FlourishingBloomKin card) { + super(card); + } + + @Override + public FlourishingBloomKin copy() { + return new FlourishingBloomKin(this); + } +} diff --git a/Mage.Sets/src/mage/sets/MurdersAtKarlovManor.java b/Mage.Sets/src/mage/sets/MurdersAtKarlovManor.java index f10f806a1b12..aa5719e3e768 100644 --- a/Mage.Sets/src/mage/sets/MurdersAtKarlovManor.java +++ b/Mage.Sets/src/mage/sets/MurdersAtKarlovManor.java @@ -105,6 +105,7 @@ private MurdersAtKarlovManor() { cards.add(new SetCardInfo("Felonious Rage", 125, Rarity.COMMON, mage.cards.f.FeloniousRage.class)); cards.add(new SetCardInfo("Festerleech", 85, Rarity.UNCOMMON, mage.cards.f.Festerleech.class)); cards.add(new SetCardInfo("Flotsam // Jetsam", 247, Rarity.UNCOMMON, mage.cards.f.FlotsamJetsam.class)); + cards.add(new SetCardInfo("Flourishing Bloom-Kin", 160, Rarity.UNCOMMON, mage.cards.f.FlourishingBloomKin.class)); cards.add(new SetCardInfo("Forensic Gadgeteer", 57, Rarity.RARE, mage.cards.f.ForensicGadgeteer.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Forensic Gadgeteer", 342, Rarity.RARE, mage.cards.f.ForensicGadgeteer.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Forensic Researcher", 58, Rarity.UNCOMMON, mage.cards.f.ForensicResearcher.class)); From 282d5b626feaeadf300a4cd6ba03d9becf6c3ae9 Mon Sep 17 00:00:00 2001 From: Cameron Merkel <44722506+cguy7777@users.noreply.github.com> Date: Fri, 23 Feb 2024 01:00:40 -0600 Subject: [PATCH 3/4] Use TargetCardInLibrary, minor changes to improve readability --- ...eOntoBattlefieldTappedRestInHandEffect.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect.java b/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect.java index 9b7ef2fb8d90..34aaf224b577 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect.java @@ -11,11 +11,8 @@ import mage.filter.FilterCard; import mage.game.Game; import mage.players.Player; -import mage.target.TargetCard; import mage.target.common.TargetCardInLibrary; -import java.util.Set; - /** * @author BetaSteward_at_googlemail.com, edited by Cguy7777 */ @@ -52,21 +49,22 @@ public boolean apply(Game game, Ability source) { controller.revealCards(sourceObject.getIdName(), revealed, game); if (target.getTargets().size() >= 2) { - TargetCard targetCardToBattlefield = new TargetCard(Zone.LIBRARY, filter); + TargetCardInLibrary targetCardToBattlefield = new TargetCardInLibrary(filter); controller.choose(Outcome.PutLandInPlay, revealed, targetCardToBattlefield, source, game); + Card cardToBattlefield = revealed.get(targetCardToBattlefield.getFirstTarget(), game); + Cards cardsToHand = new CardsImpl(revealed); if (cardToBattlefield != null) { controller.moveCards(cardToBattlefield, Zone.BATTLEFIELD, source, game, true, false, false, null); - revealed.remove(cardToBattlefield); + cardsToHand.remove(cardToBattlefield); } - Set cardsToHand = revealed.getCards(game); controller.moveCards(cardsToHand, Zone.HAND, source, game); } else if (target.getTargets().size() == 1) { - Set cards = revealed.getCards(game); - Card card = cards.isEmpty() ? null : cards.iterator().next(); - if (card != null) { - controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null); + Cards cards = new CardsImpl(revealed); + Card cardToBattlefield = cards.getRandom(game); + if (cardToBattlefield != null) { + controller.moveCards(cardToBattlefield, Zone.BATTLEFIELD, source, game, true, false, false, null); } } } From fd5784cf5842ad69fc2de4137e0d688ac7dad731 Mon Sep 17 00:00:00 2001 From: Cameron Merkel <44722506+cguy7777@users.noreply.github.com> Date: Fri, 23 Feb 2024 01:12:44 -0600 Subject: [PATCH 4/4] Announce cards going to hand --- ...earchLibraryPutOneOntoBattlefieldTappedRestInHandEffect.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect.java b/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect.java index 34aaf224b577..ab7e06d9e6ea 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutOneOntoBattlefieldTappedRestInHandEffect.java @@ -59,7 +59,7 @@ public boolean apply(Game game, Ability source) { cardsToHand.remove(cardToBattlefield); } - controller.moveCards(cardsToHand, Zone.HAND, source, game); + controller.moveCardsToHandWithInfo(cardsToHand, source, game, true); } else if (target.getTargets().size() == 1) { Cards cards = new CardsImpl(revealed); Card cardToBattlefield = cards.getRandom(game);