diff --git a/Mage.Sets/src/mage/cards/k/KasminaEnigmaSage.java b/Mage.Sets/src/mage/cards/k/KasminaEnigmaSage.java new file mode 100644 index 0000000000..ee9932b32d --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KasminaEnigmaSage.java @@ -0,0 +1,189 @@ +package mage.cards.k; + +import mage.ApprovingObject; +import mage.abilities.Ability; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.common.GetXLoyaltyValue; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.keyword.ScryEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.counters.CounterType; +import mage.filter.FilterCard; +import mage.filter.StaticFilters; +import mage.filter.common.FilterInstantOrSorceryCard; +import mage.filter.predicate.mageobject.SharesColorPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.FractalToken; +import mage.game.permanent.token.Token; +import mage.players.Player; +import mage.target.common.TargetCardInLibrary; + +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * @author TheElk801 + */ +public final class KasminaEnigmaSage extends CardImpl { + + public KasminaEnigmaSage(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{1}{G}{U}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.KASMINA); + this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(2)); + + // Each other planeswalker you control has the loyalty abilities of Kasmina, Enigma Sage. + this.addAbility(new SimpleStaticAbility(new KasminaEnigmaSageGainAbilitiesEffect())); + + // +2: Scry 1. + this.addAbility(new LoyaltyAbility(new ScryEffect(1), 2)); + + // −X: Create a 0/0 green and blue Fractal creature token. Put X +1/+1 counters on it. + this.addAbility(new LoyaltyAbility(new KasminaEnigmaSageTokenEffect())); + + // −8: Search your library for an instant or sorcery card that shares a color with this planeswalker, exile that card, then shuffle. You may cast that card without paying its mana cost. + this.addAbility(new LoyaltyAbility(new KasminaEnigmaSageSearchEffect(), -8)); + } + + private KasminaEnigmaSage(final KasminaEnigmaSage card) { + super(card); + } + + @Override + public KasminaEnigmaSage copy() { + return new KasminaEnigmaSage(this); + } +} + +class KasminaEnigmaSageGainAbilitiesEffect extends ContinuousEffectImpl { + + KasminaEnigmaSageGainAbilitiesEffect() { + super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + staticText = "each other planeswalker you control has the loyalty abilities of {this}"; + } + + private KasminaEnigmaSageGainAbilitiesEffect(final KasminaEnigmaSageGainAbilitiesEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent perm = source.getSourcePermanentIfItStillExists(game); + if (perm == null) { + return true; + } + List loyaltyAbilities = perm + .getAbilities(game) + .stream() + .filter(LoyaltyAbility.class::isInstance) + .collect(Collectors.toList()); + for (Permanent permanent : game.getState().getBattlefield().getActivePermanents( + StaticFilters.FILTER_CONTROLLED_PERMANENT_PLANESWALKER, + source.getControllerId(), source.getSourceId(), game + )) { + if (permanent == null || permanent == perm) { + continue; + } + for (Ability ability : loyaltyAbilities) { + permanent.addAbility(ability, source.getSourceId(), game); + } + } + return true; + } + + @Override + public KasminaEnigmaSageGainAbilitiesEffect copy() { + return new KasminaEnigmaSageGainAbilitiesEffect(this); + } +} + +class KasminaEnigmaSageTokenEffect extends OneShotEffect { + + KasminaEnigmaSageTokenEffect() { + super(Outcome.Benefit); + staticText = "create a 0/0 green and blue Fractal creature token. Put X +1/+1 counters on it"; + } + + private KasminaEnigmaSageTokenEffect(final KasminaEnigmaSageTokenEffect effect) { + super(effect); + } + + @Override + public KasminaEnigmaSageTokenEffect copy() { + return new KasminaEnigmaSageTokenEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Token token = new FractalToken(); + token.putOntoBattlefield(1, game, source, source.getControllerId()); + int loyalty = GetXLoyaltyValue.instance.calculate(game, source, this); + if (loyalty < 1) { + return true; + } + for (UUID tokenId : token.getLastAddedTokenIds()) { + Permanent permanent = game.getPermanent(tokenId); + if (permanent != null) { + permanent.addCounters(CounterType.P1P1.createInstance(loyalty), source.getControllerId(), source, game); + } + } + return true; + } +} + +class KasminaEnigmaSageSearchEffect extends OneShotEffect { + + KasminaEnigmaSageSearchEffect() { + super(Outcome.Benefit); + staticText = "Search your library for an instant or sorcery card that shares a color with this planeswalker, " + + "exile that card, then shuffle. You may cast that card without paying its mana cost."; + } + + private KasminaEnigmaSageSearchEffect(final KasminaEnigmaSageSearchEffect effect) { + super(effect); + } + + @Override + public KasminaEnigmaSageSearchEffect copy() { + return new KasminaEnigmaSageSearchEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = source.getSourcePermanentOrLKI(game); + if (controller == null || permanent == null) { + return false; + } + FilterCard filter = new FilterInstantOrSorceryCard( + "an instant, or sorcery card which shares a color with " + permanent.getLogName() + ); + filter.add(new SharesColorPredicate(permanent.getColor(game))); + TargetCardInLibrary target = new TargetCardInLibrary(filter); + controller.searchLibrary(target, source, game); + Card card = controller.getLibrary().getCard(target.getFirstTarget(), game); + if (card != null) { + controller.moveCards(card, Zone.EXILED, source, game); + } + controller.shuffleLibrary(source, game); + if (card == null || !controller.chooseUse( + Outcome.PlayForFree, "Cast " + card.getName() + " without paying its mana cost?", source, game + )) { + return true; + } + game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE); + Boolean cardWasCast = controller.cast(controller.chooseAbilityForCast(card, game, true), + game, true, new ApprovingObject(source, game)); + game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null); + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/StrixhavenSchoolOfMages.java b/Mage.Sets/src/mage/sets/StrixhavenSchoolOfMages.java index 6bd8beee9e..bec822f4f4 100644 --- a/Mage.Sets/src/mage/sets/StrixhavenSchoolOfMages.java +++ b/Mage.Sets/src/mage/sets/StrixhavenSchoolOfMages.java @@ -27,6 +27,7 @@ public final class StrixhavenSchoolOfMages extends ExpansionSet { this.ratioBoosterMythic = 7.4; this.maxCardNumberInBooster = 275; + cards.add(new SetCardInfo("Kasmina, Enigma Sage", 196, Rarity.MYTHIC, mage.cards.k.KasminaEnigmaSage.class)); cards.add(new SetCardInfo("Lorehold Command", 199, Rarity.RARE, mage.cards.l.LoreholdCommand.class)); cards.add(new SetCardInfo("Prismari Command", 214, Rarity.RARE, mage.cards.p.PrismariCommand.class)); cards.add(new SetCardInfo("Quandrix Command", 217, Rarity.RARE, mage.cards.q.QuandrixCommand.class)); diff --git a/Mage/src/main/java/mage/constants/SubType.java b/Mage/src/main/java/mage/constants/SubType.java index 55079b085d..05f051f4e9 100644 --- a/Mage/src/main/java/mage/constants/SubType.java +++ b/Mage/src/main/java/mage/constants/SubType.java @@ -146,6 +146,7 @@ public enum SubType { FISH("Fish", SubTypeSet.CreatureType), FLAGBEARER("Flagbearer", SubTypeSet.CreatureType), FOX("Fox", SubTypeSet.CreatureType), + FRACTAL("Fractal", SubTypeSet.CreatureType), FROG("Frog", SubTypeSet.CreatureType), FUNGUS("Fungus", SubTypeSet.CreatureType), // G diff --git a/Mage/src/main/java/mage/game/permanent/token/FractalToken.java b/Mage/src/main/java/mage/game/permanent/token/FractalToken.java new file mode 100644 index 0000000000..fbe83a0e0f --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/FractalToken.java @@ -0,0 +1,33 @@ +package mage.game.permanent.token; + +import mage.MageInt; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.Arrays; + +/** + * @author TheElk801 + */ +public final class FractalToken extends TokenImpl { + + public FractalToken() { + super("Fractal", "0/0 green and blue Fractal creature token"); + cardType.add(CardType.CREATURE); + subtype.add(SubType.FRACTAL); + color.setGreen(true); + color.setBlue(true); + power = new MageInt(0); + toughness = new MageInt(0); + + availableImageSetCodes = Arrays.asList("STX"); + } + + private FractalToken(final FractalToken token) { + super(token); + } + + public FractalToken copy() { + return new FractalToken(this); + } +}