CostAdjustment does absorb ManaCostAdjustment

This commit is contained in:
Hanmac
2016-07-26 10:19:17 +00:00
parent bca2bbfe22
commit 1cf4bc02fd
5 changed files with 258 additions and 512 deletions

1
.gitattributes vendored
View File

@@ -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

View File

@@ -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)) {

View File

@@ -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<StaticAbility> reduceAbilities = new ArrayList<StaticAbility>();
final List<StaticAbility> setAbilities = new ArrayList<StaticAbility>();
// 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<Card, ManaCostShard> 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<Card, ManaCostShard> 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<String, String> 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<String, String> 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;
@@ -139,6 +380,15 @@ public class CostAdjustment {
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;
}
}

View File

@@ -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<StaticAbility> raiseAbilities = new ArrayList<StaticAbility>();
final List<StaticAbility> reduceAbilities = new ArrayList<StaticAbility>();
final List<StaticAbility> setAbilities = new ArrayList<StaticAbility>();
// Sort abilities to apply them in proper order
for (Card c : cardsOnBattlefield) {
final Iterable<StaticAbility> 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<Card, ManaCostShard> 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<Card, ManaCostShard> 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<String, String> 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<ZoneType> 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<String, String> 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);
}
}
}
}
}

View File

@@ -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;