mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 03:38:01 +00:00
fix incorrect mana bills for human (eg: ai plays Mana Leak, with Goblin Electromancer in play)
This commit is contained in:
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -491,6 +491,7 @@ forge-game/src/main/java/forge/game/event/GameEventZone.java -text
|
|||||||
forge-game/src/main/java/forge/game/event/IGameEventVisitor.java -text
|
forge-game/src/main/java/forge/game/event/IGameEventVisitor.java -text
|
||||||
forge-game/src/main/java/forge/game/event/package-info.java -text
|
forge-game/src/main/java/forge/game/event/package-info.java -text
|
||||||
forge-game/src/main/java/forge/game/mana/Mana.java svneol=native#text/plain
|
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/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/ManaPool.java svneol=native#text/plain
|
||||||
forge-game/src/main/java/forge/game/mana/package-info.java svneol=native#text/plain
|
forge-game/src/main/java/forge/game/mana/package-info.java svneol=native#text/plain
|
||||||
@@ -554,7 +555,6 @@ forge-game/src/main/java/forge/game/staticability/StaticAbilityCantAttackBlock.j
|
|||||||
forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java svneol=native#text/plain
|
forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java svneol=native#text/plain
|
||||||
forge-game/src/main/java/forge/game/staticability/StaticAbilityCantTarget.java -text
|
forge-game/src/main/java/forge/game/staticability/StaticAbilityCantTarget.java -text
|
||||||
forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java svneol=native#text/plain
|
forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java svneol=native#text/plain
|
||||||
forge-game/src/main/java/forge/game/staticability/StaticAbilityCostChange.java -text
|
|
||||||
forge-game/src/main/java/forge/game/staticability/StaticAbilityETBTapped.java -text
|
forge-game/src/main/java/forge/game/staticability/StaticAbilityETBTapped.java -text
|
||||||
forge-game/src/main/java/forge/game/staticability/StaticAbilityMayLookAt.java -text
|
forge-game/src/main/java/forge/game/staticability/StaticAbilityMayLookAt.java -text
|
||||||
forge-game/src/main/java/forge/game/staticability/StaticAbilityPreventDamage.java svneol=native#text/plain
|
forge-game/src/main/java/forge/game/staticability/StaticAbilityPreventDamage.java svneol=native#text/plain
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import forge.game.cost.Cost;
|
|||||||
import forge.game.cost.CostPartMana;
|
import forge.game.cost.CostPartMana;
|
||||||
import forge.game.cost.CostPayment;
|
import forge.game.cost.CostPayment;
|
||||||
import forge.game.mana.Mana;
|
import forge.game.mana.Mana;
|
||||||
|
import forge.game.mana.ManaCostAdjustment;
|
||||||
import forge.game.mana.ManaCostBeingPaid;
|
import forge.game.mana.ManaCostBeingPaid;
|
||||||
import forge.game.mana.ManaPool;
|
import forge.game.mana.ManaPool;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
@@ -633,7 +634,7 @@ public class ComputerUtilMana {
|
|||||||
restriction = payCosts.getCostMana().getRestiction();
|
restriction = payCosts.getCostMana().getRestiction();
|
||||||
}
|
}
|
||||||
ManaCostBeingPaid cost = new ManaCostBeingPaid(mana, restriction);
|
ManaCostBeingPaid cost = new ManaCostBeingPaid(mana, restriction);
|
||||||
cost.applySpellCostChange(sa, test);
|
ManaCostAdjustment.adjust(cost, sa, test);
|
||||||
|
|
||||||
final Card card = sa.getHostCard();
|
final Card card = sa.getHostCard();
|
||||||
// Tack xMana Payments into mana here if X is a set value
|
// Tack xMana Payments into mana here if X is a set value
|
||||||
|
|||||||
@@ -717,9 +717,9 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean payManaCost(ManaCost toPay, CostPartMana costPartMana, SpellAbility sa, String prompt /* ai needs hints as well */ ) {
|
public boolean payManaCost(ManaCost toPay, CostPartMana costPartMana, SpellAbility sa, String prompt /* ai needs hints as well */, boolean isActivatedSa ) {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
ManaCostBeingPaid cost = ComputerUtilMana.calculateManaCost(sa, false, 0);
|
ManaCostBeingPaid cost = isActivatedSa ? ComputerUtilMana.calculateManaCost(sa, false, 0) : new ManaCostBeingPaid(toPay);
|
||||||
return ComputerUtilMana.payManaCost(cost, sa, player);
|
return ComputerUtilMana.payManaCost(cost, sa, player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ public class CostPartMana extends CostPart {
|
|||||||
sa.clearManaPaid();
|
sa.clearManaPaid();
|
||||||
|
|
||||||
// decision not used here, the whole payment is interactive!
|
// decision not used here, the whole payment is interactive!
|
||||||
return payer.getController().payManaCost(this, sa, null);
|
return payer.getController().payManaCost(this, sa, null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,41 +1,182 @@
|
|||||||
/*
|
package forge.game.mana;
|
||||||
* Forge: Play Magic: the Gathering.
|
|
||||||
* Copyright (C) 2011 Forge Team
|
import java.util.ArrayList;
|
||||||
*
|
import java.util.List;
|
||||||
* This program is free software: you can redistribute it and/or modify
|
import java.util.Map;
|
||||||
* it under the terms of the GNU General Public License as published by
|
import java.util.Map.Entry;
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
import com.google.common.collect.Lists;
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package forge.game.staticability;
|
|
||||||
|
|
||||||
import forge.card.mana.ManaCostShard;
|
import forge.card.mana.ManaCostShard;
|
||||||
|
import forge.game.Game;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardFactoryUtil;
|
import forge.game.card.CardFactoryUtil;
|
||||||
import forge.game.mana.ManaCostBeingPaid;
|
import forge.game.card.CardLists;
|
||||||
|
import forge.game.card.CardPredicates;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.AbilityActivated;
|
import forge.game.spellability.AbilityActivated;
|
||||||
import forge.game.spellability.Spell;
|
import forge.game.spellability.Spell;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.spellability.TargetRestrictions;
|
import forge.game.spellability.TargetRestrictions;
|
||||||
|
import forge.game.staticability.StaticAbility;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
|
|
||||||
import java.util.List;
|
public class ManaCostAdjustment {
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
public static final void adjust(ManaCostBeingPaid cost, final SpellAbility sa, boolean test) {
|
||||||
* The Class StaticAbility_CantBeCast.
|
final Game game = sa.getActivatingPlayer().getGame();
|
||||||
*/
|
// Beached
|
||||||
public class StaticAbilityCostChange {
|
final Card originalCard = sa.getHostCard();
|
||||||
|
if (sa.isXCost() && !originalCard.isCopiedSpell()) {
|
||||||
|
originalCard.setXManaCostPaid(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sa.isTrigger()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sa.isSpell()) {
|
||||||
|
if (sa.isDelve()) {
|
||||||
|
final Player pc = originalCard.getController();
|
||||||
|
final List<Card> mutableGrave = new ArrayList<Card>(pc.getCardsIn(ZoneType.Graveyard));
|
||||||
|
final List<Card> toExile = pc.getController().chooseCardsToDelve(cost.getColorlessManaAmount(), mutableGrave);
|
||||||
|
for (final Card c : toExile) {
|
||||||
|
cost.decreaseColorlessMana(1);
|
||||||
|
if (!test) {
|
||||||
|
pc.getGame().getAction().exile(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (sa.getHostCard().hasKeyword("Convoke")) {
|
||||||
|
adjustCostByConvoke(cost, sa);
|
||||||
|
}
|
||||||
|
} // isSpell
|
||||||
|
|
||||||
|
List<Card> cardsOnBattlefield = Lists.newArrayList(game.getCardsIn(ZoneType.Battlefield));
|
||||||
|
cardsOnBattlefield.addAll(game.getCardsIn(ZoneType.Stack));
|
||||||
|
cardsOnBattlefield.addAll(game.getCardsIn(ZoneType.Command));
|
||||||
|
if (!cardsOnBattlefield.contains(originalCard)) {
|
||||||
|
cardsOnBattlefield.add(originalCard);
|
||||||
|
}
|
||||||
|
final ArrayList<StaticAbility> raiseAbilities = new ArrayList<StaticAbility>();
|
||||||
|
final ArrayList<StaticAbility> reduceAbilities = new ArrayList<StaticAbility>();
|
||||||
|
final ArrayList<StaticAbility> setAbilities = new ArrayList<StaticAbility>();
|
||||||
|
|
||||||
|
// Sort abilities to apply them in proper order
|
||||||
|
for (Card c : cardsOnBattlefield) {
|
||||||
|
final ArrayList<StaticAbility> staticAbilities = c.getStaticAbilities();
|
||||||
|
for (final StaticAbility stAb : staticAbilities) {
|
||||||
|
if (stAb.getMapParams().get("Mode").equals("RaiseCost")) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set cost (only used by Trinisphere) is applied last
|
||||||
|
for (final StaticAbility stAb : setAbilities) {
|
||||||
|
applyAbility(stAb, "SetCost", sa, cost);
|
||||||
|
}
|
||||||
|
} // 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) {
|
||||||
|
|
||||||
|
List<Card> 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);
|
||||||
|
conv.getKey().setTapped(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void adjustCostByOffering(final ManaCostBeingPaid cost, final SpellAbility sa) {
|
||||||
|
String offeringType = "";
|
||||||
|
for (String kw : sa.getHostCard().getKeyword()) {
|
||||||
|
if (kw.endsWith(" offering")) {
|
||||||
|
offeringType = kw.split(" ")[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Card toSac = null;
|
||||||
|
List<Card> canOffer = CardLists.filter(sa.getActivatingPlayer().getCardsIn(ZoneType.Battlefield),
|
||||||
|
CardPredicates.isType(offeringType));
|
||||||
|
|
||||||
|
final List<Card> toSacList = sa.getHostCard().getController().getController().choosePermanentsToSacrifice(sa, 0, 1, canOffer,
|
||||||
|
offeringType);
|
||||||
|
|
||||||
|
if (!toSacList.isEmpty()) {
|
||||||
|
toSac = toSacList.get(0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cost.subtractManaCost(toSac.getManaCost());
|
||||||
|
|
||||||
|
sa.setSacrificedAsOffering(toSac);
|
||||||
|
toSac.setUsedToPay(true); //stop it from interfering with mana input
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies applyRaiseCostAbility ability.
|
* Applies applyRaiseCostAbility ability.
|
||||||
*
|
*
|
||||||
@@ -46,7 +187,7 @@ public class StaticAbilityCostChange {
|
|||||||
* @param originalCost
|
* @param originalCost
|
||||||
* a ManaCost
|
* a ManaCost
|
||||||
*/
|
*/
|
||||||
public static void applyRaiseCostAbility(final StaticAbility staticAbility, final SpellAbility sa, final ManaCostBeingPaid manaCost) {
|
private static void applyRaiseCostAbility(final StaticAbility staticAbility, final SpellAbility sa, final ManaCostBeingPaid manaCost) {
|
||||||
final Map<String, String> params = staticAbility.getMapParams();
|
final Map<String, String> params = staticAbility.getMapParams();
|
||||||
final Card hostCard = staticAbility.getHostCard();
|
final Card hostCard = staticAbility.getHostCard();
|
||||||
final Player activator = sa.getActivatingPlayer();
|
final Player activator = sa.getActivatingPlayer();
|
||||||
@@ -193,7 +334,7 @@ public class StaticAbilityCostChange {
|
|||||||
* @param originalCost
|
* @param originalCost
|
||||||
* a ManaCost
|
* a ManaCost
|
||||||
*/
|
*/
|
||||||
public static void applyReduceCostAbility(final StaticAbility staticAbility, final SpellAbility sa, final ManaCostBeingPaid manaCost) {
|
private static void applyReduceCostAbility(final StaticAbility staticAbility, final SpellAbility sa, final ManaCostBeingPaid manaCost) {
|
||||||
//Can't reduce zero cost
|
//Can't reduce zero cost
|
||||||
if (manaCost.toString().equals("{0}")) {
|
if (manaCost.toString().equals("{0}")) {
|
||||||
return;
|
return;
|
||||||
@@ -292,5 +433,6 @@ public class StaticAbilityCostChange {
|
|||||||
manaCost.decreaseShard(ManaCostShard.GREEN, value);
|
manaCost.decreaseShard(ManaCostShard.GREEN, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
@@ -19,20 +19,12 @@ package forge.game.mana;
|
|||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import forge.card.ColorSet;
|
import forge.card.ColorSet;
|
||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
import forge.card.mana.IParserManaCost;
|
import forge.card.mana.IParserManaCost;
|
||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.card.mana.ManaCostShard;
|
import forge.card.mana.ManaCostShard;
|
||||||
import forge.game.Game;
|
|
||||||
import forge.game.card.Card;
|
|
||||||
import forge.game.card.CardLists;
|
|
||||||
import forge.game.card.CardPredicates;
|
|
||||||
import forge.game.player.Player;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
|
||||||
import forge.game.staticability.StaticAbility;
|
|
||||||
import forge.game.zone.ZoneType;
|
|
||||||
import forge.util.maps.EnumMapToAmount;
|
import forge.util.maps.EnumMapToAmount;
|
||||||
import forge.util.maps.MapToAmount;
|
import forge.util.maps.MapToAmount;
|
||||||
|
|
||||||
@@ -488,128 +480,6 @@ public class ManaCostBeingPaid {
|
|||||||
unpaidShards.remove(ManaCostShard.COLORLESS);
|
unpaidShards.remove(ManaCostShard.COLORLESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void applySpellCostChange(final SpellAbility sa, boolean test) {
|
|
||||||
final Game game = sa.getActivatingPlayer().getGame();
|
|
||||||
// Beached
|
|
||||||
final Card originalCard = sa.getHostCard();
|
|
||||||
final SpellAbility spell = sa;
|
|
||||||
|
|
||||||
if (sa.isXCost() && !originalCard.isCopiedSpell()) {
|
|
||||||
originalCard.setXManaCostPaid(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sa.isTrigger()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spell.isSpell()) {
|
|
||||||
if (spell.isDelve()) {
|
|
||||||
final Player pc = originalCard.getController();
|
|
||||||
final List<Card> mutableGrave = new ArrayList<Card>(pc.getCardsIn(ZoneType.Graveyard));
|
|
||||||
final List<Card> toExile = pc.getController().chooseCardsToDelve(this.getColorlessManaAmount(), mutableGrave);
|
|
||||||
for (final Card c : toExile) {
|
|
||||||
decreaseColorlessMana(1);
|
|
||||||
if (!test) {
|
|
||||||
pc.getGame().getAction().exile(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (spell.getHostCard().hasKeyword("Convoke")) {
|
|
||||||
adjustCostByConvoke(sa);
|
|
||||||
}
|
|
||||||
} // isSpell
|
|
||||||
|
|
||||||
List<Card> cardsOnBattlefield = Lists.newArrayList(game.getCardsIn(ZoneType.Battlefield));
|
|
||||||
cardsOnBattlefield.addAll(game.getCardsIn(ZoneType.Stack));
|
|
||||||
cardsOnBattlefield.addAll(game.getCardsIn(ZoneType.Command));
|
|
||||||
if (!cardsOnBattlefield.contains(originalCard)) {
|
|
||||||
cardsOnBattlefield.add(originalCard);
|
|
||||||
}
|
|
||||||
final ArrayList<StaticAbility> raiseAbilities = new ArrayList<StaticAbility>();
|
|
||||||
final ArrayList<StaticAbility> reduceAbilities = new ArrayList<StaticAbility>();
|
|
||||||
final ArrayList<StaticAbility> setAbilities = new ArrayList<StaticAbility>();
|
|
||||||
|
|
||||||
// Sort abilities to apply them in proper order
|
|
||||||
for (Card c : cardsOnBattlefield) {
|
|
||||||
final ArrayList<StaticAbility> staticAbilities = c.getStaticAbilities();
|
|
||||||
for (final StaticAbility stAb : staticAbilities) {
|
|
||||||
if (stAb.getMapParams().get("Mode").equals("RaiseCost")) {
|
|
||||||
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) {
|
|
||||||
stAb.applyAbility("RaiseCost", spell, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reduce cost
|
|
||||||
for (final StaticAbility stAb : reduceAbilities) {
|
|
||||||
stAb.applyAbility("ReduceCost", spell, this);
|
|
||||||
}
|
|
||||||
if (spell.isSpell() && spell.isOffering()) { // cost reduction from offerings
|
|
||||||
adjustCostByOffering(sa, spell);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set cost (only used by Trinisphere) is applied last
|
|
||||||
for (final StaticAbility stAb : setAbilities) {
|
|
||||||
stAb.applyAbility("SetCost", spell, this);
|
|
||||||
}
|
|
||||||
} // GetSpellCostChange
|
|
||||||
|
|
||||||
private void adjustCostByConvoke(final SpellAbility sa) {
|
|
||||||
|
|
||||||
List<Card> 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, this.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());
|
|
||||||
this.decreaseShard(conv.getValue(), 1);
|
|
||||||
conv.getKey().setTapped(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void adjustCostByOffering(final SpellAbility sa, final SpellAbility spell) {
|
|
||||||
String offeringType = "";
|
|
||||||
for (String kw : sa.getHostCard().getKeyword()) {
|
|
||||||
if (kw.endsWith(" offering")) {
|
|
||||||
offeringType = kw.split(" ")[0];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Card toSac = null;
|
|
||||||
List<Card> canOffer = CardLists.filter(spell.getActivatingPlayer().getCardsIn(ZoneType.Battlefield),
|
|
||||||
CardPredicates.isType(offeringType));
|
|
||||||
|
|
||||||
final List<Card> toSacList = sa.getHostCard().getController().getController().choosePermanentsToSacrifice(spell, 0, 1, canOffer,
|
|
||||||
offeringType);
|
|
||||||
|
|
||||||
if (!toSacList.isEmpty()) {
|
|
||||||
toSac = toSacList.get(0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
subtractManaCost(toSac.getManaCost());
|
|
||||||
|
|
||||||
sa.setSacrificedAsOffering(toSac);
|
|
||||||
toSac.setUsedToPay(true); //stop it from interfering with mana input
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSourceRestriction() {
|
public String getSourceRestriction() {
|
||||||
return sourceRestriction;
|
return sourceRestriction;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -222,10 +222,10 @@ public abstract class PlayerController {
|
|||||||
public List<Card> cheatShuffle(List<Card> list) { return list; }
|
public List<Card> cheatShuffle(List<Card> list) { return list; }
|
||||||
public Collection<? extends PaperCard> complainCardsCantPlayWell(Deck myDeck) { return null; }
|
public Collection<? extends PaperCard> complainCardsCantPlayWell(Deck myDeck) { return null; }
|
||||||
|
|
||||||
public final boolean payManaCost(CostPartMana costPartMana, SpellAbility sa, String prompt) {
|
public final boolean payManaCost(CostPartMana costPartMana, SpellAbility sa, String prompt, boolean isActivatedAbility) {
|
||||||
return payManaCost(costPartMana.getManaCostFor(sa), costPartMana, sa, prompt);
|
return payManaCost(costPartMana.getManaCostFor(sa), costPartMana, sa, prompt, isActivatedAbility);
|
||||||
}
|
}
|
||||||
public abstract boolean payManaCost(ManaCost toPay, CostPartMana costPartMana, SpellAbility sa, String prompt);
|
public abstract boolean payManaCost(ManaCost toPay, CostPartMana costPartMana, SpellAbility sa, String prompt, boolean isActivatedAbility);
|
||||||
|
|
||||||
public abstract Map<Card, ManaCostShard> chooseCardsForConvoke(SpellAbility sa, ManaCost manaCost, List<Card> untappedCreats);
|
public abstract Map<Card, ManaCostShard> chooseCardsForConvoke(SpellAbility sa, ManaCost manaCost, List<Card> untappedCreats);
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import forge.game.GameEntity;
|
|||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
import forge.game.mana.ManaCostBeingPaid;
|
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
@@ -324,38 +323,6 @@ public class StaticAbility extends CardTraitBase {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply ability.
|
|
||||||
*
|
|
||||||
* @param mode
|
|
||||||
* the mode
|
|
||||||
* @param sa
|
|
||||||
* the SpellAbility
|
|
||||||
* @param originalCost
|
|
||||||
* the originalCost
|
|
||||||
* @return the modified ManaCost
|
|
||||||
*/
|
|
||||||
public final void applyAbility(final String mode, final SpellAbility sa, final ManaCostBeingPaid originalCost) {
|
|
||||||
|
|
||||||
// don't apply the ability if it hasn't got the right mode
|
|
||||||
if (!this.mapParams.get("Mode").equals(mode)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isSuppressed() || !this.checkConditions()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode.equals("RaiseCost")) {
|
|
||||||
StaticAbilityCostChange.applyRaiseCostAbility(this, sa, originalCost);
|
|
||||||
}
|
|
||||||
if (mode.equals("ReduceCost")) {
|
|
||||||
StaticAbilityCostChange.applyReduceCostAbility(this, sa, originalCost);
|
|
||||||
}
|
|
||||||
if (mode.equals("SetCost")) { //Set cost is only used by Trinisphere
|
|
||||||
StaticAbilityCostChange.applyRaiseCostAbility(this, sa, originalCost);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply ability.
|
* Apply ability.
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package forge.gui.player;
|
package forge.gui.player;
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
|
|
||||||
import forge.FThreads;
|
import forge.FThreads;
|
||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
@@ -15,6 +16,7 @@ import forge.game.ability.effects.FlipCoinEffect;
|
|||||||
import forge.game.card.*;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardPredicates.Presets;
|
import forge.game.card.CardPredicates.Presets;
|
||||||
import forge.game.cost.*;
|
import forge.game.cost.*;
|
||||||
|
import forge.game.mana.ManaCostAdjustment;
|
||||||
import forge.game.mana.ManaCostBeingPaid;
|
import forge.game.mana.ManaCostBeingPaid;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.Ability;
|
import forge.game.spellability.Ability;
|
||||||
@@ -24,6 +26,7 @@ import forge.game.zone.ZoneType;
|
|||||||
import forge.gui.GuiChoose;
|
import forge.gui.GuiChoose;
|
||||||
import forge.gui.input.*;
|
import forge.gui.input.*;
|
||||||
import forge.util.Lang;
|
import forge.util.Lang;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -124,7 +127,7 @@ public class HumanPlay {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
manaCost = new ManaCostBeingPaid(sa.getPayCosts().getTotalMana());
|
manaCost = new ManaCostBeingPaid(sa.getPayCosts().getTotalMana());
|
||||||
manaCost.applySpellCostChange(sa, false);
|
ManaCostAdjustment.adjust(manaCost, sa, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isPaid = manaCost.isPaid();
|
boolean isPaid = manaCost.isPaid();
|
||||||
@@ -627,8 +630,9 @@ public class HumanPlay {
|
|||||||
prompt = source + "\n" + promptCurrent;
|
prompt = source + "\n" + promptCurrent;
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceAbility.clearManaPaid();
|
if( sourceAbility != null )
|
||||||
boolean paid = p.getController().payManaCost(cost.getCostMana(), sourceAbility, prompt);
|
sourceAbility.clearManaPaid();
|
||||||
|
boolean paid = p.getController().payManaCost(cost.getCostMana(), sourceAbility, prompt, false);
|
||||||
if (!paid) {
|
if (!paid) {
|
||||||
p.getManaPool().refundManaPaid(sourceAbility);
|
p.getManaPool().refundManaPaid(sourceAbility);
|
||||||
}
|
}
|
||||||
@@ -679,7 +683,7 @@ public class HumanPlay {
|
|||||||
return done;
|
return done;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean payManaCost(final ManaCost realCost, final CostPartMana mc, final SpellAbility ability, final Player activator, String prompt) {
|
public static boolean payManaCost(final ManaCost realCost, final CostPartMana mc, final SpellAbility ability, final Player activator, String prompt, boolean isActivatedSa) {
|
||||||
final Card source = ability.getHostCard();
|
final Card source = ability.getHostCard();
|
||||||
ManaCostBeingPaid toPay = new ManaCostBeingPaid(realCost, mc.getRestiction());
|
ManaCostBeingPaid toPay = new ManaCostBeingPaid(realCost, mc.getRestiction());
|
||||||
|
|
||||||
@@ -699,8 +703,8 @@ public class HumanPlay {
|
|||||||
toPay.addManaCost(mkCost);
|
toPay.addManaCost(mkCost);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( isActivatedSa )
|
||||||
toPay.applySpellCostChange(ability, false);
|
ManaCostAdjustment.adjust(toPay, ability, false);
|
||||||
|
|
||||||
InputPayMana inpPayment;
|
InputPayMana inpPayment;
|
||||||
if (ability.isOffering() && ability.getSacrificedAsOffering() == null) {
|
if (ability.isOffering() && ability.getSacrificedAsOffering() == null) {
|
||||||
|
|||||||
@@ -957,8 +957,7 @@ public class PlayerControllerHuman extends PlayerController {
|
|||||||
@Override
|
@Override
|
||||||
public boolean payCostToPreventEffect(Cost cost, SpellAbility sa, boolean alreadyPaid, List<Player> allPayers) {
|
public boolean payCostToPreventEffect(Cost cost, SpellAbility sa, boolean alreadyPaid, List<Player> allPayers) {
|
||||||
// if it's paid by the AI already the human can pay, but it won't change anything
|
// if it's paid by the AI already the human can pay, but it won't change anything
|
||||||
final Card source = sa.getHostCard();
|
return HumanPlay.payCostDuringAbilityResolve(player, sa.getHostCard(), cost, sa, null);
|
||||||
return HumanPlay.payCostDuringAbilityResolve(player, source, cost, sa, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1062,8 +1061,8 @@ public class PlayerControllerHuman extends PlayerController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean payManaCost(ManaCost toPay, CostPartMana costPartMana, SpellAbility sa, String prompt /* ai needs hints as well */ ) {
|
public boolean payManaCost(ManaCost toPay, CostPartMana costPartMana, SpellAbility sa, String prompt, boolean isActivatedSa) {
|
||||||
return HumanPlay.payManaCost(toPay, costPartMana, sa, player, prompt);
|
return HumanPlay.payManaCost(toPay, costPartMana, sa, player, prompt, isActivatedSa);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -566,9 +566,10 @@ public class PlayerControllerForTests extends PlayerController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean payManaCost(ManaCost toPay, CostPartMana costPartMana, SpellAbility sa, String prompt /* ai needs hints as well */ ) {
|
public boolean payManaCost(ManaCost toPay, CostPartMana costPartMana, SpellAbility sa, String prompt /* ai needs hints as well */, boolean isActivatedSa ) {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
return ComputerUtilMana.payManaCost(new ManaCostBeingPaid(toPay), sa, player);
|
ManaCostBeingPaid cost = new ManaCostBeingPaid(toPay);
|
||||||
|
return ComputerUtilMana.payManaCost(cost, sa, player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user