mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 11:48:02 +00:00
GameAction.payCostDuringAbilityResolve now returns a boolean indicating whether the cost was paid,
all the paid/unpaid commands eliminated, since the code may be executed right after payCostDuringAbilityResolve under if's branches
This commit is contained in:
@@ -10,7 +10,6 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import forge.Card;
|
||||
import forge.CardLists;
|
||||
import forge.CardUtil;
|
||||
import forge.Command;
|
||||
import forge.Constant;
|
||||
import forge.CounterType;
|
||||
import forge.Singletons;
|
||||
@@ -1036,6 +1035,19 @@ public class AbilityUtils {
|
||||
AbilityUtils.resolveApiAbility(abSub, usedStack, game);
|
||||
}
|
||||
|
||||
private static void resolveApiAbility(final SpellAbility sa, boolean usedStack, final GameState game) {
|
||||
// check conditions
|
||||
if (sa.getConditions().areMet(sa)) {
|
||||
if (sa.isWrapper() || StringUtils.isBlank(sa.getParam("UnlessCost"))) {
|
||||
sa.resolve();
|
||||
} else {
|
||||
handleUnlessCost(sa, usedStack, game);
|
||||
return;
|
||||
}
|
||||
}
|
||||
resolveSubAbilities(sa, usedStack, game);
|
||||
}
|
||||
|
||||
private static void handleUnlessCost(final SpellAbility sa, final boolean usedStack, final GameState game) {
|
||||
final Card source = sa.getSourceCard();
|
||||
String unlessCost = sa.getParam("UnlessCost");
|
||||
@@ -1047,7 +1059,8 @@ public class AbilityUtils {
|
||||
final String resolveSubs = sa.getParam("UnlessResolveSubs"); // no value means 'Always'
|
||||
final boolean execSubsWhenPaid = "WhenPaid".equals(resolveSubs) || StringUtils.isBlank(resolveSubs);
|
||||
final boolean execSubsWhenNotPaid = "WhenNotPaid".equals(resolveSubs) || StringUtils.isBlank(resolveSubs);
|
||||
|
||||
final boolean isSwitched = sa.hasParam("UnlessSwitched");
|
||||
|
||||
// The cost
|
||||
if (unlessCost.equals("CardManaCost")) {
|
||||
unlessCost = source.getManaCost().toString();
|
||||
@@ -1070,43 +1083,6 @@ public class AbilityUtils {
|
||||
//instead of just X for cards like Draco.
|
||||
}
|
||||
|
||||
final boolean isSwitched = sa.hasParam("UnlessSwitched");
|
||||
|
||||
Command paidCommand = new Command() {
|
||||
private static final long serialVersionUID = 8094833091127334678L;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
if (isSwitched && execSubsWhenNotPaid || execSubsWhenPaid) {
|
||||
resolveSubAbilities(sa, usedStack, game);
|
||||
} else if (usedStack) {
|
||||
SpellAbility root = sa.getRootAbility();
|
||||
game.getStack().finishResolving(root, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Command unpaidCommand = new Command() {
|
||||
private static final long serialVersionUID = 8094833091127334678L;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
sa.resolve();
|
||||
if (isSwitched && execSubsWhenPaid || execSubsWhenNotPaid) {
|
||||
resolveSubAbilities(sa, usedStack, game);
|
||||
} else if (usedStack) {
|
||||
SpellAbility root = sa.getRootAbility();
|
||||
game.getStack().finishResolving(root, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (isSwitched) {
|
||||
final Command dummy = paidCommand;
|
||||
paidCommand = unpaidCommand;
|
||||
unpaidCommand = dummy;
|
||||
}
|
||||
|
||||
final Cost cost = new Cost(source, unlessCost, true);
|
||||
final Ability ability = new AbilityStatic(source, cost, null) {
|
||||
@Override
|
||||
@@ -1117,34 +1093,35 @@ public class AbilityUtils {
|
||||
|
||||
boolean paid = false;
|
||||
for (Player payer : payers) {
|
||||
ability.setActivatingPlayer(payer);
|
||||
ability.setTarget(sa.getTarget());
|
||||
if (payer.isComputer()) {
|
||||
ability.setActivatingPlayer(payer);
|
||||
if (AbilityUtils.willAIPayForAbility(sa, payer, ability, paid, payers)) {
|
||||
ability.setTarget(sa.getTarget());
|
||||
ComputerUtil.playNoStack((AIPlayer) payer, ability, game); // Unless cost was payed - no resolve
|
||||
paid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean waitForInput = false;
|
||||
for (Player payer : payers) {
|
||||
if (payer.isHuman()) {
|
||||
} else {
|
||||
// if it's paid by the AI already the human can pay, but it won't change anything
|
||||
if (paid) {
|
||||
unpaidCommand = paidCommand;
|
||||
}
|
||||
ability.setActivatingPlayer(payer);
|
||||
ability.setTarget(sa.getTarget());
|
||||
GameActionUtil.payCostDuringAbilityResolve(payer, ability, cost, paidCommand, unpaidCommand, sa, game);
|
||||
waitForInput = true; // wait for the human input
|
||||
break; // multiple human players are not supported
|
||||
paid = GameActionUtil.payCostDuringAbilityResolve(payer, ability, cost, sa, game);
|
||||
}
|
||||
}
|
||||
if (!waitForInput) {
|
||||
Command toExecute = paid ? paidCommand : unpaidCommand;
|
||||
toExecute.execute();
|
||||
}
|
||||
|
||||
if ( paid ^ isSwitched ) {
|
||||
if (isSwitched && execSubsWhenNotPaid || execSubsWhenPaid) {
|
||||
resolveSubAbilities(sa, usedStack, game);
|
||||
} else if (usedStack) {
|
||||
SpellAbility root = sa.getRootAbility();
|
||||
game.getStack().finishResolving(root, false);
|
||||
}
|
||||
} else {
|
||||
sa.resolve();
|
||||
if (isSwitched && execSubsWhenPaid || execSubsWhenNotPaid) {
|
||||
resolveSubAbilities(sa, usedStack, game);
|
||||
} else if (usedStack) {
|
||||
SpellAbility root = sa.getRootAbility();
|
||||
game.getStack().finishResolving(root, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1221,19 +1198,6 @@ public class AbilityUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void resolveApiAbility(final SpellAbility sa, boolean usedStack, final GameState game) {
|
||||
// check conditions
|
||||
if (sa.getConditions().areMet(sa)) {
|
||||
if (sa.isWrapper() || StringUtils.isBlank(sa.getParam("UnlessCost"))) {
|
||||
sa.resolve();
|
||||
} else {
|
||||
handleUnlessCost(sa, usedStack, game);
|
||||
return;
|
||||
}
|
||||
}
|
||||
resolveSubAbilities(sa, usedStack, game);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Parse non-mana X variables.
|
||||
|
||||
@@ -486,24 +486,6 @@ public class GameAction {
|
||||
final String recoverCost = recoverable.getKeyword().get(recoverable.getKeywordPosition("Recover")).split(":")[1];
|
||||
final Cost cost = new Cost(recoverable, recoverCost, true);
|
||||
|
||||
final Command paidCommand = new Command() {
|
||||
private static final long serialVersionUID = -6357156873861051845L;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
moveToHand(recoverable);
|
||||
}
|
||||
};
|
||||
|
||||
final Command unpaidCommand = new Command() {
|
||||
private static final long serialVersionUID = -7354791599039157375L;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
exile(recoverable);
|
||||
}
|
||||
};
|
||||
|
||||
final SpellAbility abRecover = new AbilityActivated(recoverable, cost, null) {
|
||||
private static final long serialVersionUID = 8858061639236920054L;
|
||||
|
||||
@@ -535,8 +517,10 @@ public class GameAction {
|
||||
Player p = recoverable.getController();
|
||||
|
||||
if (p.isHuman()) {
|
||||
GameActionUtil.payCostDuringAbilityResolve(p, abRecover, abRecover.getPayCosts(),
|
||||
paidCommand, unpaidCommand, null, game);
|
||||
if ( GameActionUtil.payCostDuringAbilityResolve(p, abRecover, abRecover.getPayCosts(), null, game) )
|
||||
moveToHand(recoverable);
|
||||
else
|
||||
exile(recoverable);
|
||||
} else { // computer
|
||||
if (ComputerUtilCost.canPayCost(abRecover, p)) {
|
||||
ComputerUtil.playNoStack((AIPlayer)p, abRecover, game);
|
||||
|
||||
@@ -382,8 +382,7 @@ public final class GameActionUtil {
|
||||
* a {@link forge.Command} object.
|
||||
* @param sourceAbility TODO
|
||||
*/
|
||||
public static void payCostDuringAbilityResolve(final Player p, final SpellAbility ability, final Cost cost, final Command paid,
|
||||
final Command unpaid, SpellAbility sourceAbility, final GameState game) {
|
||||
public static boolean payCostDuringAbilityResolve(final Player p, final SpellAbility ability, final Cost cost, SpellAbility sourceAbility, final GameState game) {
|
||||
final Card source = ability.getSourceCard();
|
||||
final List<CostPart> parts = cost.getCostParts();
|
||||
ArrayList<CostPart> remainingParts = new ArrayList<CostPart>(cost.getCostParts());
|
||||
@@ -396,13 +395,9 @@ public final class GameActionUtil {
|
||||
orString = " (or: " + sourceAbility.getStackDescription() + ")";
|
||||
}
|
||||
if (parts.isEmpty() || costPart.getAmount().equals("0")) {
|
||||
if (GuiDialog.confirm(source, "Do you want to pay 0?" + orString)) {
|
||||
paid.execute();
|
||||
} else {
|
||||
unpaid.execute();
|
||||
}
|
||||
return;
|
||||
return GuiDialog.confirm(source, "Do you want to pay 0?" + orString);
|
||||
}
|
||||
|
||||
boolean hasPaid = true;
|
||||
//the following costs do not need inputs
|
||||
for (CostPart part : parts) {
|
||||
@@ -591,12 +586,10 @@ public final class GameActionUtil {
|
||||
GuiUtils.clearPanelSelections();
|
||||
|
||||
if (!hasPaid) {
|
||||
unpaid.execute();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
if (remainingParts.isEmpty()) {
|
||||
paid.execute();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (remainingParts.size() > 1) {
|
||||
throw new RuntimeException("GameActionUtil::payCostDuringAbilityResolve - Too many payment types - " + source);
|
||||
@@ -609,11 +602,7 @@ public final class GameActionUtil {
|
||||
|
||||
InputPayment toSet = new InputPayManaExecuteCommands(game, source + "\r\n", ability.getManaCost());
|
||||
FThreads.setInputAndWait(toSet);
|
||||
if (toSet.isPaid() ) {
|
||||
paid.execute();
|
||||
} else {
|
||||
unpaid.execute();
|
||||
}
|
||||
return toSet.isPaid();
|
||||
}
|
||||
|
||||
// not restricted to combat damage, not restricted to dealing damage to
|
||||
|
||||
@@ -1150,39 +1150,13 @@ public class CombatUtil {
|
||||
}
|
||||
};
|
||||
|
||||
final Command unpaidCommand = new Command() {
|
||||
|
||||
private static final long serialVersionUID = -6483405139208343935L;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
game.getCombat().removeFromCombat(crd);
|
||||
|
||||
if (bLast) {
|
||||
PhaseUtil.handleAttackingTriggers();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
final Command paidCommand = new Command() {
|
||||
private static final long serialVersionUID = -8303368287601871955L;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
// if Propaganda is paid, tap this card
|
||||
if (!crd.hasKeyword("Vigilance")) {
|
||||
crd.tap();
|
||||
}
|
||||
|
||||
if (bLast) {
|
||||
PhaseUtil.handleAttackingTriggers();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ability.setActivatingPlayer(c.getController());
|
||||
if (c.getController().isHuman()) {
|
||||
GameActionUtil.payCostDuringAbilityResolve(c.getController(), ability, attackCost, paidCommand, unpaidCommand, null, game);
|
||||
if ( GameActionUtil.payCostDuringAbilityResolve(c.getController(), ability, attackCost, null, game) ) {
|
||||
if (!crd.hasKeyword("Vigilance")) { crd.tap(); }
|
||||
} else {
|
||||
game.getCombat().removeFromCombat(crd);
|
||||
}
|
||||
} else { // computer
|
||||
if (ComputerUtilCost.canPayCost(ability, c.getController())) {
|
||||
ComputerUtil.playNoStack((AIPlayer)c.getController(), ability, game);
|
||||
@@ -1194,10 +1168,9 @@ public class CombatUtil {
|
||||
// during Declare_Attackers
|
||||
game.getCombat().removeFromCombat(crd);
|
||||
}
|
||||
if (bLast) {
|
||||
PhaseUtil.handleAttackingTriggers();
|
||||
}
|
||||
}
|
||||
if (bLast)
|
||||
PhaseUtil.handleAttackingTriggers();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -175,18 +175,6 @@ public class Upkeep extends Phase {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
final Card c = list.get(i);
|
||||
if (c.hasStartOfKeyword("(Echo unpaid)")) {
|
||||
|
||||
final Command paidCommand = Command.BLANK;
|
||||
|
||||
final Command unpaidCommand = new Command() {
|
||||
private static final long serialVersionUID = -7354791599039157375L;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
game.getAction().sacrifice(c, null);
|
||||
}
|
||||
};
|
||||
|
||||
final Ability blankAbility = Upkeep.BlankAbility(c, c.getEchoCost());
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
@@ -199,7 +187,9 @@ public class Upkeep extends Phase {
|
||||
Player controller = c.getController();
|
||||
if (controller.isHuman()) {
|
||||
Cost cost = new Cost(c, c.getEchoCost().trim(), true);
|
||||
GameActionUtil.payCostDuringAbilityResolve(controller, blankAbility, cost, paidCommand, unpaidCommand, null, game);
|
||||
if ( !GameActionUtil.payCostDuringAbilityResolve(controller, blankAbility, cost, null, game) )
|
||||
game.getAction().sacrifice(c, null);;
|
||||
|
||||
} else { // computer
|
||||
if (ComputerUtilCost.canPayCost(blankAbility, controller)) {
|
||||
ComputerUtil.playNoStack((AIPlayer)controller, blankAbility, game);
|
||||
@@ -332,18 +322,6 @@ public class Upkeep extends Phase {
|
||||
}
|
||||
|
||||
final String upkeepCost = cost;
|
||||
|
||||
final Command unpaidCommand = new Command() {
|
||||
private static final long serialVersionUID = 5612348769167529102L;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
game.getAction().sacrifice(c, null);
|
||||
}
|
||||
};
|
||||
|
||||
final Command paidCommand = Command.BLANK;
|
||||
|
||||
final Ability blankAbility = Upkeep.BlankAbility(c, upkeepCost);
|
||||
blankAbility.setActivatingPlayer(controller);
|
||||
|
||||
@@ -351,11 +329,11 @@ public class Upkeep extends Phase {
|
||||
@Override
|
||||
public void resolve() {
|
||||
if (controller.isHuman()) {
|
||||
GameActionUtil.payCostDuringAbilityResolve(controller, blankAbility, blankAbility.getPayCosts(),
|
||||
paidCommand, unpaidCommand, this, game);
|
||||
if ( !GameActionUtil.payCostDuringAbilityResolve(controller, blankAbility, blankAbility.getPayCosts(), this, game))
|
||||
game.getAction().sacrifice(c, null);
|
||||
} else { // computer
|
||||
if (ComputerUtilCost.shouldPayCost(controller, c, upkeepCost) && ComputerUtilCost.canPayCost(blankAbility, controller)) {
|
||||
ComputerUtil.playNoStack((AIPlayer)controller, blankAbility, game);
|
||||
ComputerUtil.playNoStack((AIPlayer)controller, blankAbility, game); // this makes AI pay
|
||||
} else {
|
||||
game.getAction().sacrifice(c, null);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user