From fe09873631138c145c26357671ae14f2b2177990 Mon Sep 17 00:00:00 2001 From: Jeff Wadsworth Date: Mon, 4 Dec 2023 18:53:12 -0600 Subject: [PATCH] Added The Everflowing Well // The Myriad Pools. Perhaps someone knows why the ability keyword won't show up on the card. Works fine, though. --- .../src/mage/cards/t/TheEverflowingWell.java | 59 ++++++ .../src/mage/cards/t/TheMyriadPools.java | 187 ++++++++++++++++++ .../src/mage/sets/TheLostCavernsOfIxalan.java | 2 + .../common/MillThenDrawControllerEffect.java | 87 ++++++++ 4 files changed, 335 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TheEverflowingWell.java create mode 100644 Mage.Sets/src/mage/cards/t/TheMyriadPools.java create mode 100644 Mage/src/main/java/mage/abilities/effects/common/MillThenDrawControllerEffect.java diff --git a/Mage.Sets/src/mage/cards/t/TheEverflowingWell.java b/Mage.Sets/src/mage/cards/t/TheEverflowingWell.java new file mode 100644 index 00000000000..d9799c9a36d --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheEverflowingWell.java @@ -0,0 +1,59 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package mage.cards.t; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.common.DescendCondition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.MillThenDrawControllerEffect; +import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.keyword.TransformAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; +import mage.constants.CardType; +import mage.constants.SuperType; +import mage.constants.TargetController; + +/** + * + * @author jeffwadsworth + */ +public class TheEverflowingWell extends CardImpl { + + public TheEverflowingWell(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{U}"); + this.supertype.add(SuperType.LEGENDARY); + + this.secondSideCardClazz = mage.cards.t.TheMyriadPools.class; + this.color.setBlue(true); + + // When the Everflowing Well enters the battlefield, mill two cards, then draw two cards + this.addAbility(new EntersBattlefieldTriggeredAbility( + new MillThenDrawControllerEffect(2, 2), false) + ); + + // Descend 8 -- At the beginning of your upkeep, if there are eight of more permanent cards in your graveyard, transform The Everflowing Well. + this.addAbility(new TransformAbility()); + Ability ability = new ConditionalTriggeredAbility(new BeginningOfUpkeepTriggeredAbility( + new TransformSourceEffect(), TargetController.YOU, false), + DescendCondition.EIGHT, "Descend 8 -- At the beginning of your upkeep, if there are eight of more permanent cards in your graveyard, transform {this}."); + ability.setAbilityWord(AbilityWord.DESCEND_8).addHint(DescendCondition.getHint()); + this.addAbility(ability); + } + + private TheEverflowingWell(final TheEverflowingWell card) { + super(card); + } + + @Override + public TheEverflowingWell copy() { + return new TheEverflowingWell(this); + } + +} diff --git a/Mage.Sets/src/mage/cards/t/TheMyriadPools.java b/Mage.Sets/src/mage/cards/t/TheMyriadPools.java new file mode 100644 index 00000000000..a572dfda990 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheMyriadPools.java @@ -0,0 +1,187 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package mage.cards.t; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CopyEffect; +import mage.abilities.mana.BlueManaAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SuperType; +import mage.constants.WatcherScope; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.permanent.PermanentCard; +import mage.game.stack.Spell; +import mage.players.Player; +import mage.target.common.TargetControlledPermanent; +import mage.target.targetpointer.FixedTarget; +import mage.watchers.Watcher; + +/** + * + * @author jeffwadsworth + */ +public class TheMyriadPools extends CardImpl { + + public TheMyriadPools(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.LAND}, null); + this.supertype.add(SuperType.LEGENDARY); + + // this is the second face of The Everflowing Well + this.nightCard = true; + + // {T}: Add {U}. + Ability ability = new BlueManaAbility(); + // Whenever you cast a permanent spell using mana produced by The Myriad Pools, up to one other target permanent you control becomes a copy of that spell until end of turn. + this.addAbility(ability, new TheMyriadPoolsWatcher(ability.getOriginalId().toString())); + this.addAbility(new TheMyriadPoolsTriggeredAbility()); + + } + + private TheMyriadPools(final TheMyriadPools card) { + super(card); + } + + @Override + public TheMyriadPools copy() { + return new TheMyriadPools(this); + } +} + +class TheMyriadPoolsWatcher extends Watcher { + + private UUID permanentId = UUID.randomUUID(); + private final String originalId; + + public TheMyriadPoolsWatcher(String originalId) { + super(WatcherScope.CARD); + this.originalId = originalId; + } + + public boolean manaUsedToCastPermanentPart(UUID id) { + return permanentId.equals(id); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.MANA_PAID) { + if (event.getData() != null + && event.getData().equals(originalId)) { + Spell spell = game.getStack().getSpell(event.getTargetId()); + if (spell != null + && spell.isPermanent(game)) { + Card card = spell.getCard(); + permanentId = card.getId(); + } + } + } + } + + @Override + public void reset() { + super.reset(); + } +} + +class TheMyriadPoolsTriggeredAbility extends TriggeredAbilityImpl { + + public TheMyriadPoolsTriggeredAbility() { + super(Zone.BATTLEFIELD, new TheMyriadPoolsCopyEffect()); + } + + private TheMyriadPoolsTriggeredAbility(final TheMyriadPoolsTriggeredAbility ability) { + super(ability); + } + + @Override + public TheMyriadPoolsTriggeredAbility copy() { + return new TheMyriadPoolsTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.SPELL_CAST; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + TheMyriadPoolsWatcher watcher = game.getState().getWatcher(TheMyriadPoolsWatcher.class, this.getSourceId()); + if (watcher != null + && watcher.manaUsedToCastPermanentPart(event.getSourceId())) { + Spell spell = game.getSpell(event.getSourceId()); + if (spell != null + && spell.isControlledBy(getControllerId())) { + for (Effect effect : this.getEffects()) { + effect.setTargetPointer(new FixedTarget(event.getSourceId())); + } + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever you cast a permanent spell using mana produced by {this}, up to one other target permanent you control becomes a copy of that spell until end of turn."; + } + +} + +class TheMyriadPoolsCopyEffect extends OneShotEffect { + + public TheMyriadPoolsCopyEffect() { + super(Outcome.Neutral); + this.staticText = "copy of card on stack"; + } + + private TheMyriadPoolsCopyEffect(final TheMyriadPoolsCopyEffect effect) { + super(effect); + } + + @Override + public TheMyriadPoolsCopyEffect copy() { + return new TheMyriadPoolsCopyEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent targetPermanentToCopyTo = null; + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + TargetControlledPermanent target = new TargetControlledPermanent(0, 1, new FilterControlledPermanent(), false); + if (controller.choose(Outcome.Neutral, target, source, game)) { + targetPermanentToCopyTo = game.getPermanent(target.getFirstTarget()); + } + Card copyFromCardOnStack = game.getCard(targetPointer.getFirst(game, source)); + Permanent newBluePrint = null; + if (targetPermanentToCopyTo != null) { + if (copyFromCardOnStack != null) { + newBluePrint = new PermanentCard(copyFromCardOnStack, source.getControllerId(), game); + newBluePrint.assignNewId(); + CopyEffect copyEffect = new CopyEffect(Duration.EndOfTurn, newBluePrint, targetPermanentToCopyTo.getId()); + copyEffect.newId(); + Ability newAbility = source.copy(); + copyEffect.init(newAbility, game); + game.addEffect(copyEffect, newAbility); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java b/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java index ea734550b29..8b1e13882d5 100644 --- a/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java +++ b/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java @@ -324,9 +324,11 @@ public final class TheLostCavernsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("The Belligerent", 225, Rarity.RARE, mage.cards.t.TheBelligerent.class)); cards.add(new SetCardInfo("The Core", 256, Rarity.RARE, mage.cards.t.TheCore.class)); cards.add(new SetCardInfo("The Enigma Jewel", 55, Rarity.MYTHIC, mage.cards.t.TheEnigmaJewel.class)); + cards.add(new SetCardInfo("The Everflowing Well", 363, Rarity.RARE, mage.cards.t.TheEverflowingWell.class)); cards.add(new SetCardInfo("The Grim Captain", 266, Rarity.RARE, mage.cards.t.TheGrimCaptain.class)); cards.add(new SetCardInfo("The Millennium Calendar", 257, Rarity.MYTHIC, mage.cards.t.TheMillenniumCalendar.class)); cards.add(new SetCardInfo("The Mycotyrant", 235, Rarity.MYTHIC, mage.cards.t.TheMycotyrant.class)); + cards.add(new SetCardInfo("The Myriad Pools", 363, Rarity.RARE, mage.cards.t.TheMyriadPools.class)); cards.add(new SetCardInfo("The Skullspore Nexus", 212, Rarity.MYTHIC, mage.cards.t.TheSkullsporeNexus.class)); cards.add(new SetCardInfo("Thousand Moons Crackshot", 37, Rarity.COMMON, mage.cards.t.ThousandMoonsCrackshot.class)); cards.add(new SetCardInfo("Thousand Moons Infantry", 38, Rarity.COMMON, mage.cards.t.ThousandMoonsInfantry.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/MillThenDrawControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/MillThenDrawControllerEffect.java new file mode 100644 index 00000000000..1ee4e72d937 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/MillThenDrawControllerEffect.java @@ -0,0 +1,87 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package mage.abilities.effects.common; + +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.game.Game; +import mage.players.Player; +import mage.util.CardUtil; + +/** + * + * @author jeffwadsworth + */ +public class MillThenDrawControllerEffect extends OneShotEffect { + + private final int cardsToMill; + private final int cardsToDraw; + private final boolean optional; + + public MillThenDrawControllerEffect() { + this(1, 1); + } + + public MillThenDrawControllerEffect(boolean optional) { + this(1, 1, optional); + } + + public MillThenDrawControllerEffect(int cardsToMill, int cardsToDraw) { + this(cardsToMill, cardsToDraw, false); + } + + public MillThenDrawControllerEffect(int cardsToMill, int cardsToDraw, boolean optional) { + super(Outcome.Benefit); + this.cardsToMill = cardsToMill; + this.cardsToDraw = cardsToDraw; + this.optional = optional; + } + + protected MillThenDrawControllerEffect(final MillThenDrawControllerEffect effect) { + super(effect); + this.cardsToMill = effect.cardsToMill; + this.cardsToDraw = effect.cardsToDraw; + this.optional = effect.optional; + } + + @Override + public MillThenDrawControllerEffect copy() { + return new MillThenDrawControllerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + if (optional && !controller.chooseUse(outcome, "Mill, then draw?", source, game)) { + return true; + } + controller.millCards(cardsToDraw, source, game); + controller.drawCards(cardsToMill, source, game); + return true; + } + + @Override + public String getText(Mode mode) { + if (staticText != null + && !staticText.isEmpty()) { + return staticText; + } + return (optional ? "you may " : "") + + "mill " + + (cardsToMill == 1 ? "a" : CardUtil.numberToText(cardsToMill)) + + " card" + + (cardsToMill == 1 ? "" : "s") + + (optional ? ". If you do," : ", then") + + " draw " + + (cardsToDraw == 1 ? "a" : CardUtil.numberToText(cardsToDraw)) + + " card" + + (cardsToDraw == 1 ? "" : "s"); + } +}