Make it so X mana costs are paid using a pre-mana payment announcement

This commit is contained in:
drdev
2014-09-07 21:54:12 +00:00
parent 407bc67af9
commit e64de69a39
6 changed files with 40 additions and 217 deletions

View File

@@ -1,184 +0,0 @@
package forge.match.input;
import forge.ai.ComputerUtilMana;
import forge.card.ColorSet;
import forge.card.mana.ManaCost;
import forge.card.mana.ManaCostParser;
import forge.game.card.Card;
import forge.game.mana.Mana;
import forge.game.mana.ManaCostBeingPaid;
import forge.game.spellability.SpellAbility;
import forge.util.Evaluator;
import forge.util.ITriggerEvent;
import forge.util.ThreadUtil;
import forge.util.gui.SGuiChoose;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
public class InputPayManaX extends InputPayMana {
private static final long serialVersionUID = -6900234444347364050L;
private int xPaid = 0;
private ArrayList<Mana> xPaidByColor = new ArrayList<>();
private byte colorsPaid;
private final String xCostStr;
private final ManaCost manaCostPerX;
private final boolean xCanBe0;
private boolean canceled = false;
private Integer max;
public InputPayManaX(final SpellAbility sa0, final int amountX, final boolean xCanBe0) {
super(sa0, sa0.getActivatingPlayer());
xPaid = 0;
StringBuilder builder = new StringBuilder();
for (int i = 0; i < amountX; i++) {
builder.append("{X}");
}
xCostStr = builder.toString();
if (saPaidFor.hasParam("XColor")) {
String xColor = saPaidFor.getParam("XColor");
if (amountX == 1) {
manaCostPerX = new ManaCost(new ManaCostParser(xColor));
}
else {
List<String> list = new ArrayList<String>(amountX);
for (int i = 0; i < amountX; i++) {
list.add(xColor);
}
manaCostPerX = new ManaCost(new ManaCostParser(StringUtils.join(list, ' ')));
}
}
else {
manaCostPerX = ManaCost.get(amountX);
}
manaCost = new ManaCostBeingPaid(manaCostPerX);
this.xCanBe0 = xCanBe0;
colorsPaid = saPaidFor.getHostCard().getColorsPaid(); // for effects like sunburst
canPayManaCost = true; //flag as true always since it doesn't need to be calculated using AI logic
}
/* (non-Javadoc)
* @see forge.control.input.InputPayManaBase#isPaid()
*/
@Override
public boolean isPaid() {
//return !( xPaid == 0 && !costMana.canXbe0() || this.colorX.equals("") && !this.manaCost.toString().equals(strX) );
// return !( xPaid == 0 && !costMana.canXbe0()) && !(this.colorX.equals("") && !this.manaCost.toString().equals(strX));
return !canceled && (xPaid > 0 || xCanBe0);
}
@Override
protected boolean supportAutoPay() {
return xPaid == 0;
}
@Override
public void showMessage() {
if (isFinished()) { return; }
updateMessage();
}
@Override
protected String getMessage() {
StringBuilder msg = new StringBuilder("Pay " + xCostStr + ". X=" + xPaid + ".");
if (xPaid > 0) {
// Enable just cancel is full X value hasn't been paid for multiple X values
// or X is 0, and x can't be 0
ButtonUtil.update(isPaid(), true, true);
}
if (!xCanBe0) {
msg.append("\nX Can't be 0.");
}
return msg.toString();
}
@Override
protected boolean onCardSelected(final Card card, final ITriggerEvent triggerEvent) {
// don't allow here the cards that produce only wrong colors
return activateManaAbility(card, this.manaCost);
}
@Override
protected void onManaAbilityPaid() {
if (this.manaCost.isPaid()) {
this.colorsPaid |= manaCost.getColorsPaid();
this.manaCost = new ManaCostBeingPaid(manaCostPerX);
this.xPaid++;
this.xPaidByColor.add(saPaidFor.getPayingMana().get(0));
}
}
@Override
protected final void onCancel() {
// If you hit cancel, isPaid needs to return false
this.canceled = true;
this.stop();
}
@Override
protected final void onOk() {
if (supportAutoPay()) {
ThreadUtil.invokeInGameThread(new Runnable() {
@Override
public void run() {
int min = xCanBe0 ? 0 : 1;
if (max == null) {
//use AI utility to determine maximum possible value for X if that hasn't been determined yet
Evaluator<Integer> proc = new Evaluator<Integer>() {
@Override
public Integer evaluate() {
ManaCostBeingPaid cost = new ManaCostBeingPaid(manaCostPerX);
for (int i = 1; i < 100; i++) {
if (!ComputerUtilMana.canPayManaCost(cost, saPaidFor, player)) {
return i - 1;
}
cost.addManaCost(manaCostPerX);
}
return 99;
}
};
runAsAi(proc);
max = proc.getResult();
}
Integer value = SGuiChoose.getInteger("Choose a value for X", min, max, true);
if (value != null) {
xPaid = value;
saPaidFor.getHostCard().setXManaCostPaid(xPaid);
if (xPaid > 0) {
final ManaCostBeingPaid cost = new ManaCostBeingPaid(manaCostPerX);
for (int i = 1; i < xPaid; i++) {
cost.addManaCost(manaCostPerX);
}
runAsAi(new Runnable() {
@Override
public void run() {
ComputerUtilMana.payManaCost(cost, saPaidFor, player);
}
});
}
stop();
}
}
});
}
else {
done();
stop();
}
}
@Override
protected void done() {
final Card card = saPaidFor.getHostCard();
card.setXManaCostPaid(this.xPaid);
card.setXManaCostPaidByColor(this.xPaidByColor);
card.setColorsPaid(this.colorsPaid);
card.setSunburstValue(ColorSet.fromMask(this.colorsPaid).countColors());
}
}

