diff --git a/Mage.Sets/src/mage/cards/r/RaulTroubleShooter.java b/Mage.Sets/src/mage/cards/r/RaulTroubleShooter.java index 030bc31eddb..6a7723eee0d 100644 --- a/Mage.Sets/src/mage/cards/r/RaulTroubleShooter.java +++ b/Mage.Sets/src/mage/cards/r/RaulTroubleShooter.java @@ -1,23 +1,21 @@ package mage.cards.r; import mage.MageInt; -import mage.MageObjectReference; import mage.abilities.common.CastFromGraveyardOnceEachTurnAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.effects.common.MillCardsEachPlayerEffect; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.TargetController; import mage.filter.FilterCard; -import mage.filter.predicate.ObjectSourcePlayer; -import mage.filter.predicate.ObjectSourcePlayerPredicate; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.watchers.Watcher; +import mage.filter.predicate.card.MilledThisTurnPredicate; +import mage.watchers.common.CardsMilledWatcher; -import java.util.*; +import java.util.UUID; /** * @author Susucr @@ -27,7 +25,7 @@ public final class RaulTroubleShooter extends CardImpl { private static final FilterCard filter = new FilterCard("a spell from among cards in your graveyard that were milled this turn"); static { - filter.add(RaulTroubleShooterPredicate.instance); + filter.add(MilledThisTurnPredicate.instance); } public RaulTroubleShooter(UUID ownerId, CardSetInfo setInfo) { @@ -41,7 +39,7 @@ public final class RaulTroubleShooter extends CardImpl { this.toughness = new MageInt(4); // Once during each of your turns, you may cast a spell from among cards in your graveyard that were milled this turn. - this.addAbility(new CastFromGraveyardOnceEachTurnAbility(filter), new RaulTroubleShooterWatcher()); + this.addAbility(new CastFromGraveyardOnceEachTurnAbility(filter), new CardsMilledWatcher()); // {T}: Each player mills a card. this.addAbility(new SimpleActivatedAbility( @@ -58,59 +56,4 @@ public final class RaulTroubleShooter extends CardImpl { public RaulTroubleShooter copy() { return new RaulTroubleShooter(this); } -} - -enum RaulTroubleShooterPredicate implements ObjectSourcePlayerPredicate { - instance; - - @Override - public boolean apply(ObjectSourcePlayer input, Game game) { - return RaulTroubleShooterWatcher.wasMilledThisTurn( - input.getPlayerId(), - new MageObjectReference(input.getObject().getMainCard(), game), - game - ); - } -} - -class RaulTroubleShooterWatcher extends Watcher { - - // player -> set of Cards mor (the main card's mor) milled this turn. - private final Map> milledThisTurn = new HashMap<>(); - - RaulTroubleShooterWatcher() { - super(WatcherScope.GAME); - } - - @Override - public void watch(GameEvent event, Game game) { - if (event.getType() != GameEvent.EventType.MILLED_CARD) { - return; - } - Card card = game.getCard(event.getTargetId()); - if (card == null) { - return; - } - Card mainCard = card.getMainCard(); - if (game.getState().getZone(mainCard.getId()) != Zone.GRAVEYARD) { - // Ensure that the current zone is indeed the graveyard - return; - } - milledThisTurn.computeIfAbsent(event.getPlayerId(), k -> new HashSet<>()); - milledThisTurn.get(event.getPlayerId()).add(new MageObjectReference(mainCard, game)); - } - - @Override - public void reset() { - super.reset(); - milledThisTurn.clear(); - } - - static boolean wasMilledThisTurn(UUID playerId, MageObjectReference morMainCard, Game game) { - RaulTroubleShooterWatcher watcher = game.getState().getWatcher(RaulTroubleShooterWatcher.class); - return watcher != null && watcher - .milledThisTurn - .getOrDefault(playerId, Collections.emptySet()) - .contains(morMainCard); - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/t/TatoFarmer.java b/Mage.Sets/src/mage/cards/t/TatoFarmer.java new file mode 100644 index 00000000000..66ef552aedd --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TatoFarmer.java @@ -0,0 +1,67 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.LandfallAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; +import mage.abilities.effects.common.counter.AddCountersPlayersEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.counters.CounterType; +import mage.filter.FilterCard; +import mage.filter.common.FilterLandCard; +import mage.filter.predicate.card.MilledThisTurnPredicate; +import mage.target.common.TargetCardInGraveyard; +import mage.watchers.common.CardsMilledWatcher; + +import java.util.UUID; + +/** + * @author Susucr + */ +public final class TatoFarmer extends CardImpl { + + private static final FilterCard filter = new FilterLandCard("land card in a graveyard that was milled this turn"); + + static { + filter.add(MilledThisTurnPredicate.instance); + } + + public TatoFarmer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); + + this.subtype.add(SubType.ZOMBIE); + this.subtype.add(SubType.MUTANT); + this.subtype.add(SubType.PEASANT); + this.power = new MageInt(1); + this.toughness = new MageInt(4); + + // Landfall -- Whenever a land enters the battlefield under your control, you may get two rad counters. + this.addAbility(new LandfallAbility( + new AddCountersPlayersEffect(CounterType.RAD.createInstance(2), TargetController.YOU), true + )); + + // {T}: Put target land card in a graveyard that was milled this turn onto the battlefield under your control tapped. + Ability ability = new SimpleActivatedAbility( + new ReturnFromGraveyardToBattlefieldTargetEffect(true), + new TapSourceCost() + ); + ability.addTarget(new TargetCardInGraveyard(filter)); + this.addAbility(ability, new CardsMilledWatcher()); + } + + private TatoFarmer(final TatoFarmer card) { + super(card); + } + + @Override + public TatoFarmer copy() { + return new TatoFarmer(this); + } +} + diff --git a/Mage.Sets/src/mage/sets/Fallout.java b/Mage.Sets/src/mage/sets/Fallout.java index acdf643613b..9ee352fda34 100644 --- a/Mage.Sets/src/mage/sets/Fallout.java +++ b/Mage.Sets/src/mage/sets/Fallout.java @@ -320,6 +320,7 @@ public final class Fallout extends ExpansionSet { cards.add(new SetCardInfo("Talisman of Progress", 249, Rarity.UNCOMMON, mage.cards.t.TalismanOfProgress.class)); cards.add(new SetCardInfo("Talisman of Resilience", 250, Rarity.UNCOMMON, mage.cards.t.TalismanOfResilience.class)); cards.add(new SetCardInfo("Tarmogoyf", 349, Rarity.MYTHIC, mage.cards.t.Tarmogoyf.class)); + cards.add(new SetCardInfo("Tato Farmer", 86, Rarity.RARE, mage.cards.t.TatoFarmer.class)); cards.add(new SetCardInfo("Temple of Abandon", 302, Rarity.RARE, mage.cards.t.TempleOfAbandon.class)); cards.add(new SetCardInfo("Temple of Deceit", 303, Rarity.RARE, mage.cards.t.TempleOfDeceit.class)); cards.add(new SetCardInfo("Temple of Enlightenment", 304, Rarity.RARE, mage.cards.t.TempleOfEnlightenment.class)); diff --git a/Mage/src/main/java/mage/filter/predicate/card/MilledThisTurnPredicate.java b/Mage/src/main/java/mage/filter/predicate/card/MilledThisTurnPredicate.java new file mode 100644 index 00000000000..3c27dfdf4c8 --- /dev/null +++ b/Mage/src/main/java/mage/filter/predicate/card/MilledThisTurnPredicate.java @@ -0,0 +1,23 @@ +package mage.filter.predicate.card; + +import mage.MageObjectReference; +import mage.cards.Card; +import mage.filter.predicate.Predicate; +import mage.game.Game; +import mage.watchers.common.CardsMilledWatcher; + +/** + * Needs CardsMilledWatcher to work. + * + * @author Susucr + */ +public enum MilledThisTurnPredicate implements Predicate { + instance; + + @Override + public boolean apply(Card input, Game game) { + return CardsMilledWatcher.wasMilledThisTurn( + new MageObjectReference(input.getMainCard(), game), game + ); + } +} diff --git a/Mage/src/main/java/mage/watchers/common/CardsMilledWatcher.java b/Mage/src/main/java/mage/watchers/common/CardsMilledWatcher.java new file mode 100644 index 00000000000..9aa2cbc1b57 --- /dev/null +++ b/Mage/src/main/java/mage/watchers/common/CardsMilledWatcher.java @@ -0,0 +1,56 @@ +package mage.watchers.common; + +import mage.MageObjectReference; +import mage.cards.Card; +import mage.constants.WatcherScope; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.watchers.Watcher; + +import java.util.*; + +/** + * Track MOR of mainCard milled this turn. + * + * @author Susucr + */ +public class CardsMilledWatcher extends Watcher { + + // set of Cards (the main card's mor) milled this turn. + private final Set milledThisTurn = new HashSet<>(); + + public CardsMilledWatcher() { + super(WatcherScope.GAME); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() != GameEvent.EventType.MILLED_CARD) { + return; + } + Card card = game.getCard(event.getTargetId()); + if (card == null) { + return; + } + Card mainCard = card.getMainCard(); + if (game.getState().getZone(mainCard.getId()) != Zone.GRAVEYARD) { + // Ensure that the current zone is indeed the graveyard + return; + } + milledThisTurn.add(new MageObjectReference(mainCard, game)); + } + + @Override + public void reset() { + super.reset(); + milledThisTurn.clear(); + } + + public static boolean wasMilledThisTurn(MageObjectReference morMainCard, Game game) { + CardsMilledWatcher watcher = game.getState().getWatcher(CardsMilledWatcher.class); + return watcher != null && watcher + .milledThisTurn + .contains(morMainCard); + } +}