diff --git a/Mage.Sets/src/mage/cards/a/AmyPond.java b/Mage.Sets/src/mage/cards/a/AmyPond.java new file mode 100644 index 00000000000..c9313e55bdd --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AmyPond.java @@ -0,0 +1,97 @@ +package mage.cards.a; + +import java.util.UUID; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.SavedDamageValue; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.PartnerWithAbility; +import mage.cards.*; +import mage.constants.*; +import mage.abilities.keyword.DoctorsCompanionAbility; +import mage.counters.CounterType; +import mage.filter.common.FilterSuspendedCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInExile; + +/** + * + * @author Skiwkr + */ +public final class AmyPond extends CardImpl { + + private static final FilterSuspendedCard filter = new FilterSuspendedCard("suspended card you own"); + static { + filter.add(TargetController.YOU.getOwnerPredicate()); + } + + public AmyPond(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Partner with Rory Williams + this.addAbility(new PartnerWithAbility("Rory Williams")); + + // Whenever Amy Pond deals combat damage to a player, choose a suspended card you own and remove that many time counters from it. + Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new AmyPondEffect(SavedDamageValue.MANY), + false, true); + ability.addTarget(new TargetCardInExile(filter).withNotTarget(true)); + this.addAbility(ability); + + // Doctor's companion + this.addAbility(DoctorsCompanionAbility.getInstance()); + + } + + private AmyPond(final AmyPond card) { + super(card); + } + + @Override + public AmyPond copy() { + return new AmyPond(this); + } +} + +class AmyPondEffect extends OneShotEffect { + + private final DynamicValue numberCounters; + + AmyPondEffect(DynamicValue numberCounters) { + super(Outcome.Benefit); + this.numberCounters = numberCounters; + this.staticText= "choose a suspended card you own and remove that many time counters from it"; + } + + private AmyPondEffect(final AmyPondEffect effect) { + super(effect); + this.numberCounters = effect.numberCounters; + } + + @Override + public AmyPondEffect copy() { + return new AmyPondEffect(this); + } + + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Card card = game.getExile().getCard(source.getFirstTarget(), game); + if (card != null) { + card.removeCounters(CounterType.TIME.toString(), (Integer) getValue("damage"), source, game); + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/e/Epochrasite.java b/Mage.Sets/src/mage/cards/e/Epochrasite.java index ced2a932098..29533196bf4 100644 --- a/Mage.Sets/src/mage/cards/e/Epochrasite.java +++ b/Mage.Sets/src/mage/cards/e/Epochrasite.java @@ -1,26 +1,17 @@ package mage.cards.e; import mage.MageInt; -import mage.MageObjectReference; -import mage.abilities.Ability; import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.condition.InvertCondition; import mage.abilities.condition.common.CastFromHandSourcePermanentCondition; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.continuous.GainSuspendEffect; +import mage.abilities.effects.common.ExileSpellWithTimeCountersEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; -import mage.abilities.keyword.SuspendAbility; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SubType; -import mage.constants.Zone; import mage.counters.CounterType; -import mage.game.Game; -import mage.players.Player; import mage.watchers.common.CastFromHandWatcher; import java.util.UUID; @@ -45,7 +36,10 @@ public final class Epochrasite extends CardImpl { new CastFromHandWatcher()); // When Epochrasite dies, exile it with three time counters on it and it gains suspend. - this.addAbility(new DiesSourceTriggeredAbility(new EpochrasiteEffect())); + this.addAbility(new DiesSourceTriggeredAbility(new ExileSpellWithTimeCountersEffect(3, true) + .setText("exile it with three time counters on it and it gains suspend." + + " (At the beginning of its owner's upkeep, they remove a time counter." + + " When the last is removed, they may cast this card without paying its mana cost. It has haste.)"))); } private Epochrasite(final Epochrasite card) { @@ -57,41 +51,3 @@ public final class Epochrasite extends CardImpl { return new Epochrasite(this); } } - -class EpochrasiteEffect extends OneShotEffect { - - EpochrasiteEffect() { - super(Outcome.Benefit); - this.staticText = "exile it with three time counters on it and it gains suspend"; - } - - private EpochrasiteEffect(final EpochrasiteEffect effect) { - super(effect); - } - - @Override - public EpochrasiteEffect copy() { - return new EpochrasiteEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - Card card = game.getCard(source.getSourceId()); - if (controller == null || card == null) { - return false; - } - card = card.getMainCard(); - - if (game.getState().getZone(card.getId()) != Zone.GRAVEYARD) { - return false; - } - - UUID exileId = SuspendAbility.getSuspendExileId(controller.getId(), game); - controller.moveCardToExileWithInfo(card, exileId, "Suspended cards of " + controller.getName(), source, game, Zone.GRAVEYARD, true); - card.addCounters(CounterType.TIME.createInstance(3), source.getControllerId(), source, game); - game.addEffect(new GainSuspendEffect(new MageObjectReference(card, game)), source); - - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/r/RoryWilliams.java b/Mage.Sets/src/mage/cards/r/RoryWilliams.java new file mode 100644 index 00000000000..4fda7ab101b --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RoryWilliams.java @@ -0,0 +1,81 @@ +package mage.cards.r; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CastSourceTriggeredAbility; +import mage.abilities.effects.common.ExileSpellWithTimeCountersEffect; +import mage.abilities.effects.keyword.InvestigateEffect; +import mage.abilities.keyword.*; +import mage.constants.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.stack.Spell; + +/** + * + * @author Skiwkr + */ +public final class RoryWilliams extends CardImpl { + + public RoryWilliams(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{U}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Partner with Amy Pond + this.addAbility(new PartnerWithAbility("Amy Pond")); + + // First strike + this.addAbility(FirstStrikeAbility.getInstance()); + + // Lifelink + this.addAbility(LifelinkAbility.getInstance()); + + // The Last Centurion -- When you cast this spell from anywhere other than exile, exile it with three time counters on it. It gains suspend. Then investigate. + Ability ability = new RoryWilliamsTriggeredAbility(new ExileSpellWithTimeCountersEffect(3, true)); + ability.addEffect(new InvestigateEffect(1).concatBy("Then")); + ability.withFlavorWord("The Last Centurion"); + this.addAbility(ability); + } + + private RoryWilliams(final RoryWilliams card) { + super(card); + } + + @Override + public RoryWilliams copy() { + return new RoryWilliams(this); + } +} + +class RoryWilliamsTriggeredAbility extends CastSourceTriggeredAbility { + + protected RoryWilliamsTriggeredAbility(Effect effect) { + super(effect, false); + this.ruleAtTheTop = true; + setTriggerPhrase("When you cast this spell from anywhere other than exile, "); + } + + protected RoryWilliamsTriggeredAbility(final RoryWilliamsTriggeredAbility ability) { + super(ability); + } + + @Override + public RoryWilliamsTriggeredAbility copy() { + return new RoryWilliamsTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return super.checkTrigger(event,game) + && !((Spell) game.getObject(sourceId)).getFromZone().equals(Zone.EXILED); + } +} diff --git a/Mage.Sets/src/mage/sets/DoctorWho.java b/Mage.Sets/src/mage/sets/DoctorWho.java index 0e7a70792eb..5abcb0108f7 100644 --- a/Mage.Sets/src/mage/sets/DoctorWho.java +++ b/Mage.Sets/src/mage/sets/DoctorWho.java @@ -24,6 +24,7 @@ public final class DoctorWho extends ExpansionSet { cards.add(new SetCardInfo("Adric, Mathematical Genius", 33, Rarity.RARE, mage.cards.a.AdricMathematicalGenius.class)); cards.add(new SetCardInfo("Alistair, the Brigadier", 112, Rarity.RARE, mage.cards.a.AlistairTheBrigadier.class)); cards.add(new SetCardInfo("All of History, All at Once", 34, Rarity.RARE, mage.cards.a.AllOfHistoryAllAtOnce.class)); + cards.add(new SetCardInfo("Amy Pond", 75, Rarity.RARE, mage.cards.a.AmyPond.class)); cards.add(new SetCardInfo("An Unearthly Child", 35, Rarity.RARE, mage.cards.a.AnUnearthlyChild.class)); cards.add(new SetCardInfo("Arcane Signet", 239, Rarity.COMMON, mage.cards.a.ArcaneSignet.class)); cards.add(new SetCardInfo("As Foretold", 214, Rarity.RARE, mage.cards.a.AsForetold.class)); @@ -171,6 +172,7 @@ public final class DoctorWho extends ExpansionSet { cards.add(new SetCardInfo("Rogue's Passage", 299, Rarity.UNCOMMON, mage.cards.r.RoguesPassage.class)); cards.add(new SetCardInfo("Romana II", 27, Rarity.RARE, mage.cards.r.RomanaII.class)); cards.add(new SetCardInfo("Rootbound Crag", 300, Rarity.RARE, mage.cards.r.RootboundCrag.class)); + cards.add(new SetCardInfo("Rory Williams", 153, Rarity.RARE, mage.cards.r.RoryWilliams.class)); cards.add(new SetCardInfo("Rose Tyler", 5, Rarity.RARE, mage.cards.r.RoseTyler.class)); cards.add(new SetCardInfo("Rotating Fireplace", 183, Rarity.RARE, mage.cards.r.RotatingFireplace.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Rotating Fireplace", 461, Rarity.RARE, mage.cards.r.RotatingFireplace.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/ExileSpellWithTimeCountersEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ExileSpellWithTimeCountersEffect.java index 49d882f42b5..95f9e58327a 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ExileSpellWithTimeCountersEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ExileSpellWithTimeCountersEffect.java @@ -1,7 +1,9 @@ package mage.abilities.effects.common; +import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.GainSuspendEffect; import mage.abilities.keyword.SuspendAbility; import mage.cards.Card; import mage.constants.Outcome; @@ -18,16 +20,23 @@ import java.util.UUID; public class ExileSpellWithTimeCountersEffect extends OneShotEffect { private final int counters; + private final boolean gainsSuspend; public ExileSpellWithTimeCountersEffect(int counters) { - super(Outcome.Exile); - this.counters = counters; - this.staticText = "Exile {this} with " + CardUtil.numberToText(this.counters) + " time counters on it"; + this (counters, false); } + public ExileSpellWithTimeCountersEffect(int counters, boolean gainsSuspend) { + super(Outcome.Exile); + this.counters = counters; + this.gainsSuspend = gainsSuspend; + this.staticText = "exile {this} with " + CardUtil.numberToText(this.counters) + " time counters on it" + + (gainsSuspend ? ". It gains suspend" : ""); + } private ExileSpellWithTimeCountersEffect(final ExileSpellWithTimeCountersEffect effect) { super(effect); this.counters = effect.counters; + this.gainsSuspend = effect.gainsSuspend; } @Override @@ -38,14 +47,17 @@ public class ExileSpellWithTimeCountersEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - Card card = game.getStack().getSpell(source.getId()).getCard(); + Card card = game.getCard(source.getSourceId()); if (controller == null || card == null) { - return true; + return false; } UUID exileId = SuspendAbility.getSuspendExileId(controller.getId(), game); if (!card.isCopy() && controller.moveCardsToExile(card, source, game, true, exileId, "Suspended cards of " + controller.getName())) { card.addCounters(CounterType.TIME.createInstance(3), source.getControllerId(), source, game); game.informPlayers(controller.getLogName() + " exiles " + card.getLogName() + " with " + counters + " time counters on it"); + if (gainsSuspend) { + game.addEffect(new GainSuspendEffect(new MageObjectReference(card, game)), source); + } } return true; } diff --git a/Mage/src/main/java/mage/filter/common/FilterSuspendedCard.java b/Mage/src/main/java/mage/filter/common/FilterSuspendedCard.java new file mode 100644 index 00000000000..a06ad43e909 --- /dev/null +++ b/Mage/src/main/java/mage/filter/common/FilterSuspendedCard.java @@ -0,0 +1,32 @@ +package mage.filter.common; + +import mage.abilities.keyword.SuspendAbility; +import mage.counters.CounterType; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.AbilityPredicate; + +/** + * @author skiwkr + * 702.62b. A card is "suspended" if it's in the exile zone, has suspend, and has a time counter on it. + */ +public class FilterSuspendedCard extends FilterCard { + + public FilterSuspendedCard() { + this("suspended card"); + } + + public FilterSuspendedCard(String name) { + super(name); + this.add(new AbilityPredicate(SuspendAbility.class)); + this.add(CounterType.TIME.getPredicate()); + } + + protected FilterSuspendedCard(final FilterSuspendedCard filter) { + super(filter); + } + + @Override + public FilterSuspendedCard copy() { + return new FilterSuspendedCard(this); + } +}