View File

@@ -4,9 +4,7 @@ import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import forge.FThreads;
import forge.card.MagicColor;
import forge.card.mana.ManaCost;
import forge.card.mana.ManaCostShard;
import forge.game.Game;
import forge.game.GameActionUtil;
import forge.game.GameLogEntryType;
@@ -27,7 +25,6 @@ import forge.game.zone.ZoneType;
import forge.match.input.InputPayMana;
import forge.match.input.InputPayManaOfCostPayment;
import forge.match.input.InputPayManaSimple;
import forge.match.input.InputPayManaX;
import forge.match.input.InputSelectCardsFromList;
import forge.util.Lang;
import forge.util.gui.SGuiChoose;
@@ -42,7 +39,6 @@ import java.util.Map;
public class HumanPlay {
public HumanPlay() {
// TODO Auto-generated constructor stub
}
/**
@@ -694,14 +690,12 @@ public class HumanPlay {
final Card source = ability.getHostCard();
ManaCostBeingPaid toPay = new ManaCostBeingPaid(realCost, mc.getRestiction());
boolean xWasBilled = false;
String xInCard = source.getSVar("X");
if (mc.getAmountOfX() > 0 && !"Count$xPaid".equals(xInCard)) { // announce X will overwrite whatever was in card script
// this currently only works for things about Targeted object
int xCost = AbilityUtils.calculateAmount(source, "X", ability) * mc.getAmountOfX();
byte xColor = MagicColor.fromName(ability.hasParam("XColor") ? ability.getParam("XColor") : "1");
toPay.increaseShard(ManaCostShard.valueOf(xColor), xCost);
xWasBilled = true;
int xPaid = AbilityUtils.calculateAmount(source, "X", ability);
toPay.setXManaCostPaid(xPaid, ability.getParam("XColor"));
source.setXManaCostPaid(xPaid);
}
int timesMultikicked = source.getKickerMagnitude();
@@ -740,19 +734,6 @@ public class HumanPlay {
source.setColorsPaid(toPay.getColorsPaid());
source.setSunburstValue(toPay.getSunburst());
}
if (mc.getAmountOfX() > 0) {
if (!ability.isAnnouncing("X") && !xWasBilled) {
source.setXManaCostPaid(0);
inpPayment = new InputPayManaX(ability, mc.getAmountOfX(), mc.canXbe0());
inpPayment.showAndWait();
if (!inpPayment.isPaid()) {
return false;
}
} else {
int x = AbilityUtils.calculateAmount(source, "X", ability);
source.setXManaCostPaid(x);
}
}
// Handle convoke and offerings
if (ability.isOffering() && ability.getSacrificedAsOffering() != null) {

View File

@@ -195,20 +195,22 @@ public class HumanPlaySpellAbility {
private boolean announceValuesLikeX() {
if (ability.isCopied()) { return true; } //don't re-announce for spell copies
boolean needX = true;
boolean allowZero = !ability.hasParam("XCantBe0");
CostPartMana manaCost = ability.getPayCosts().getCostMana();
PlayerController controller = ability.getActivatingPlayer().getController();
Card card = ability.getHostCard();
// Announcing Requirements like Choosing X or Multikicker
// SA Params as comma delimited list
String announce = ability.getParam("Announce");
if (announce != null) {
PlayerController controller = ability.getActivatingPlayer().getController();
Card card = ability.getHostCard();
boolean allowZero = !ability.hasParam("XCantBe0");
CostPartMana manaCost = ability.getPayCosts().getCostMana();
for (String aVar : announce.split(",")) {
String varName = aVar.trim();
boolean isX = "X".equalsIgnoreCase(varName);
if (isX) { needX = false; }
Integer value = controller.announceRequirements(ability, varName, allowZero && (!isX || manaCost == null || manaCost.canXbe0()));
if (value == null) {
@@ -224,6 +226,16 @@ public class HumanPlaySpellAbility {
}
}
}
if (needX && manaCost != null && manaCost.getAmountOfX() > 0) {
Integer value = controller.announceRequirements(ability, "X", allowZero && manaCost.canXbe0());
if (value == null) {
return false;
}
ability.setSVar("X", value.toString());
card.setSVar("X", value.toString());
}
return true;
}