From fcd38fd51250e0b4299f01691035d8f1646c87e9 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 10 Feb 2022 18:12:42 -0500 Subject: [PATCH] [AER] reworked Heart of Kiran implementation --- Mage.Sets/src/mage/cards/h/HeartOfKiran.java | 90 ++++--------------- .../mage/abilities/keyword/CrewAbility.java | 44 +++++++-- 2 files changed, 57 insertions(+), 77 deletions(-) diff --git a/Mage.Sets/src/mage/cards/h/HeartOfKiran.java b/Mage.Sets/src/mage/cards/h/HeartOfKiran.java index 78d9b9d421..1b7917376a 100644 --- a/Mage.Sets/src/mage/cards/h/HeartOfKiran.java +++ b/Mage.Sets/src/mage/cards/h/HeartOfKiran.java @@ -1,25 +1,20 @@ - package mage.cards.h; import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.SimpleActivatedAbility; -import mage.abilities.costs.Cost; -import mage.abilities.costs.CostImpl; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.continuous.AddCardTypeSourceEffect; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.RemoveCounterCost; +import mage.abilities.effects.common.InfoEffect; import mage.abilities.keyword.CrewAbility; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.VigilanceAbility; 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.Zone; import mage.counters.CounterType; -import mage.filter.common.FilterControlledPlaneswalkerPermanent; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; -import mage.target.Target; +import mage.filter.StaticFilters; import mage.target.common.TargetControlledPermanent; import java.util.UUID; @@ -44,13 +39,18 @@ public final class HeartOfKiran extends CardImpl { this.addAbility(VigilanceAbility.getInstance()); // Crew 3 - this.addAbility(new CrewAbility(3)); + this.addAbility(new CrewAbility( + 3, + new RemoveCounterCost(new TargetControlledPermanent( + StaticFilters.FILTER_CONTROLLED_PERMANENT_PLANESWALKER + ), CounterType.LOYALTY) + )); // You may remove a loyalty counter from a planeswalker you control rather than pay Heart of Kiran's crew cost. - Cost cost = new HeartOfKiranAlternateCrewCost(CounterType.LOYALTY, 1); - Effect effect = new AddCardTypeSourceEffect(Duration.EndOfTurn, CardType.CREATURE); - effect.setText("You may remove a loyalty counter from a planeswalker you control rather than pay {this}'s crew cost"); - this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, cost)); + this.addAbility(new SimpleStaticAbility( + Zone.ALL, new InfoEffect("you may remove a loyalty counter " + + "from a planeswalker you control rather than pay {this}'s crew cost") + )); } private HeartOfKiran(final HeartOfKiran card) { @@ -62,57 +62,3 @@ public final class HeartOfKiran extends CardImpl { return new HeartOfKiran(this); } } - -class HeartOfKiranAlternateCrewCost extends CostImpl { - - private final CounterType counterTypeToRemove; - private final int countersToRemove; - - private static final FilterControlledPlaneswalkerPermanent filter = new FilterControlledPlaneswalkerPermanent("planeswalker you control"); - - public HeartOfKiranAlternateCrewCost(CounterType counterTypeToRemove, int countersToRemove) { - this.counterTypeToRemove = counterTypeToRemove; - this.countersToRemove = countersToRemove; - } - - public HeartOfKiranAlternateCrewCost(final HeartOfKiranAlternateCrewCost cost) { - super(cost); - this.counterTypeToRemove = cost.counterTypeToRemove; - this.countersToRemove = cost.countersToRemove; - } - - @Override - public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) { - paid = false; - - Target target = new TargetControlledPermanent(1, 1, filter, true); - - if (target.choose(Outcome.Benefit, controllerId, source.getSourceId(), game)) { - Permanent permanent = game.getPermanent(target.getFirstTarget()); - int originalLoyalty = permanent.getCounters(game).getCount(counterTypeToRemove); - - GameEvent event = new GameEvent(GameEvent.EventType.CREW_VEHICLE, target.getFirstTarget(), source, controllerId); - if (!game.replaceEvent(event)) { - permanent.removeCounters(counterTypeToRemove.createInstance(), source, game); - } - - paid = permanent.getCounters(game).getCount(counterTypeToRemove) < originalLoyalty; - - if (paid) { - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CREWED_VEHICLE, target.getFirstTarget(), source, controllerId)); - } - } - - return paid; - } - - @Override - public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) { - return !game.getBattlefield().getAllActivePermanents(filter, game).isEmpty(); - } - - @Override - public HeartOfKiranAlternateCrewCost copy() { - return new HeartOfKiranAlternateCrewCost(this); - } -} diff --git a/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java b/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java index 48d5821752..e4e9938e25 100644 --- a/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/CrewAbility.java @@ -20,8 +20,10 @@ import mage.filter.predicate.permanent.TappedPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; +import mage.players.Player; import mage.target.Target; import mage.target.common.TargetControlledCreaturePermanent; +import mage.util.CardUtil; import java.awt.*; import java.util.Objects; @@ -35,7 +37,13 @@ public class CrewAbility extends SimpleActivatedAbility { private final int value; public CrewAbility(int value) { - super(Zone.BATTLEFIELD, new AddCardTypeSourceEffect(Duration.EndOfTurn, CardType.ARTIFACT, CardType.CREATURE), new CrewCost(value)); + this(value, null); + } + + public CrewAbility(int value, Cost altCost) { + super(Zone.BATTLEFIELD, new AddCardTypeSourceEffect( + Duration.EndOfTurn, CardType.ARTIFACT, CardType.CREATURE + ), new CrewCost(value, altCost)); this.addEffect(new CrewEventEffect()); this.addIcon(CrewAbilityIcon.instance); this.value = value; @@ -53,7 +61,8 @@ public class CrewAbility extends SimpleActivatedAbility { @Override public String getRule() { - return "Crew " + value + " (Tap any number of creatures you control with total power " + value + " or more: This Vehicle becomes an artifact creature until end of turn.)"; + return "Crew " + value + " (Tap any number of creatures you control with total power " + + value + " or more: This Vehicle becomes an artifact creature until end of turn.)"; } } @@ -87,7 +96,8 @@ class CrewEventEffect extends OneShotEffect { class CrewCost extends CostImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("another untapped creature you control"); + private static final FilterControlledCreaturePermanent filter + = new FilterControlledCreaturePermanent("another untapped creature you control"); static { filter.add(TappedPredicate.UNTAPPED); @@ -95,18 +105,39 @@ class CrewCost extends CostImpl { } private final int value; + private final Cost altCost; - CrewCost(int value) { + CrewCost(int value, Cost altCost) { this.value = value; + this.altCost = altCost; } - CrewCost(final CrewCost cost) { + private CrewCost(final CrewCost cost) { super(cost); this.value = cost.value; + this.altCost = cost.altCost.copy(); + } + + private boolean handleAltCost(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) { + if (altCost == null || !altCost.canPay(ability, source, controllerId, game)) { + return false; + } + Player player = game.getPlayer(controllerId); + String costName = altCost.getText(); + String message = CardUtil.getTextWithFirstCharUpperCase( + (CardUtil.checkCostWords(costName) ? "" : "Pay ") + costName + ) + " rather than the crew cost?"; + return player != null + && player.chooseUse(Outcome.Benefit, message, source, game) + && altCost.pay(ability, game, source, controllerId, noMana, costToPay); } @Override public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) { + if (handleAltCost(ability, game, source, controllerId, noMana, costToPay)) { + paid = true; + return true; + } Target target = new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, filter, true) { @Override public String getMessage() { @@ -151,6 +182,9 @@ class CrewCost extends CostImpl { @Override public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) { + if (altCost != null && altCost.canPay(ability, source, controllerId, game)) { + return true; + } int sumPower = 0; for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controllerId, game)) { int powerToAdd = getCrewPower(permanent, game);