diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java index 9680f81d482..256bbf07a3a 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -32,6 +32,7 @@ import forge.game.card.CardCollection; import forge.game.card.CardCollectionView; import forge.game.card.CardDamageMap; import forge.game.card.CardFactory; +import forge.game.card.CardPredicates; import forge.game.card.CardZoneTable; import forge.game.cost.Cost; import forge.game.cost.CostPart; @@ -46,6 +47,7 @@ import forge.game.trigger.Trigger; import forge.game.trigger.TriggerType; import forge.game.trigger.WrappedAbility; import forge.game.zone.ZoneType; +import forge.util.Aggregates; import forge.util.Expressions; import forge.util.TextUtil; import org.apache.commons.lang3.StringUtils; @@ -1099,8 +1101,14 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit } if (hasParam("MaxTotalTargetCMC") && entity instanceof Card) { - final Card c = (Card) entity; - if (c.getCMC() > tr.getMaxTotalCMC(c, this)) { + int soFar = Aggregates.sum(getTargets().getTargetCards(), CardPredicates.Accessors.fnGetCmc); + // only add if it isn't already targeting + if (!isTargeting(entity)) { + final Card c = (Card) entity; + soFar += c.getCMC(); + } + + if (soFar > tr.getMaxTotalCMC(getHostCard(), this)) { return false; } } diff --git a/forge-gui/src/main/java/forge/match/input/InputSelectTargets.java b/forge-gui/src/main/java/forge/match/input/InputSelectTargets.java index 547b185b681..e6ba852fce2 100644 --- a/forge-gui/src/main/java/forge/match/input/InputSelectTargets.java +++ b/forge-gui/src/main/java/forge/match/input/InputSelectTargets.java @@ -6,6 +6,7 @@ import forge.game.GameEntity; import forge.game.GameObject; import forge.game.ability.ApiType; import forge.game.card.Card; +import forge.game.card.CardPredicates; import forge.game.card.CardView; import forge.game.player.Player; import forge.game.spellability.SpellAbility; @@ -16,6 +17,7 @@ import forge.player.PlayerZoneUpdate; import forge.player.PlayerZoneUpdates; import forge.properties.ForgeConstants; import forge.properties.ForgePreferences; +import forge.util.Aggregates; import forge.util.ITriggerEvent; import forge.util.TextUtil; @@ -148,6 +150,9 @@ public final class InputSelectTargets extends InputSyncronizedBase { return false; } + // TODO should use sa.canTarget(card) instead? + // it doesn't have messages + //If the card is not a valid target if (!card.canBeTargetedBy(sa)) { showMessage(sa.getHostCard() + " - Cannot target this card (Shroud? Protection? Restrictions)."); @@ -170,6 +175,20 @@ public final class InputSelectTargets extends InputSyncronizedBase { return false; } + if (sa.hasParam("MaxTotalTargetCMC")) { + int maxTotalCMC = tgt.getMaxTotalCMC(sa.getHostCard(), sa); + if (maxTotalCMC > 0) { + int soFar = Aggregates.sum(sa.getTargets().getTargetCards(), CardPredicates.Accessors.fnGetCmc); + if (!sa.isTargeting(card)) { + soFar += card.getCMC(); + } + if (soFar > maxTotalCMC) { + showMessage(sa.getHostCard() + " - Cannot target this card (CMC limit exceeded)"); + return false; + } + } + } + // If all cards must have different controllers if (tgt.isDifferentControllers()) { final List targetedControllers = new ArrayList<>(); @@ -186,12 +205,7 @@ public final class InputSelectTargets extends InputSyncronizedBase { } if (!choices.contains(card)) { - if (card.isPlaneswalker() && sa.getApi() == ApiType.DealDamage) { - showMessage(sa.getHostCard() + " - To deal an opposing Planeswalker direct damage, target its controller and then redirect the damage on resolution."); - } - else { - showMessage(sa.getHostCard() + " - The selected card is not a valid choice to be targeted."); - } + showMessage(sa.getHostCard() + " - The selected card is not a valid choice to be targeted."); return false; }