diff --git a/Mage.Sets/src/mage/cards/g/GetawayCar.java b/Mage.Sets/src/mage/cards/g/GetawayCar.java new file mode 100644 index 0000000000..96e17e6932 --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GetawayCar.java @@ -0,0 +1,143 @@ +package mage.cards.g; + +import mage.MageInt; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.common.AttacksOrBlocksTriggeredAbility; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.abilities.keyword.CrewAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.SubType; +import mage.constants.WatcherScope; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.MageObjectReferencePredicate; +import mage.filter.predicate.mageobject.ManaValuePredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; +import mage.target.targetadjustment.TargetAdjuster; +import mage.util.CardUtil; +import mage.watchers.Watcher; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author TheElk801 + */ +public final class GetawayCar extends CardImpl { + + public GetawayCar(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); + + this.subtype.add(SubType.VEHICLE); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // Whenever Getaway Car attacks or blocks, return up to one target creature that crewed it this turn to its owner's hand. + this.addAbility(new AttacksOrBlocksTriggeredAbility( + new ReturnToHandTargetEffect() + .setText("return up to one target creature that crewed it this turn to its owner's hand"), + false + ).setTargetAdjuster(GetawayCarAdjuster.instance), new GetawayCarWatcher()); + + // Crew 1 + this.addAbility(new CrewAbility(1)); + } + + private GetawayCar(final GetawayCar card) { + super(card); + } + + @Override + public GetawayCar copy() { + return new GetawayCar(this); + } +} + +enum GetawayCarAdjuster implements TargetAdjuster { + instance; + + @Override + public void adjustTargets(Ability ability, Game game) { + ability.getTargets().clear(); + ability.addTarget(new TargetPermanent( + 0, 1, GetawayCarWatcher.makeFilter(ability, game) + )); + } +} + +class GetawayCarWatcher extends Watcher { + + private final Map> crewMap = new HashMap<>(); + private static final FilterPermanent invalidFilter = new FilterPermanent(); + + static { + invalidFilter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, -2)); + } + + GetawayCarWatcher() { + super(WatcherScope.GAME); + } + + @Override + public void watch(GameEvent event, Game game) { + Permanent vehicle; + Permanent crewer; + switch (event.getType()) { + case VEHICLE_CREWED: + vehicle = game.getPermanent(event.getTargetId()); + crewer = null; + break; + case CREWED_VEHICLE: + vehicle = game.getPermanent(event.getSourceId()); + crewer = game.getPermanent(event.getTargetId()); + break; + default: + return; + } + if (vehicle == null) { + return; + } + crewMap.computeIfAbsent( + new MageObjectReference(vehicle, game), x -> new HashSet<>() + ).add(new MageObjectReference(crewer, game)); + } + + @Override + public void reset() { + super.reset(); + crewMap.clear(); + } + + public static FilterPermanent makeFilter(Ability source, Game game) { + Set predicates = game + .getState() + .getWatcher(GetawayCarWatcher.class) + .crewMap + .computeIfAbsent(new MageObjectReference(source), x -> new HashSet<>()) + .stream() + .filter(mor -> { + Permanent permanent = mor.getPermanent(game); + return permanent != null && permanent.isCreature(game); + }).map(MageObjectReferencePredicate::new) + .collect(Collectors.toSet()); + if (predicates.isEmpty()) { + return invalidFilter; + } + FilterPermanent filterPermanent = new FilterPermanent( + "creature that crewed " + CardUtil.getSourceName(game, source) + " this turn" + ); + filterPermanent.add(Predicates.or(predicates)); + return filterPermanent; + } +} diff --git a/Mage.Sets/src/mage/sets/StreetsOfNewCapenna.java b/Mage.Sets/src/mage/sets/StreetsOfNewCapenna.java index 4303bdc79c..ca7bc5537a 100644 --- a/Mage.Sets/src/mage/sets/StreetsOfNewCapenna.java +++ b/Mage.Sets/src/mage/sets/StreetsOfNewCapenna.java @@ -39,6 +39,7 @@ public final class StreetsOfNewCapenna extends ExpansionSet { cards.add(new SetCardInfo("Disciplined Duelist", 182, Rarity.UNCOMMON, mage.cards.d.DisciplinedDuelist.class)); cards.add(new SetCardInfo("Forest", 270, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Gala Greeters", 148, Rarity.RARE, mage.cards.g.GalaGreeters.class)); + cards.add(new SetCardInfo("Getaway Car", 237, Rarity.RARE, mage.cards.g.GetawayCar.class)); cards.add(new SetCardInfo("Island", 264, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Jetmir's Garden", 250, Rarity.RARE, mage.cards.j.JetmirsGarden.class)); cards.add(new SetCardInfo("Jetmir, Nexus of Revels", 193, Rarity.MYTHIC, mage.cards.j.JetmirNexusOfRevels.class));