From cc4be1b637fb258f1dab8455658fb2898285b463 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 5 Mar 2024 09:42:21 -0500 Subject: [PATCH] [SLD] Implement The Fourteenth Doctor --- .../src/mage/cards/t/TheFourteenthDoctor.java | 184 ++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TheFourteenthDoctor.java diff --git a/Mage.Sets/src/mage/cards/t/TheFourteenthDoctor.java b/Mage.Sets/src/mage/cards/t/TheFourteenthDoctor.java new file mode 100644 index 00000000000..dd4aa4bcc12 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TheFourteenthDoctor.java @@ -0,0 +1,184 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CastSourceTriggeredAbility; +import mage.abilities.effects.common.CopyEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.HasteAbility; +import mage.cards.*; +import mage.constants.*; +import mage.filter.FilterCard; +import mage.filter.predicate.Predicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.players.Player; +import mage.target.Target; +import mage.target.common.TargetCardInYourGraveyard; +import mage.watchers.Watcher; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TheFourteenthDoctor extends CardImpl { + + public TheFourteenthDoctor(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R/G}{W}{U}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.TIME_LORD); + this.subtype.add(SubType.DOCTOR); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // When you cast this spell, reveal the top fourteen cards of your library. Put all Doctor cards revealed this way into your graveyard and the rest on the bottom of your library in a random order. + this.addAbility(new CastSourceTriggeredAbility(new TheFourteenthDoctorRevealEffect())); + + // You may have The Fourteenth Doctor enter the battlefield as a copy of a Doctor card in your graveyard that was put there from your library this turn. If you do, it gains haste until end of turn. + this.addAbility(new EntersBattlefieldTriggeredAbility(new TheFourteenthDoctorCopyEffect(), true)); + } + + private TheFourteenthDoctor(final TheFourteenthDoctor card) { + super(card); + } + + @Override + public TheFourteenthDoctor copy() { + return new TheFourteenthDoctor(this); + } +} + +class TheFourteenthDoctorRevealEffect extends OneShotEffect { + + private static final FilterCard filter = new FilterCard(); + + static { + filter.add(SubType.DOCTOR.getPredicate()); + } + + TheFourteenthDoctorRevealEffect() { + super(Outcome.Benefit); + staticText = "reveal the top fourteen cards of your library. Put all Doctor cards revealed this way " + + "into your graveyard and the rest on the bottom of your library in a random order"; + } + + private TheFourteenthDoctorRevealEffect(final TheFourteenthDoctorRevealEffect effect) { + super(effect); + } + + @Override + public TheFourteenthDoctorRevealEffect copy() { + return new TheFourteenthDoctorRevealEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 14)); + player.revealCards(source, cards, game); + Cards toGrave = new CardsImpl(cards.getCards(filter, game)); + player.moveCards(toGrave, Zone.GRAVEYARD, source, game); + cards.retainZone(Zone.LIBRARY, game); + player.putCardsOnBottomOfLibrary(cards, game, source, false); + return true; + } +} + +class TheFourteenthDoctorCopyEffect extends OneShotEffect { + + private enum TheFourteenthDoctorPredicate implements Predicate { + instance; + + @Override + public boolean apply(Card input, Game game) { + return TheFourteenthDoctorWatcher.checkCard(input, game); + } + } + + private static final FilterCard filter + = new FilterCard("Doctor card in your graveyard that was put there from your library this turn"); + + static { + filter.add(SubType.DOCTOR.getPredicate()); + filter.add(TheFourteenthDoctorPredicate.instance); + } + + TheFourteenthDoctorCopyEffect() { + super(Outcome.Benefit); + staticText = "as a copy of a Doctor card in your graveyard that was put there " + + "from your library this turn. If you do, it gains haste until end of turn"; + } + + private TheFourteenthDoctorCopyEffect(final TheFourteenthDoctorCopyEffect effect) { + super(effect); + } + + @Override + public TheFourteenthDoctorCopyEffect copy() { + return new TheFourteenthDoctorCopyEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + Target target = new TargetCardInYourGraveyard(0, 1, filter, true); + player.choose(outcome, target, source, game); + Card copyFromCard = game.getCard(target.getFirstTarget()); + if (copyFromCard == null) { + return false; + } + CopyEffect copyEffect = new CopyEffect(Duration.Custom, copyFromCard, source.getSourceId()); + game.addEffect(copyEffect, source); + game.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.EndOfTurn), source); + return true; + } +} + +class TheFourteenthDoctorWatcher extends Watcher { + + private final Set set = new HashSet<>(); + + TheFourteenthDoctorWatcher() { + super(WatcherScope.GAME); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() != GameEvent.EventType.ZONE_CHANGE) { + return; + } + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + if (zEvent.getToZone() == Zone.GRAVEYARD && zEvent.getFromZone() == Zone.LIBRARY) { + set.add(new MageObjectReference(zEvent.getTargetId(), game)); + } + } + + @Override + public void reset() { + super.reset(); + set.clear(); + } + + static boolean checkCard(Card card, Game game) { + return game + .getState() + .getWatcher(TheFourteenthDoctorWatcher.class) + .set + .stream() + .anyMatch(mor -> mor.refersTo(card, game)); + } +}