diff --git a/.gitattributes b/.gitattributes index 16e38c7fbe0..4460a5cb997 100644 --- a/.gitattributes +++ b/.gitattributes @@ -586,7 +586,6 @@ forge-game/src/main/java/forge/game/keyword/Protection.java -text forge-game/src/main/java/forge/game/keyword/SimpleKeyword.java -text forge-game/src/main/java/forge/game/keyword/UndefinedKeyword.java -text forge-game/src/main/java/forge/game/mana/Mana.java svneol=native#text/plain -forge-game/src/main/java/forge/game/mana/ManaCostAdjustment.java -text forge-game/src/main/java/forge/game/mana/ManaCostBeingPaid.java svneol=native#text/plain forge-game/src/main/java/forge/game/mana/ManaPool.java svneol=native#text/plain forge-game/src/main/java/forge/game/mana/package-info.java svneol=native#text/plain diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java b/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java index 343502ad939..47fde1234f3 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java @@ -22,10 +22,10 @@ import forge.game.card.CardLists; import forge.game.card.CardUtil; import forge.game.combat.CombatUtil; import forge.game.cost.Cost; +import forge.game.cost.CostAdjustment; import forge.game.cost.CostPartMana; import forge.game.cost.CostPayment; import forge.game.mana.Mana; -import forge.game.mana.ManaCostAdjustment; import forge.game.mana.ManaCostBeingPaid; import forge.game.mana.ManaPool; import forge.game.phase.PhaseType; @@ -970,7 +970,7 @@ public class ComputerUtilMana { restriction = payCosts.getCostMana().getRestiction(); } ManaCostBeingPaid cost = new ManaCostBeingPaid(mana, restriction); - ManaCostAdjustment.adjust(cost, sa, null, test); + CostAdjustment.adjust(cost, sa, null, test); // Tack xMana Payments into mana here if X is a set value if (sa.getPayCosts() != null && (cost.getXcounter() > 0 || extraMana > 0)) { diff --git a/forge-game/src/main/java/forge/game/cost/CostAdjustment.java b/forge-game/src/main/java/forge/game/cost/CostAdjustment.java index 9a524dc89cb..95c74c282cc 100644 --- a/forge-game/src/main/java/forge/game/cost/CostAdjustment.java +++ b/forge-game/src/main/java/forge/game/cost/CostAdjustment.java @@ -3,6 +3,7 @@ package forge.game.cost; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import org.apache.commons.lang3.StringUtils; @@ -14,8 +15,11 @@ import forge.game.GameObject; import forge.game.ability.AbilityUtils; import forge.game.card.Card; import forge.game.card.CardCollection; +import forge.game.card.CardCollectionView; import forge.game.card.CardFactoryUtil; import forge.game.card.CardLists; +import forge.game.card.CardPredicates; +import forge.game.mana.ManaCostBeingPaid; import forge.game.player.Player; import forge.game.spellability.AbilityActivated; import forge.game.spellability.Spell; @@ -54,7 +58,7 @@ public class CostAdjustment { // Sort abilities to apply them in proper order for (Card c : cardsOnBattlefield) { for (final StaticAbility stAb : c.getStaticAbilities()) { - if (stAb.getMapParams().get("Mode").equals("RaiseCost") && stAb.getMapParams().containsKey("Cost")) { + if (stAb.getMapParams().get("Mode").equals("RaiseCost")) { raiseAbilities.add(stAb); } } @@ -80,7 +84,7 @@ public class CostAdjustment { return; } - Cost part = new Cost(params.get("Cost"), sa.isAbility()); + Cost part = new Cost(params.getOrDefault("Cost", "1"), sa.isAbility()); int count = 0; if (params.containsKey("ForEachShard")) { @@ -129,6 +133,243 @@ public class CostAdjustment { } } + // If cardsToDelveOut is null, will immediately exile the delved cards and remember them on the host card. + // Otherwise, will return them in cardsToDelveOut and the caller is responsible for doing the above. + public static final void adjust(ManaCostBeingPaid cost, final SpellAbility sa, CardCollection cardsToDelveOut, boolean test) { + final Game game = sa.getActivatingPlayer().getGame(); + final Card originalCard = sa.getHostCard(); + + if (sa.isTrigger()) { + return; + } + + boolean isStateChangeToFaceDown = false; + if (sa.isSpell()) { + if (((Spell) sa).isCastFaceDown()) { + // Turn face down to apply cost modifiers correctly + originalCard.setState(CardStateName.FaceDown, false); + isStateChangeToFaceDown = true; + } + } // isSpell + + CardCollection cardsOnBattlefield = new CardCollection(game.getCardsIn(ZoneType.Battlefield)); + cardsOnBattlefield.addAll(game.getCardsIn(ZoneType.Stack)); + cardsOnBattlefield.addAll(game.getCardsIn(ZoneType.Command)); + if (!cardsOnBattlefield.contains(originalCard)) { + cardsOnBattlefield.add(originalCard); + } + final List reduceAbilities = new ArrayList(); + final List setAbilities = new ArrayList(); + + // Sort abilities to apply them in proper order + for (Card c : cardsOnBattlefield) { + for (final StaticAbility stAb : c.getStaticAbilities()) { + if (stAb.getMapParams().get("Mode").equals("ReduceCost")) { + reduceAbilities.add(stAb); + } + else if (stAb.getMapParams().get("Mode").equals("SetCost")) { + setAbilities.add(stAb); + } + } + } + + // Reduce cost + for (final StaticAbility stAb : reduceAbilities) { + applyReduceCostAbility(stAb, sa, cost); + } + if (sa.isSpell() && sa.isOffering()) { // cost reduction from offerings + adjustCostByOffering(cost, sa); + } + if (sa.isSpell() && sa.isEmerge()) { // cost reduction from offerings + adjustCostByEmerge(cost, sa); + } + // Set cost (only used by Trinisphere) is applied last + for (final StaticAbility stAb : setAbilities) { + applySetCostAbility(stAb, sa, cost); + } + + if (sa.isSpell()) { + if (sa.isDelve()) { + sa.getHostCard().clearDelved(); + final Player pc = sa.getActivatingPlayer(); + final CardCollection mutableGrave = new CardCollection(pc.getCardsIn(ZoneType.Graveyard)); + final CardCollectionView toExile = pc.getController().chooseCardsToDelve(cost.getUnpaidShards(ManaCostShard.GENERIC), mutableGrave); + for (final Card c : toExile) { + cost.decreaseGenericMana(1); + if (cardsToDelveOut != null) { + cardsToDelveOut.add(c); + } else if (!test) { + sa.getHostCard().addDelved(c); + pc.getGame().getAction().exile(c); + } + } + } + else if (sa.getHostCard().hasKeyword("Convoke")) { + adjustCostByConvoke(cost, sa, test); + } + } // isSpell + + // Reset card state (if changed) + if (isStateChangeToFaceDown) { + originalCard.setState(CardStateName.Original, false); + } + } + // GetSpellCostChange + + private static void adjustCostByConvoke(ManaCostBeingPaid cost, final SpellAbility sa, boolean test) { + CardCollectionView untappedCreats = CardLists.filter(sa.getActivatingPlayer().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES); + untappedCreats = CardLists.filter(untappedCreats, CardPredicates.Presets.UNTAPPED); + + Map convokedCards = sa.getActivatingPlayer().getController().chooseCardsForConvoke(sa, cost.toManaCost(), untappedCreats); + + // Convoked creats are tapped here with triggers suppressed, + // Then again when payment is done(In InputPayManaCost.done()) with suppression cleared. + // This is to make sure that triggers go off at the right time + // AND that you can't use mana tapabilities of convoked creatures to pay the convoked cost. + for (final Entry conv : convokedCards.entrySet()) { + sa.addTappedForConvoke(conv.getKey()); + cost.decreaseShard(conv.getValue(), 1); + if (!test) { + conv.getKey().tap(); + } + } + } + + private static void adjustCostByOffering(final ManaCostBeingPaid cost, final SpellAbility sa) { + String offeringType = ""; + for (String kw : sa.getHostCard().getKeywords()) { + if (kw.endsWith(" offering")) { + offeringType = kw.split(" ")[0]; + break; + } + } + + Card toSac = null; + CardCollectionView canOffer = CardLists.filter(sa.getActivatingPlayer().getCardsIn(ZoneType.Battlefield), + CardPredicates.isType(offeringType), CardPredicates.canBeSacrificedBy(sa)); + + final CardCollectionView toSacList = sa.getHostCard().getController().getController().choosePermanentsToSacrifice(sa, 0, 1, canOffer, offeringType); + + if (!toSacList.isEmpty()) { + toSac = toSacList.getFirst(); + } + else { + return; + } + + cost.subtractManaCost(toSac.getManaCost()); + + sa.setSacrificedAsOffering(toSac); + toSac.setUsedToPay(true); //stop it from interfering with mana input + } + + private static void adjustCostByEmerge(final ManaCostBeingPaid cost, final SpellAbility sa) { + + Card toSac = null; + CardCollectionView canEmerge = CardLists.filter(sa.getActivatingPlayer().getCreaturesInPlay(), CardPredicates.canBeSacrificedBy(sa)); + + final CardCollectionView toSacList = sa.getHostCard().getController().getController().choosePermanentsToSacrifice(sa, 0, 1, canEmerge, "Creature"); + + if (!toSacList.isEmpty()) { + toSac = toSacList.getFirst(); + } + else { + return; + } + + cost.decreaseGenericMana(toSac.getCMC()); + + sa.setSacrificedAsEmerge(toSac); + toSac.setUsedToPay(true); //stop it from interfering with mana input + } + /** + * Applies applyRaiseCostAbility ability. + * + * @param staticAbility + * a StaticAbility + * @param sa + * the SpellAbility + * @param manaCost + * a ManaCost + */ + private static void applySetCostAbility(final StaticAbility staticAbility, final SpellAbility sa, final ManaCostBeingPaid manaCost) { + final Map params = staticAbility.getMapParams(); + final String amount = params.get("Amount"); + + if (!checkRequirement(sa, staticAbility)) { + return; + } + + int value = 0; + if (StringUtils.isNumeric(amount)) { + value = Integer.parseInt(amount); + } else { + if ("Min3".equals(amount)) { + int cmc = manaCost.getConvertedManaCost(); + if (cmc < 3) { + value = 3 - cmc; + } + } + } + + manaCost.increaseGenericMana(value); + } + + /** + * Applies applyReduceCostAbility ability. + * + * @param staticAbility + * a StaticAbility + * @param sa + * the SpellAbility + * @param manaCost + * a ManaCost + */ + private static void applyReduceCostAbility(final StaticAbility staticAbility, final SpellAbility sa, final ManaCostBeingPaid manaCost) { + //Can't reduce zero cost + if (manaCost.toString().equals("{0}")) { + return; + } + final Map params = staticAbility.getMapParams(); + final Card hostCard = staticAbility.getHostCard(); + final Card card = sa.getHostCard(); + final String amount = params.get("Amount"); + + if (!checkRequirement(sa, staticAbility)) { + return; + } + + int value; + if ("AffectedX".equals(amount)) { + value = CardFactoryUtil.xCount(card, hostCard.getSVar(amount)); + } else if ("X".equals(amount)){ + value = CardFactoryUtil.xCount(hostCard, hostCard.getSVar(amount)); + } else { + value = AbilityUtils.calculateAmount(hostCard, amount, sa); + } + + if (!params.containsKey("Cost") && ! params.containsKey("Color")) { + int minMana = 0; + if (params.containsKey("MinMana")) { + minMana = Integer.valueOf(params.get("MinMana")); + } + + final int maxReduction = Math.max(0, manaCost.getConvertedManaCost() - minMana); + if (maxReduction > 0) { + manaCost.decreaseGenericMana(Math.min(value, maxReduction)); + } + } else { + final String color = params.getOrDefault("Cost", params.get("Color")); + for (final String cost : color.split(" ")) { + if (StringUtils.isNumeric(cost)) { + manaCost.decreaseGenericMana(Integer.parseInt(cost) * value); + } else { + manaCost.decreaseShard(ManaCostShard.parseNonGeneric(cost), value); + } + } + } + } + private static boolean checkRequirement(final SpellAbility sa, final StaticAbility st) { if (st.isSuppressed() || !st.checkConditions()) { return false; @@ -138,7 +379,16 @@ public class CostAdjustment { final Card hostCard = st.getHostCard(); final Player activator = sa.getActivatingPlayer(); final Card card = sa.getHostCard(); - + + if (params.containsKey("ValidCard") + && !card.isValid(params.get("ValidCard").split(","), hostCard.getController(), hostCard, sa)) { + return false; + } + if (params.containsKey("Activator") && ((activator == null) + || !activator.isValid(params.get("Activator"), hostCard.getController(), hostCard, sa))) { + return false; + } + if (params.containsKey("Type")) { final String type = params.get("Type"); if (type.equals("Spell")) { @@ -250,7 +500,6 @@ public class CostAdjustment { return false; } } - return true; } -} +} \ No newline at end of file diff --git a/forge-game/src/main/java/forge/game/mana/ManaCostAdjustment.java b/forge-game/src/main/java/forge/game/mana/ManaCostAdjustment.java deleted file mode 100644 index 02cc2e187ee..00000000000 --- a/forge-game/src/main/java/forge/game/mana/ManaCostAdjustment.java +++ /dev/null @@ -1,501 +0,0 @@ -package forge.game.mana; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.apache.commons.lang3.StringUtils; - -import forge.card.CardStateName; -import forge.card.mana.ManaCostShard; -import forge.game.Game; -import forge.game.GameObject; -import forge.game.ability.AbilityUtils; -import forge.game.card.Card; -import forge.game.card.CardCollection; -import forge.game.card.CardCollectionView; -import forge.game.card.CardFactoryUtil; -import forge.game.card.CardLists; -import forge.game.card.CardPredicates; -import forge.game.player.Player; -import forge.game.spellability.AbilityActivated; -import forge.game.spellability.Spell; -import forge.game.spellability.SpellAbility; -import forge.game.spellability.TargetRestrictions; -import forge.game.staticability.StaticAbility; -import forge.game.zone.ZoneType; - -public class ManaCostAdjustment { - // If cardsToDelveOut is null, will immediately exile the delved cards and remember them on the host card. - // Otherwise, will return them in cardsToDelveOut and the caller is responsible for doing the above. - public static final void adjust(ManaCostBeingPaid cost, final SpellAbility sa, CardCollection cardsToDelveOut, boolean test) { - final Game game = sa.getActivatingPlayer().getGame(); - final Card originalCard = sa.getHostCard(); - - if (sa.isTrigger()) { - return; - } - - boolean isStateChangeToFaceDown = false; - if (sa.isSpell()) { - if (((Spell) sa).isCastFaceDown()) { - // Turn face down to apply cost modifiers correctly - originalCard.setState(CardStateName.FaceDown, false); - isStateChangeToFaceDown = true; - } - } // isSpell - - CardCollection cardsOnBattlefield = new CardCollection(game.getCardsIn(ZoneType.Battlefield)); - cardsOnBattlefield.addAll(game.getCardsIn(ZoneType.Stack)); - cardsOnBattlefield.addAll(game.getCardsIn(ZoneType.Command)); - if (!cardsOnBattlefield.contains(originalCard)) { - cardsOnBattlefield.add(originalCard); - } - final List raiseAbilities = new ArrayList(); - final List reduceAbilities = new ArrayList(); - final List setAbilities = new ArrayList(); - - // Sort abilities to apply them in proper order - for (Card c : cardsOnBattlefield) { - final Iterable staticAbilities = c.getStaticAbilities(); - for (final StaticAbility stAb : staticAbilities) { - if (stAb.getMapParams().get("Mode").equals("RaiseCost") && !stAb.getMapParams().containsKey("Cost")) { - raiseAbilities.add(stAb); - } - else if (stAb.getMapParams().get("Mode").equals("ReduceCost")) { - reduceAbilities.add(stAb); - } - else if (stAb.getMapParams().get("Mode").equals("SetCost")) { - setAbilities.add(stAb); - } - } - } - // Raise cost - for (final StaticAbility stAb : raiseAbilities) { - applyAbility(stAb, "RaiseCost", sa, cost); - } - - // Reduce cost - for (final StaticAbility stAb : reduceAbilities) { - applyAbility(stAb, "ReduceCost", sa, cost); - } - if (sa.isSpell() && sa.isOffering()) { // cost reduction from offerings - adjustCostByOffering(cost, sa); - } - if (sa.isSpell() && sa.isEmerge()) { // cost reduction from offerings - adjustCostByEmerge(cost, sa); - } - // Set cost (only used by Trinisphere) is applied last - for (final StaticAbility stAb : setAbilities) { - applyAbility(stAb, "SetCost", sa, cost); - } - - if (sa.isSpell()) { - if (sa.isDelve()) { - sa.getHostCard().clearDelved(); - final Player pc = sa.getActivatingPlayer(); - final CardCollection mutableGrave = new CardCollection(pc.getCardsIn(ZoneType.Graveyard)); - final CardCollectionView toExile = pc.getController().chooseCardsToDelve(cost.getUnpaidShards(ManaCostShard.GENERIC), mutableGrave); - for (final Card c : toExile) { - cost.decreaseGenericMana(1); - if (cardsToDelveOut != null) { - cardsToDelveOut.add(c); - } else if (!test) { - sa.getHostCard().addDelved(c); - pc.getGame().getAction().exile(c); - } - } - } - else if (sa.getHostCard().hasKeyword("Convoke")) { - adjustCostByConvoke(cost, sa, test); - } - } // isSpell - - // Reset card state (if changed) - if (isStateChangeToFaceDown) { - originalCard.setState(CardStateName.Original, false); - } - } - // GetSpellCostChange - - - /** - * Apply ability. - * - * @param mode - * the mode - * @param sa - * the SpellAbility - * @param originalCost - * the originalCost - * @return the modified ManaCost - */ - private static final void applyAbility(StaticAbility stAb, final String mode, final SpellAbility sa, final ManaCostBeingPaid originalCost) { - - // don't apply the ability if it hasn't got the right mode - if (!stAb.getMapParams().get("Mode").equals(mode)) { - return; - } - - if (stAb.isSuppressed() || !stAb.checkConditions()) { - return; - } - - if (mode.equals("RaiseCost")) { - applyRaiseCostAbility(stAb, sa, originalCost); - } - if (mode.equals("ReduceCost")) { - applyReduceCostAbility(stAb, sa, originalCost); - } - if (mode.equals("SetCost")) { //Set cost is only used by Trinisphere - applyRaiseCostAbility(stAb, sa, originalCost); - } - } - - private static void adjustCostByConvoke(ManaCostBeingPaid cost, final SpellAbility sa, boolean test) { - CardCollectionView untappedCreats = CardLists.filter(sa.getActivatingPlayer().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES); - untappedCreats = CardLists.filter(untappedCreats, CardPredicates.Presets.UNTAPPED); - - Map convokedCards = sa.getActivatingPlayer().getController().chooseCardsForConvoke(sa, cost.toManaCost(), untappedCreats); - - // Convoked creats are tapped here with triggers suppressed, - // Then again when payment is done(In InputPayManaCost.done()) with suppression cleared. - // This is to make sure that triggers go off at the right time - // AND that you can't use mana tapabilities of convoked creatures to pay the convoked cost. - for (final Entry conv : convokedCards.entrySet()) { - sa.addTappedForConvoke(conv.getKey()); - cost.decreaseShard(conv.getValue(), 1); - if (!test) { - conv.getKey().tap(); - } - } - } - - private static void adjustCostByOffering(final ManaCostBeingPaid cost, final SpellAbility sa) { - String offeringType = ""; - for (String kw : sa.getHostCard().getKeywords()) { - if (kw.endsWith(" offering")) { - offeringType = kw.split(" ")[0]; - break; - } - } - - Card toSac = null; - CardCollectionView canOffer = CardLists.filter(sa.getActivatingPlayer().getCardsIn(ZoneType.Battlefield), - CardPredicates.isType(offeringType), CardPredicates.canBeSacrificedBy(sa)); - - final CardCollectionView toSacList = sa.getHostCard().getController().getController().choosePermanentsToSacrifice(sa, 0, 1, canOffer, offeringType); - - if (!toSacList.isEmpty()) { - toSac = toSacList.getFirst(); - } - else { - return; - } - - cost.subtractManaCost(toSac.getManaCost()); - - sa.setSacrificedAsOffering(toSac); - toSac.setUsedToPay(true); //stop it from interfering with mana input - } - - private static void adjustCostByEmerge(final ManaCostBeingPaid cost, final SpellAbility sa) { - - Card toSac = null; - CardCollectionView canEmerge = CardLists.filter(sa.getActivatingPlayer().getCreaturesInPlay(), CardPredicates.canBeSacrificedBy(sa)); - - final CardCollectionView toSacList = sa.getHostCard().getController().getController().choosePermanentsToSacrifice(sa, 0, 1, canEmerge, "Creature"); - - if (!toSacList.isEmpty()) { - toSac = toSacList.getFirst(); - } - else { - return; - } - - cost.decreaseGenericMana(toSac.getCMC()); - - sa.setSacrificedAsEmerge(toSac); - toSac.setUsedToPay(true); //stop it from interfering with mana input - } - /** - * Applies applyRaiseCostAbility ability. - * - * @param staticAbility - * a StaticAbility - * @param sa - * the SpellAbility - * @param manaCost - * a ManaCost - */ - private static void applyRaiseCostAbility(final StaticAbility staticAbility, final SpellAbility sa, final ManaCostBeingPaid manaCost) { - final Map params = staticAbility.getMapParams(); - final Card hostCard = staticAbility.getHostCard(); - final Player activator = sa.getActivatingPlayer(); - final Card card = sa.getHostCard(); - final String amount = params.get("Amount"); - - - if (params.containsKey("ValidCard") - && !card.isValid(params.get("ValidCard").split(","), hostCard.getController(), hostCard, sa)) { - return; - } - - if (params.containsKey("Activator") && ((activator == null) - || !activator.isValid(params.get("Activator"), hostCard.getController(), hostCard, sa))) { - return; - } - - if (params.containsKey("Type")) { - if (params.get("Type").equals("Spell")) { - if (!sa.isSpell()) { - return; - } - if (params.containsKey("OnlyFirstSpell")) { - if (activator == null ) { - return; - } - CardCollection list = CardLists.filterControlledBy(activator.getGame().getStack().getSpellsCastThisTurn(), activator); - if (params.containsKey("ValidCard")) { - list = CardLists.getValidCards(list, params.get("ValidCard"), hostCard.getController(), hostCard); - } - if (list.size() > 0) { - return; - } - } - } else if (params.get("Type").equals("Ability")) { - if (!(sa instanceof AbilityActivated) || sa.isReplacementAbility()) { - return; - } - } else if (params.get("Type").equals("NonManaAbility")) { - if (!(sa instanceof AbilityActivated) || sa.isManaAbility() || sa.isReplacementAbility()) { - return; - } - } else if (params.get("Type").equals("Flashback")) { - if (!sa.isFlashBackAbility()) { - return; - } - } else if (params.get("Type").equals("MorphUp")) { - if (!sa.isMorphUp()) { - return; - } - } else if (params.get("Type").equals("SelfIntrinsicAbility")) { - if (!(sa instanceof AbilityActivated) || sa.isReplacementAbility() || sa.isTemporary()) { - return; - } - } - } - if (params.containsKey("AffectedZone")) { - List zones = ZoneType.listValueOf(params.get("AffectedZone")); - boolean found = false; - for(ZoneType zt : zones) { - if(card.isInZone(zt)) - { - found = true; - break; - } - } - if(!found) { - return; - } - } - if (params.containsKey("ValidTarget")) { - TargetRestrictions tgt = sa.getTargetRestrictions(); - if (tgt == null) { - return; - } - boolean targetValid = false; - for (GameObject target : sa.getTargets().getTargets()) { - if (target.isValid(params.get("ValidTarget").split(","), hostCard.getController(), hostCard, sa)) { - targetValid = true; - } - } - if (!targetValid) { - return; - } - } - if (params.containsKey("ValidSpellTarget")) { - TargetRestrictions tgt = sa.getTargetRestrictions(); - if (tgt == null) { - return; - } - boolean targetValid = false; - for (SpellAbility target : sa.getTargets().getTargetSpells()) { - Card targetCard = target.getHostCard(); - if (targetCard.isValid(params.get("ValidSpellTarget").split(","), hostCard.getController(), hostCard, sa)) { - targetValid = true; - } - } - if (!targetValid) { - return; - } - } - int value = 0; - try { - value = Integer.parseInt(amount); - } - catch(NumberFormatException nfe) { - if ("Min3".equals(amount)) { - int cmc = manaCost.getConvertedManaCost(); - if (cmc < 3) { - value = 3 - cmc; - } - } else if (params.containsKey("AffectedAmount")) { - value = CardFactoryUtil.xCount(card, hostCard.getSVar(amount)); - } else { - value = AbilityUtils.calculateAmount(hostCard, amount, sa); - } - } - - if (!params.containsKey("Color")) { - manaCost.increaseGenericMana(value); - if (manaCost.toString().equals("{0}") && params.containsKey("MinMana")) { - manaCost.increaseGenericMana(Integer.valueOf(params.get("MinMana"))); - } - } else { - final String color = params.get("Color"); - for (final String cost : color.split(" ")) { - if (StringUtils.isNumeric(cost)) { - manaCost.increaseGenericMana(Integer.parseInt(cost) * value); - } else { - manaCost.increaseShard(ManaCostShard.parseNonGeneric(cost), value); - } - } - } - } - - /** - * Applies applyReduceCostAbility ability. - * - * @param staticAbility - * a StaticAbility - * @param sa - * the SpellAbility - * @param manaCost - * a ManaCost - */ - private static void applyReduceCostAbility(final StaticAbility staticAbility, final SpellAbility sa, final ManaCostBeingPaid manaCost) { - //Can't reduce zero cost - if (manaCost.toString().equals("{0}")) { - return; - } - final Map params = staticAbility.getMapParams(); - final Card hostCard = staticAbility.getHostCard(); - final Player activator = sa.getActivatingPlayer(); - final Card card = sa.getHostCard(); - final String amount = params.get("Amount"); - - - if (params.containsKey("ValidCard") - && !card.isValid(params.get("ValidCard").split(","), hostCard.getController(), hostCard, sa)) { - return; - } - if (params.containsKey("Activator") && ((activator == null) - || !activator.isValid(params.get("Activator"), hostCard.getController(), hostCard, sa))) { - return; - } - if (params.containsKey("Type")) { - if (params.get("Type").equals("Spell")) { - if (!sa.isSpell()) { - return; - } - if (params.containsKey("OnlyFirstSpell")) { - if (activator == null ) { - return; - } - CardCollection list = CardLists.filterControlledBy(activator.getGame().getStack().getSpellsCastThisTurn(), activator); - if (params.containsKey("ValidCard")) { - list = CardLists.getValidCards(list, params.get("ValidCard"), hostCard.getController(), hostCard); - } - if (list.size() > 0) { - return; - } - } - } else if (params.get("Type").equals("Ability")) { - if (!(sa instanceof AbilityActivated)) { - return; - } - } else if (params.get("Type").equals("Buyback")) { - if (!sa.isBuyBackAbility()) { - return; - } - } else if (params.get("Type").equals("Cycling")) { - if (!sa.isCycling()) { - return; - } - } else if (params.get("Type").equals("Dash")) { - if (!sa.isDash()) { - return; - } - } else if (params.get("Type").equals("Equip")) { - if (!(sa instanceof AbilityActivated) || !sa.hasParam("Equip")) { - return; - } - } else if (params.get("Type").equals("Flashback")) { - if (!sa.isFlashBackAbility()) { - return; - } - } else if (params.get("Type").equals("MorphDown")) { - if (!sa.isSpell() || !((Spell) sa).isCastFaceDown()) { - return; - } - } else if (params.get("Type").equals("SelfMonstrosity")) { - if (!(sa instanceof AbilityActivated) || !sa.hasParam("Monstrosity") || sa.isTemporary()) { - // Nemesis of Mortals - return; - } - } - } - if (params.containsKey("ValidTarget")) { - TargetRestrictions tgt = sa.getTargetRestrictions(); - if (tgt == null) { - return; - } - boolean targetValid = false; - for (GameObject target : sa.getTargets().getTargets()) { - if (target.isValid(params.get("ValidTarget").split(","), hostCard.getController(), hostCard, sa)) { - targetValid = true; - } - } - if (!targetValid) { - return; - } - } - if (params.containsKey("AffectedZone") && !card.isInZone(ZoneType.smartValueOf(params.get("AffectedZone")))) { - return; - } - - int value; - if ("AffectedX".equals(amount)) { - value = CardFactoryUtil.xCount(card, hostCard.getSVar(amount)); - } else if ("X".equals(amount)){ - value = CardFactoryUtil.xCount(hostCard, hostCard.getSVar(amount)); - } else { - value = AbilityUtils.calculateAmount(hostCard, amount, sa); - } - - - if (!params.containsKey("Color")) { - int minMana = 0; - if (params.containsKey("MinMana")) { - minMana = Integer.valueOf(params.get("MinMana")); - } - - final int maxReduction = Math.max(0, manaCost.getConvertedManaCost() - minMana); - if (maxReduction > 0) { - manaCost.decreaseGenericMana(Math.min(value, maxReduction)); - } - } else { - final String color = params.get("Color"); - for (final String cost : color.split(" ")) { - if (StringUtils.isNumeric(cost)) { - manaCost.decreaseGenericMana(Integer.parseInt(cost) * value); - } else { - manaCost.decreaseShard(ManaCostShard.parseNonGeneric(cost), value); - } - } - } - } - -} \ No newline at end of file diff --git a/forge-gui/src/main/java/forge/player/HumanPlay.java b/forge-gui/src/main/java/forge/player/HumanPlay.java index c70af235e07..2ed48c50490 100644 --- a/forge-gui/src/main/java/forge/player/HumanPlay.java +++ b/forge-gui/src/main/java/forge/player/HumanPlay.java @@ -53,7 +53,6 @@ import forge.game.cost.CostReveal; import forge.game.cost.CostSacrifice; import forge.game.cost.CostTapType; import forge.game.cost.PaymentDecision; -import forge.game.mana.ManaCostAdjustment; import forge.game.mana.ManaCostBeingPaid; import forge.game.player.Player; import forge.game.player.PlayerView; @@ -175,7 +174,7 @@ public class HumanPlay { } else { manaCost = new ManaCostBeingPaid(sa.getPayCosts().getTotalMana()); - ManaCostAdjustment.adjust(manaCost, sa, null, false); + CostAdjustment.adjust(manaCost, sa, null, false); } boolean isPaid = manaCost.isPaid(); @@ -782,7 +781,7 @@ public class HumanPlay { CardCollection cardsToDelve = new CardCollection(); if (isActivatedSa) { - ManaCostAdjustment.adjust(toPay, ability, cardsToDelve, false); + CostAdjustment.adjust(toPay, ability, cardsToDelve, false); } Card offering = null;