mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 19:58:00 +00:00
All cost-paying inputs are syncronous
This commit is contained in:
@@ -7675,6 +7675,14 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
this.receivedDamageFromThisTurn.clear();
|
||||
}
|
||||
|
||||
public final int getTotalDamageRecievedThisTurn() {
|
||||
int total = 0;
|
||||
for (int damage : this.receivedDamageFromThisTurn.values()) {
|
||||
total += damage;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* addDealtDamageToThisTurn.
|
||||
|
||||
@@ -6,8 +6,6 @@ import java.util.concurrent.Executors;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import forge.control.input.InputLockUI;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
@@ -87,18 +85,17 @@ public class FThreads {
|
||||
invokeInNewThread(proc, false);
|
||||
}
|
||||
|
||||
private final static InputLockUI inpuptLock = new InputLockUI();
|
||||
public static void invokeInNewThread(final Runnable proc, boolean lockUI) {
|
||||
Runnable toRun = proc;
|
||||
if( lockUI ) {
|
||||
// checkEDT("FThreads.invokeInNewthread", true)
|
||||
Singletons.getModel().getMatch().getInput().setInput(inpuptLock);
|
||||
Singletons.getModel().getMatch().getInput().lock();
|
||||
toRun = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
proc.run();
|
||||
// may try special unlock method here
|
||||
Singletons.getModel().getMatch().getInput().resetInput();
|
||||
Singletons.getModel().getMatch().getInput().unlock();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import forge.card.cost.CostDiscard;
|
||||
import forge.card.cost.CostPart;
|
||||
import forge.card.spellability.AbilitySub;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.SpellPermanent;
|
||||
import forge.card.spellability.Target;
|
||||
import forge.card.trigger.TriggerType;
|
||||
import forge.game.GlobalRuleChange;
|
||||
|
||||
@@ -1537,6 +1537,10 @@ public class CardFactoryUtil {
|
||||
return CardFactoryUtil.doXMath(c.getTotalDamageDoneBy(), m, c);
|
||||
}
|
||||
|
||||
if (sq[0].equals("TotalDamageReceivedThisTurn")) {
|
||||
return CardFactoryUtil.doXMath(c.getTotalDamageRecievedThisTurn(), m, c);
|
||||
}
|
||||
|
||||
// Count$YourPoisonCounters
|
||||
if (sq[0].contains("YourPoisonCounters")) {
|
||||
return CardFactoryUtil.doXMath(cardController.getPoisonCounters(), m, c);
|
||||
|
||||
@@ -103,7 +103,7 @@ public class CostDamage extends CostPart {
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
final String amount = this.getAmount();
|
||||
final Player activator = ability.getActivatingPlayer();
|
||||
final int life = activator.getLife();
|
||||
@@ -125,13 +125,9 @@ public class CostDamage extends CostPart {
|
||||
if (GuiDialog.confirm(source, sb.toString()) && activator.canPayLife(c)) {
|
||||
activator.addDamage(c, source);
|
||||
this.setLastPaidAmount(c);
|
||||
payment.setPaidManaPart(this);
|
||||
} else {
|
||||
payment.setCancel(true);
|
||||
payment.getRequirements().finishPaying();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -19,6 +19,7 @@ package forge.card.cost;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
@@ -43,6 +44,99 @@ import forge.view.ButtonUtil;
|
||||
public class CostDiscard extends CostPartWithList {
|
||||
// Discard<Num/Type{/TypeDescription}>
|
||||
|
||||
// Inputs
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public static final class InputPayCostDiscard extends InputPayCostBase {
|
||||
private final List<Card> handList;
|
||||
private final CostDiscard part;
|
||||
private final int nNeeded;
|
||||
private final String discType;
|
||||
private static final long serialVersionUID = -329993322080934435L;
|
||||
private int nDiscard = 0;
|
||||
private boolean sameName;
|
||||
|
||||
private final SpellAbility sa;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for Constructor.
|
||||
* @param sa
|
||||
* @param handList
|
||||
* @param part
|
||||
* @param payment
|
||||
* @param nNeeded
|
||||
* @param sp
|
||||
* @param discType
|
||||
*/
|
||||
public InputPayCostDiscard(CountDownLatch cdl, SpellAbility sa, List<Card> handList, CostDiscard part, CostPayment payment, int nNeeded, String discType) {
|
||||
super(cdl, payment);
|
||||
this.sa = sa;
|
||||
this.handList = handList;
|
||||
this.part = part;
|
||||
this.nNeeded = nNeeded;
|
||||
this.discType = discType;
|
||||
sameName = discType.contains("WithSameName");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
if (nNeeded == 0) {
|
||||
this.done();
|
||||
}
|
||||
|
||||
if (sa.getActivatingPlayer().getZone(ZoneType.Hand).isEmpty()) {
|
||||
this.stop();
|
||||
}
|
||||
final StringBuilder type = new StringBuilder("");
|
||||
if (!discType.equals("Card")) {
|
||||
type.append(" ").append(discType);
|
||||
}
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("Select a ");
|
||||
sb.append(part.getDescriptiveType());
|
||||
sb.append(" to discard.");
|
||||
if (nNeeded > 1) {
|
||||
sb.append(" You have ");
|
||||
sb.append(nNeeded - this.nDiscard);
|
||||
sb.append(" remaining.");
|
||||
}
|
||||
CMatchUI.SINGLETON_INSTANCE.showMessage(sb.toString());
|
||||
if (nNeeded > 0) {
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(final Card card) {
|
||||
Zone zone = Singletons.getModel().getGame().getZoneOf(card);
|
||||
if (zone.is(ZoneType.Hand) && handList.contains(card)) {
|
||||
if (!sameName || part.getList().isEmpty()
|
||||
|| part.getList().get(0).getName().equals(card.getName())) {
|
||||
// send in List<Card> for Typing
|
||||
card.getController().discard(card, sa);
|
||||
part.addToList(card);
|
||||
handList.remove(card);
|
||||
this.nDiscard++;
|
||||
|
||||
// in case no more cards in hand
|
||||
if (this.nDiscard == nNeeded) {
|
||||
this.done();
|
||||
} else if (sa.getActivatingPlayer().getZone(ZoneType.Hand).size() == 0) {
|
||||
// really
|
||||
// shouldn't
|
||||
// happen
|
||||
this.cancel();
|
||||
} else {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new cost discard.
|
||||
*
|
||||
@@ -167,36 +261,36 @@ public class CostDiscard extends CostPartWithList {
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
final Player activator = ability.getActivatingPlayer();
|
||||
List<Card> handList = new ArrayList<Card>(activator.getCardsIn(ZoneType.Hand));
|
||||
String discType = this.getType();
|
||||
String discardType = this.getType();
|
||||
final String amount = this.getAmount();
|
||||
this.resetList();
|
||||
|
||||
if (this.payCostFromSource()) {
|
||||
if (!handList.contains(source)) {
|
||||
return false;
|
||||
payment.setCancel(true);
|
||||
}
|
||||
activator.discard(source, ability);
|
||||
payment.setPaidManaPart(this);
|
||||
payment.setPaidPart(this);
|
||||
//this.addToList(source);
|
||||
} else if (discType.equals("Hand")) {
|
||||
} else if (discardType.equals("Hand")) {
|
||||
this.setList(handList);
|
||||
activator.discardHand(ability);
|
||||
payment.setPaidManaPart(this);
|
||||
} else if (discType.equals("LastDrawn")) {
|
||||
payment.setPaidPart(this);
|
||||
} else if (discardType.equals("LastDrawn")) {
|
||||
final Card lastDrawn = activator.getLastDrawnCard();
|
||||
this.addToList(lastDrawn);
|
||||
if (!handList.contains(lastDrawn)) {
|
||||
return false;
|
||||
payment.setCancel(true);
|
||||
}
|
||||
activator.discard(lastDrawn, ability);
|
||||
payment.setPaidManaPart(this);
|
||||
payment.setPaidPart(this);
|
||||
} else {
|
||||
Integer c = this.convertAmount();
|
||||
|
||||
if (discType.equals("Random")) {
|
||||
if (discardType.equals("Random")) {
|
||||
if (c == null) {
|
||||
final String sVar = ability.getSVar(amount);
|
||||
// Generalize this
|
||||
@@ -208,9 +302,9 @@ public class CostDiscard extends CostPartWithList {
|
||||
}
|
||||
|
||||
this.setList(activator.discardRandom(c, ability));
|
||||
payment.setPaidManaPart(this);
|
||||
payment.setPaidPart(this);
|
||||
} else {
|
||||
String type = new String(discType);
|
||||
String type = new String(discardType);
|
||||
boolean sameName = false;
|
||||
if (type.contains("+WithSameName")) {
|
||||
sameName = true;
|
||||
@@ -243,13 +337,13 @@ public class CostDiscard extends CostPartWithList {
|
||||
}
|
||||
}
|
||||
|
||||
final Input inp = CostDiscard.inputDiscardCost(discType, handList, ability, payment, this, c);
|
||||
Singletons.getModel().getMatch().getInput().setInputInterrupt(inp);
|
||||
return false;
|
||||
CountDownLatch cdl = new CountDownLatch(1);
|
||||
final Input inp = new InputPayCostDiscard(cdl, ability, handList, this, payment, c, discardType);
|
||||
setInputAndWait(inp, cdl);
|
||||
}
|
||||
}
|
||||
this.addListToHash(ability, "Discarded");
|
||||
return true;
|
||||
if ( !payment.isCanceled())
|
||||
this.addListToHash(ability, "Discarded");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -308,107 +402,4 @@ public class CostDiscard extends CostPartWithList {
|
||||
|
||||
// Inputs
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* input_discardCost.
|
||||
* </p>
|
||||
*
|
||||
* @param discType
|
||||
* a {@link java.lang.String} object.
|
||||
* @param handList
|
||||
* a {@link forge.CardList} object.
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param payment
|
||||
* a {@link forge.card.cost.CostPayment} object.
|
||||
* @param part
|
||||
* TODO
|
||||
* @param nNeeded
|
||||
* a int.
|
||||
*
|
||||
* @return a {@link forge.control.input.Input} object.
|
||||
*/
|
||||
public static Input inputDiscardCost(final String discType, final List<Card> handList, final SpellAbility sa,
|
||||
final CostPayment payment, final CostDiscard part, final int nNeeded) {
|
||||
final SpellAbility sp = sa;
|
||||
final Input target = new Input() {
|
||||
private static final long serialVersionUID = -329993322080934435L;
|
||||
|
||||
private int nDiscard = 0;
|
||||
private boolean sameName = discType.contains("WithSameName");
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
if (nNeeded == 0) {
|
||||
this.done();
|
||||
}
|
||||
|
||||
if (sa.getActivatingPlayer().getZone(ZoneType.Hand).isEmpty()) {
|
||||
this.stop();
|
||||
}
|
||||
final StringBuilder type = new StringBuilder("");
|
||||
if (!discType.equals("Card")) {
|
||||
type.append(" ").append(discType);
|
||||
}
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("Select a ");
|
||||
sb.append(part.getDescriptiveType());
|
||||
sb.append(" to discard.");
|
||||
if (nNeeded > 1) {
|
||||
sb.append(" You have ");
|
||||
sb.append(nNeeded - this.nDiscard);
|
||||
sb.append(" remaining.");
|
||||
}
|
||||
CMatchUI.SINGLETON_INSTANCE.showMessage(sb.toString());
|
||||
if (nNeeded > 0) {
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(final Card card) {
|
||||
Zone zone = Singletons.getModel().getGame().getZoneOf(card);
|
||||
if (zone.is(ZoneType.Hand) && handList.contains(card)) {
|
||||
if (!sameName || part.getList().isEmpty()
|
||||
|| part.getList().get(0).getName().equals(card.getName())) {
|
||||
// send in List<Card> for Typing
|
||||
card.getController().discard(card, sp);
|
||||
part.addToList(card);
|
||||
handList.remove(card);
|
||||
this.nDiscard++;
|
||||
|
||||
// in case no more cards in hand
|
||||
if (this.nDiscard == nNeeded) {
|
||||
this.done();
|
||||
} else if (sa.getActivatingPlayer().getZone(ZoneType.Hand).size() == 0) {
|
||||
// really
|
||||
// shouldn't
|
||||
// happen
|
||||
this.cancel();
|
||||
} else {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
this.stop();
|
||||
payment.cancelCost();
|
||||
}
|
||||
|
||||
public void done() {
|
||||
this.stop();
|
||||
part.addListToHash(sp, "Discarded");
|
||||
payment.paidCost(part);
|
||||
}
|
||||
};
|
||||
|
||||
return target;
|
||||
} // input_discard()
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ package forge.card.cost;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import forge.Card;
|
||||
import forge.CardLists;
|
||||
@@ -49,18 +50,14 @@ public class CostExile extends CostPartWithList {
|
||||
// ExileFromTop<Num/Type{/TypeDescription}> (of library)
|
||||
// ExileSameGrave<Num/Type{/TypeDescription}>
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
private static final class InputExileFrom extends Input {
|
||||
private static final class InputExileFrom extends InputPayCostBase {
|
||||
private final SpellAbility sa;
|
||||
private final String type;
|
||||
private final int nNeeded;
|
||||
private final CostPayment payment;
|
||||
private final CostExile part;
|
||||
private static final long serialVersionUID = 734256837615635021L;
|
||||
private List<Card> typeList;
|
||||
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for Constructor.
|
||||
@@ -70,11 +67,11 @@ public class CostExile extends CostPartWithList {
|
||||
* @param payment
|
||||
* @param part
|
||||
*/
|
||||
private InputExileFrom(SpellAbility sa, String type, int nNeeded, CostPayment payment, CostExile part) {
|
||||
private InputExileFrom(CountDownLatch cdl, SpellAbility sa, String type, int nNeeded, CostPayment payment, CostExile part) {
|
||||
super(cdl, payment);
|
||||
this.sa = sa;
|
||||
this.type = type;
|
||||
this.nNeeded = nNeeded;
|
||||
this.payment = payment;
|
||||
this.part = part;
|
||||
}
|
||||
|
||||
@@ -107,33 +104,15 @@ public class CostExile extends CostPartWithList {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
public void done() {
|
||||
this.stop();
|
||||
part.addListToHash(sa, "Exiled");
|
||||
payment.paidCost(part);
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
this.stop();
|
||||
payment.cancelCost();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
private static final class InputExileFromSame extends Input {
|
||||
private static final class InputExileFromSame extends InputPayCostBase {
|
||||
private final List<Card> list;
|
||||
private final CostExile part;
|
||||
private final CostPayment payment;
|
||||
private final SpellAbility sa;
|
||||
private final int nNeeded;
|
||||
private final List<Player> payableZone;
|
||||
private static final long serialVersionUID = 734256837615635021L;
|
||||
@@ -148,12 +127,10 @@ public class CostExile extends CostPartWithList {
|
||||
* @param nNeeded
|
||||
* @param payableZone
|
||||
*/
|
||||
private InputExileFromSame(List<Card> list, CostExile part, CostPayment payment, SpellAbility sa, int nNeeded,
|
||||
List<Player> payableZone) {
|
||||
private InputExileFromSame(CountDownLatch cdl, List<Card> list, CostExile part, CostPayment payment, int nNeeded, List<Player> payableZone) {
|
||||
super(cdl, payment);
|
||||
this.list = list;
|
||||
this.part = part;
|
||||
this.payment = payment;
|
||||
this.sa = sa;
|
||||
this.nNeeded = nNeeded;
|
||||
this.payableZone = payableZone;
|
||||
}
|
||||
@@ -196,30 +173,14 @@ public class CostExile extends CostPartWithList {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
public void done() {
|
||||
this.stop();
|
||||
part.addListToHash(sa, "Exiled");
|
||||
payment.paidCost(part);
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
this.stop();
|
||||
payment.cancelCost();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
private static final class InputExileFromStack extends Input {
|
||||
private final CostPayment payment;
|
||||
private static final class InputExileFromStack extends InputPayCostBase {
|
||||
|
||||
private final SpellAbility sa;
|
||||
private final String type;
|
||||
private final int nNeeded;
|
||||
@@ -236,8 +197,8 @@ public class CostExile extends CostPartWithList {
|
||||
* @param nNeeded
|
||||
* @param part
|
||||
*/
|
||||
private InputExileFromStack(CostPayment payment, SpellAbility sa, String type, int nNeeded, CostExile part) {
|
||||
this.payment = payment;
|
||||
private InputExileFromStack(CountDownLatch cdl, CostPayment payment, SpellAbility sa, String type, int nNeeded, CostExile part) {
|
||||
super(cdl, payment);
|
||||
this.sa = sa;
|
||||
this.type = type;
|
||||
this.nNeeded = nNeeded;
|
||||
@@ -293,31 +254,14 @@ public class CostExile extends CostPartWithList {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
public void done() {
|
||||
this.stop();
|
||||
part.addListToHash(sa, "Exiled");
|
||||
payment.paidCost(part);
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
this.stop();
|
||||
payment.cancelCost();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
private static final class InputExileType extends Input {
|
||||
private static final class InputExileType extends InputPayCostBase {
|
||||
private final CostExile part;
|
||||
private final CostPayment payment;
|
||||
private final String type;
|
||||
private final int nNeeded;
|
||||
private final SpellAbility sa;
|
||||
@@ -333,9 +277,9 @@ public class CostExile extends CostPartWithList {
|
||||
* @param nNeeded
|
||||
* @param sa
|
||||
*/
|
||||
private InputExileType(CostExile part, CostPayment payment, String type, int nNeeded, SpellAbility sa) {
|
||||
private InputExileType(CountDownLatch cdl, CostExile part, CostPayment payment, String type, int nNeeded, SpellAbility sa) {
|
||||
super(cdl, payment);
|
||||
this.part = part;
|
||||
this.payment = payment;
|
||||
this.type = type;
|
||||
this.nNeeded = nNeeded;
|
||||
this.sa = sa;
|
||||
@@ -366,11 +310,6 @@ public class CostExile extends CostPartWithList {
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(final Card card) {
|
||||
if (this.typeList.contains(card)) {
|
||||
@@ -389,25 +328,13 @@ public class CostExile extends CostPartWithList {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void done() {
|
||||
this.stop();
|
||||
part.addListToHash(sa, "Exiled");
|
||||
payment.paidCost(part);
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
this.stop();
|
||||
payment.cancelCost();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
private static final class InputExileThis extends Input {
|
||||
private final CostPayment payment;
|
||||
private static final class InputExileThis extends InputPayCostBase {
|
||||
private final CostExile part;
|
||||
private final SpellAbility sa;
|
||||
private static final long serialVersionUID = 678668673002725001L;
|
||||
@@ -418,30 +345,27 @@ public class CostExile extends CostPartWithList {
|
||||
* @param part
|
||||
* @param sa
|
||||
*/
|
||||
private InputExileThis(CostPayment payment, CostExile part, SpellAbility sa) {
|
||||
this.payment = payment;
|
||||
private InputExileThis(CountDownLatch cdl, CostPayment payment, CostExile part, SpellAbility sa) {
|
||||
super(cdl, payment);
|
||||
this.part = part;
|
||||
this.sa = sa;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
final Card card = sa.getSourceCard();
|
||||
if ( sa.getActivatingPlayer().getZone(part.getFrom()).contains(card)) {
|
||||
|
||||
boolean choice = GuiDialog.confirm(card, card.getName() + " - Exile?");
|
||||
if (choice) {
|
||||
payment.getAbility().addCostToHashList(card, "Exiled");
|
||||
Singletons.getModel().getGame().getAction().exile(card);
|
||||
part.addToList(card);
|
||||
this.stop();
|
||||
part.addListToHash(sa, "Exiled");
|
||||
payment.paidCost(part);
|
||||
done();
|
||||
} else {
|
||||
this.stop();
|
||||
payment.cancelCost();
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
else cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -619,7 +543,7 @@ public class CostExile extends CostPartWithList {
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
final String amount = this.getAmount();
|
||||
Integer c = this.convertAmount();
|
||||
final Player activator = ability.getActivatingPlayer();
|
||||
@@ -636,7 +560,7 @@ public class CostExile extends CostPartWithList {
|
||||
for (final Card card : list) {
|
||||
Singletons.getModel().getGame().getAction().exile(card);
|
||||
}
|
||||
payment.paidCost(this);
|
||||
payment.setPaidPart(this);
|
||||
}
|
||||
list = CardLists.getValidCards(list, this.getType().split(";"), activator, source);
|
||||
if (c == null) {
|
||||
@@ -651,13 +575,15 @@ public class CostExile extends CostPartWithList {
|
||||
}
|
||||
}
|
||||
|
||||
final CountDownLatch cdl = new CountDownLatch(1);
|
||||
|
||||
Input target = null;
|
||||
if (this.payCostFromSource()) {
|
||||
target = new InputExileThis(payment, this, ability);
|
||||
target = new InputExileThis(cdl, payment, this, ability);
|
||||
} else if (this.from.equals(ZoneType.Battlefield) || this.from.equals(ZoneType.Hand)) {
|
||||
target = new InputExileType(this, payment, this.getType(), c, ability);
|
||||
target = new InputExileType(cdl, this, payment, this.getType(), c, ability);
|
||||
} else if (this.from.equals(ZoneType.Stack)) {
|
||||
target = new InputExileFromStack(payment, ability, this.getType(), c, this);
|
||||
target = new InputExileFromStack(cdl,payment, ability, this.getType(), c, this);
|
||||
} else if (this.from.equals(ZoneType.Library)) {
|
||||
// this does not create input
|
||||
CostExile.exileFromTop(ability, this, payment, c);
|
||||
@@ -672,13 +598,13 @@ public class CostExile extends CostPartWithList {
|
||||
payableZone.add(p);
|
||||
}
|
||||
}
|
||||
target = new InputExileFromSame(list, this, payment, ability, c, payableZone);
|
||||
target = new InputExileFromSame(cdl, list, this, payment, c, payableZone);
|
||||
} else {
|
||||
target = new InputExileFrom(ability, this.getType(), c, payment, this);
|
||||
target = new InputExileFrom(cdl,ability, this.getType(), c, payment, this);
|
||||
}
|
||||
if ( null != target )
|
||||
Singletons.getModel().getMatch().getInput().setInputInterrupt(target);
|
||||
return false;
|
||||
setInputAndWait(target, cdl);
|
||||
if(!payment.isCanceled())
|
||||
addListToHash(ability, "Exiled");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -762,7 +688,7 @@ public class CostExile extends CostPartWithList {
|
||||
Singletons.getModel().getGame().getAction().exile(c);
|
||||
}
|
||||
part.addListToHash(sa, "Exiled");
|
||||
payment.paidCost(part);
|
||||
payment.setPaidPart(part);
|
||||
} else {
|
||||
payment.cancelCost();
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ public class CostGainLife extends CostPart {
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
final String amount = this.getAmount();
|
||||
final Player activator = ability.getActivatingPlayer();
|
||||
final int life = activator.getLife();
|
||||
@@ -163,8 +163,6 @@ public class CostGainLife extends CostPart {
|
||||
if(cntPlayers == Integer.MAX_VALUE) { // applied to all players who can gain
|
||||
for(Player opp: oppsThatCanGainLife)
|
||||
opp.gainLife(c, null);
|
||||
payment.setPaidManaPart(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
@@ -175,16 +173,12 @@ public class CostGainLife extends CostPart {
|
||||
final Player chosenToGain = GuiChoose.oneOrNone(sb.toString(), oppsThatCanGainLife);
|
||||
if (null == chosenToGain) {
|
||||
payment.setCancel(true);
|
||||
payment.getRequirements().finishPaying();
|
||||
return false;
|
||||
return;
|
||||
} else {
|
||||
final Player chosen = chosenToGain;
|
||||
chosen.gainLife(c, null);
|
||||
}
|
||||
}
|
||||
|
||||
payment.setPaidManaPart(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -126,7 +126,7 @@ public class CostMill extends CostPartWithList {
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
final String amount = this.getAmount();
|
||||
Integer c = this.convertAmount();
|
||||
final Player activator = ability.getActivatingPlayer();
|
||||
@@ -145,7 +145,7 @@ public class CostMill extends CostPartWithList {
|
||||
if ((list == null) || (list.size() > c)) {
|
||||
// I don't believe this is possible
|
||||
payment.cancelCost();
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
@@ -161,11 +161,8 @@ public class CostMill extends CostPartWithList {
|
||||
Singletons.getModel().getGame().getAction().moveToGraveyard(card);
|
||||
}
|
||||
this.addListToHash(ability, "Milled");
|
||||
payment.paidCost(this);
|
||||
return false;
|
||||
} else {
|
||||
payment.cancelCost();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,13 @@
|
||||
*/
|
||||
package forge.card.cost;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import forge.Card;
|
||||
import forge.Singletons;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.control.input.Input;
|
||||
import forge.error.BugReporter;
|
||||
import forge.game.GameState;
|
||||
import forge.game.player.AIPlayer;
|
||||
import forge.game.player.Player;
|
||||
@@ -141,6 +146,15 @@ public abstract class CostPart {
|
||||
return i;
|
||||
}
|
||||
|
||||
public final void setInputAndWait(Input inp, CountDownLatch cdl) {
|
||||
Singletons.getModel().getMatch().getInput().setInputInterrupt(inp);
|
||||
try {
|
||||
cdl.await();
|
||||
} catch (InterruptedException e) {
|
||||
BugReporter.reportException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Can pay.
|
||||
*
|
||||
@@ -199,7 +213,7 @@ public abstract class CostPart {
|
||||
* @param game
|
||||
* @return true, if successful
|
||||
*/
|
||||
public abstract boolean payHuman(SpellAbility ability, Card source, CostPayment payment, GameState game);
|
||||
public abstract void payHuman(SpellAbility ability, Card source, CostPayment payment, GameState game);
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
*/
|
||||
package forge.card.cost;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import forge.Card;
|
||||
import forge.Singletons;
|
||||
import forge.card.ability.AbilityUtils;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.control.input.Input;
|
||||
@@ -206,7 +207,7 @@ public class CostPartMana extends CostPart {
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
int manaToAdd = 0;
|
||||
if (!this.hasNoXManaCost()) {
|
||||
// if X cost is a defined value, other than xPaid
|
||||
@@ -215,19 +216,19 @@ public class CostPartMana extends CostPart {
|
||||
manaToAdd = AbilityUtils.calculateAmount(source, "X", ability) * this.getXMana();
|
||||
}
|
||||
}
|
||||
if (!this.getManaToPay().equals("0") || (manaToAdd > 0)) {
|
||||
final Input inp = new InputPayManaOfCostPayment(game, this, ability, payment, manaToAdd);
|
||||
Singletons.getModel().getMatch().getInput().setInputInterrupt(inp);
|
||||
|
||||
CountDownLatch cdl = new CountDownLatch(1);
|
||||
final Input inp;
|
||||
if (!"0".equals(this.getManaToPay()) || manaToAdd > 0) {
|
||||
inp = new InputPayManaOfCostPayment(game, this, ability, payment, manaToAdd, cdl);
|
||||
|
||||
} else if (this.getXMana() > 0) {
|
||||
final Input inp = new InputPayManaX(game, ability, payment, this);
|
||||
Singletons.getModel().getMatch().getInput().setInputInterrupt(inp);
|
||||
} else {
|
||||
payment.paidCost(this);
|
||||
inp = new InputPayManaX(game, ability, payment, this, cdl);
|
||||
}
|
||||
else inp = null;
|
||||
if ( null != inp) {
|
||||
setInputAndWait(inp, cdl);
|
||||
}
|
||||
|
||||
// We return false here because the Inputs set above should recall
|
||||
// payment.payCosts()
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -123,7 +123,7 @@ public class CostPayLife extends CostPart {
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
final String amount = this.getAmount();
|
||||
final Player activator = ability.getActivatingPlayer();
|
||||
final int life = activator.getLife();
|
||||
@@ -147,16 +147,12 @@ public class CostPayLife extends CostPart {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(source.getName()).append(" - Pay ").append(c).append(" Life?");
|
||||
|
||||
if (GuiDialog.confirm(source, sb.toString()) && activator.canPayLife(c)) {
|
||||
if (activator.canPayLife(c) && GuiDialog.confirm(source, sb.toString())) {
|
||||
activator.payLife(c, null);
|
||||
this.setLastPaidAmount(c);
|
||||
payment.setPaidManaPart(this);
|
||||
} else {
|
||||
payment.setCancel(true);
|
||||
payment.getRequirements().finishPaying();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -179,26 +179,15 @@ public class CostPayment {
|
||||
* @param bPaid
|
||||
* the b paid
|
||||
*/
|
||||
public final void setPaidManaPart(final CostPart part) {
|
||||
public final void setPaidPart(final CostPart part) {
|
||||
this.paidCostParts.add(part);
|
||||
}
|
||||
|
||||
/**
|
||||
* Paid cost.
|
||||
*
|
||||
* @param part
|
||||
* the part
|
||||
*/
|
||||
public final void paidCost(final CostPart part) {
|
||||
this.setPaidManaPart(part);
|
||||
this.payCost();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel cost (including CostPart for refunding).
|
||||
*/
|
||||
public final void cancelCost(final CostPart part) {
|
||||
this.setPaidManaPart(part);
|
||||
this.setPaidPart(part);
|
||||
this.cancelCost();
|
||||
}
|
||||
|
||||
@@ -207,7 +196,6 @@ public class CostPayment {
|
||||
*/
|
||||
public final void cancelCost() {
|
||||
this.setCancel(true);
|
||||
this.req.finishPaying();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -220,7 +208,6 @@ public class CostPayment {
|
||||
public final boolean payCost() {
|
||||
// Nothing actually ever checks this return value, is it needed?
|
||||
if (this.bCancel) {
|
||||
this.req.finishPaying();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -230,13 +217,13 @@ public class CostPayment {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!part.payHuman(this.ability, this.card, this, game)) {
|
||||
return false;
|
||||
}
|
||||
part.payHuman(this.ability, this.card, this, game);
|
||||
if ( isCanceled() ) break;
|
||||
|
||||
setPaidPart(part);
|
||||
}
|
||||
|
||||
this.resetUndoList();
|
||||
this.req.finishPaying();
|
||||
|
||||
this.resetUndoList(); // ??
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,14 +18,13 @@
|
||||
package forge.card.cost;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import forge.Card;
|
||||
import forge.CardLists;
|
||||
import forge.CounterType;
|
||||
import forge.Singletons;
|
||||
import forge.card.ability.AbilityUtils;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.control.input.Input;
|
||||
import forge.game.GameState;
|
||||
import forge.game.ai.ComputerUtilCard;
|
||||
import forge.game.player.AIPlayer;
|
||||
@@ -38,6 +37,72 @@ import forge.view.ButtonUtil;
|
||||
* The Class CostPutCounter.
|
||||
*/
|
||||
public class CostPutCounter extends CostPartWithList {
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public static final class InputPayCostPutCounter extends InputPayCostBase {
|
||||
private final String type;
|
||||
private final CostPutCounter costPutCounter;
|
||||
private final int nNeeded;
|
||||
private final SpellAbility sa;
|
||||
private static final long serialVersionUID = 2685832214519141903L;
|
||||
private List<Card> typeList;
|
||||
private int nPut = 0;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for Constructor.
|
||||
* @param type
|
||||
* @param costPutCounter
|
||||
* @param nNeeded
|
||||
* @param payment
|
||||
* @param sa
|
||||
*/
|
||||
public InputPayCostPutCounter(CountDownLatch cdl, String type, CostPutCounter costPutCounter, int nNeeded, CostPayment payment, SpellAbility sa) {
|
||||
super(cdl, payment);
|
||||
this.type = type;
|
||||
this.costPutCounter = costPutCounter;
|
||||
this.nNeeded = nNeeded;
|
||||
this.sa = sa;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
if ((nNeeded == 0) || (nNeeded == this.nPut)) {
|
||||
this.done();
|
||||
}
|
||||
|
||||
final StringBuilder msg = new StringBuilder("Put ");
|
||||
final int nLeft = nNeeded - this.nPut;
|
||||
msg.append(nLeft).append(" ");
|
||||
msg.append(costPutCounter.getCounter()).append(" on ");
|
||||
|
||||
msg.append(costPutCounter.getDescriptiveType());
|
||||
if (nLeft > 1) {
|
||||
msg.append("s");
|
||||
}
|
||||
|
||||
this.typeList = CardLists.getValidCards(sa.getActivatingPlayer().getCardsIn(ZoneType.Battlefield), type.split(";"), sa.getActivatingPlayer(), sa.getSourceCard());
|
||||
CMatchUI.SINGLETON_INSTANCE.showMessage(msg.toString());
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(final Card card) {
|
||||
if (this.typeList.contains(card)) {
|
||||
this.nPut++;
|
||||
costPutCounter.addToList(card);
|
||||
card.addCounter(costPutCounter.getCounter(), 1, false);
|
||||
|
||||
if (nNeeded == this.nPut) {
|
||||
this.done();
|
||||
} else {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Put Counter doesn't really have a "Valid" portion of the cost
|
||||
private final CounterType counter;
|
||||
private int lastPaidAmount = 0;
|
||||
@@ -179,7 +244,7 @@ public class CostPutCounter extends CostPartWithList {
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
Integer c = this.convertAmount();
|
||||
if (c == null) {
|
||||
c = AbilityUtils.calculateAmount(source, this.getAmount(), ability);
|
||||
@@ -187,14 +252,13 @@ public class CostPutCounter extends CostPartWithList {
|
||||
|
||||
if (this.payCostFromSource()) {
|
||||
source.addCounter(this.getCounter(), c, false);
|
||||
payment.setPaidManaPart(this);
|
||||
this.addToList(source);
|
||||
return true;
|
||||
} else {
|
||||
final Input inp = CostPutCounter.putCounterType(ability, this.getType(), payment, this, c);
|
||||
Singletons.getModel().getMatch().getInput().setInputInterrupt(inp);
|
||||
return false;
|
||||
CountDownLatch cdl = new CountDownLatch(1);
|
||||
setInputAndWait(new InputPayCostPutCounter(cdl, this.getType(), this, c, payment, ability), cdl);
|
||||
}
|
||||
if ( !payment.isCanceled())
|
||||
addListToHash(ability, "CounterPut");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -229,84 +293,4 @@ public class CostPutCounter extends CostPartWithList {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* returnType.
|
||||
* </p>
|
||||
*
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param type
|
||||
* a {@link java.lang.String} object.
|
||||
* @param payment
|
||||
* a {@link forge.card.cost.CostPayment} object.
|
||||
* @param costPutCounter
|
||||
* TODO
|
||||
* @param nNeeded
|
||||
* the n needed
|
||||
* @return a {@link forge.control.input.Input} object.
|
||||
*/
|
||||
public static Input putCounterType(final SpellAbility sa, final String type, final CostPayment payment,
|
||||
final CostPutCounter costPutCounter, final int nNeeded) {
|
||||
final Input target = new Input() {
|
||||
private static final long serialVersionUID = 2685832214519141903L;
|
||||
private List<Card> typeList;
|
||||
private int nPut = 0;
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
if ((nNeeded == 0) || (nNeeded == this.nPut)) {
|
||||
this.done();
|
||||
}
|
||||
|
||||
final StringBuilder msg = new StringBuilder("Put ");
|
||||
final int nLeft = nNeeded - this.nPut;
|
||||
msg.append(nLeft).append(" ");
|
||||
msg.append(costPutCounter.getCounter()).append(" on ");
|
||||
|
||||
msg.append(costPutCounter.getDescriptiveType());
|
||||
if (nLeft > 1) {
|
||||
msg.append("s");
|
||||
}
|
||||
|
||||
this.typeList = CardLists.getValidCards(sa.getActivatingPlayer().getCardsIn(ZoneType.Battlefield), type.split(";"), sa.getActivatingPlayer(), sa.getSourceCard());
|
||||
CMatchUI.SINGLETON_INSTANCE.showMessage(msg.toString());
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(final Card card) {
|
||||
if (this.typeList.contains(card)) {
|
||||
this.nPut++;
|
||||
costPutCounter.addToList(card);
|
||||
card.addCounter(costPutCounter.getCounter(), 1, false);
|
||||
|
||||
if (nNeeded == this.nPut) {
|
||||
this.done();
|
||||
} else {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void done() {
|
||||
this.stop();
|
||||
payment.paidCost(costPutCounter);
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
this.stop();
|
||||
costPutCounter.addListToHash(sa, "CounterPut");
|
||||
payment.cancelCost();
|
||||
}
|
||||
};
|
||||
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,11 +19,11 @@ package forge.card.cost;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import forge.Card;
|
||||
import forge.CardLists;
|
||||
import forge.CounterType;
|
||||
import forge.Singletons;
|
||||
import forge.card.ability.AbilityUtils;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.control.input.Input;
|
||||
@@ -46,6 +46,148 @@ public class CostRemoveCounter extends CostPartWithList {
|
||||
// Counter is tough),
|
||||
// Quillspike, Rift Elemental, Sage of Fables, Spike Rogue
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public static final class InputPayCostRemoveCounterType extends InputPayCostBase {
|
||||
private final int nNeeded;
|
||||
private final SpellAbility sa;
|
||||
private final String type;
|
||||
private final CostRemoveCounter costRemoveCounter;
|
||||
private static final long serialVersionUID = 2685832214519141903L;
|
||||
private List<Card> typeList;
|
||||
private int nRemove = 0;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for Constructor.
|
||||
* @param payment
|
||||
* @param nNeeded
|
||||
* @param sa
|
||||
* @param type
|
||||
* @param costRemoveCounter
|
||||
*/
|
||||
public InputPayCostRemoveCounterType(CountDownLatch cdl, CostPayment payment, int nNeeded, SpellAbility sa, String type,
|
||||
CostRemoveCounter costRemoveCounter) {
|
||||
super(cdl, payment);
|
||||
this.nNeeded = nNeeded;
|
||||
this.sa = sa;
|
||||
this.type = type;
|
||||
this.costRemoveCounter = costRemoveCounter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
if ((nNeeded == 0) || (nNeeded == this.nRemove)) {
|
||||
this.done();
|
||||
}
|
||||
|
||||
final StringBuilder msg = new StringBuilder("Remove ");
|
||||
final int nLeft = nNeeded - this.nRemove;
|
||||
msg.append(nLeft).append(" ");
|
||||
msg.append(costRemoveCounter.getCounter().getName()).append(" counters from ");
|
||||
msg.append(costRemoveCounter.getDescriptiveType());
|
||||
|
||||
this.typeList = CardLists.getValidCards(sa.getActivatingPlayer().getCardsIn(costRemoveCounter.getZone()), type.split(";"), sa.getActivatingPlayer(), sa.getSourceCard());
|
||||
|
||||
// TODO Tabulate typelist vs nNeeded to see if there are enough counters to remove
|
||||
|
||||
CMatchUI.SINGLETON_INSTANCE.showMessage(msg.toString());
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(final Card card) {
|
||||
if (this.typeList.contains(card)) {
|
||||
if (card.getCounters(costRemoveCounter.getCounter()) > 0) {
|
||||
this.nRemove++;
|
||||
costRemoveCounter.addToList(card);
|
||||
card.subtractCounter(costRemoveCounter.getCounter(), 1);
|
||||
|
||||
if (nNeeded == this.nRemove) {
|
||||
this.done();
|
||||
} else {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public static final class InputPayCostRemoveCounterFrom extends InputPayCostBase {
|
||||
private final CostRemoveCounter costRemoveCounter;
|
||||
private final String type;
|
||||
private final SpellAbility sa;
|
||||
private final int nNeeded;
|
||||
private static final long serialVersionUID = 734256837615635021L;
|
||||
private List<Card> typeList;
|
||||
private int nRemove = 0;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for Constructor.
|
||||
* @param costRemoveCounter
|
||||
* @param type
|
||||
* @param sa
|
||||
* @param nNeeded
|
||||
* @param payment
|
||||
*/
|
||||
public InputPayCostRemoveCounterFrom(CountDownLatch cdl, CostRemoveCounter costRemoveCounter, String type, SpellAbility sa,
|
||||
int nNeeded, CostPayment payment) {
|
||||
super(cdl, payment);
|
||||
this.costRemoveCounter = costRemoveCounter;
|
||||
this.type = type;
|
||||
this.sa = sa;
|
||||
this.nNeeded = nNeeded;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
if (nNeeded == 0) {
|
||||
this.done();
|
||||
}
|
||||
|
||||
this.typeList = new ArrayList<Card>(sa.getActivatingPlayer().getCardsIn(costRemoveCounter.getZone()));
|
||||
this.typeList = CardLists.getValidCards(this.typeList, type.split(";"), sa.getActivatingPlayer(), sa.getSourceCard());
|
||||
|
||||
for (int i = 0; i < nNeeded; i++) {
|
||||
if (this.typeList.size() == 0) {
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
final Card o = GuiChoose
|
||||
.oneOrNone("Remove counter(s) from a card in " + costRemoveCounter.getZone(), this.typeList);
|
||||
|
||||
if (o != null) {
|
||||
final Card card = o;
|
||||
|
||||
if (card.getCounters(costRemoveCounter.getCounter()) > 0) {
|
||||
this.nRemove++;
|
||||
costRemoveCounter.addToList(card);
|
||||
card.subtractCounter(costRemoveCounter.getCounter(), 1);
|
||||
|
||||
if (card.getCounters(costRemoveCounter.getCounter()) == 0) {
|
||||
this.typeList.remove(card);
|
||||
}
|
||||
|
||||
if (nNeeded == this.nRemove) {
|
||||
this.done();
|
||||
} else {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.cancel();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final CounterType counter;
|
||||
private int lastPaidAmount = 0;
|
||||
private ZoneType zone;
|
||||
@@ -221,7 +363,7 @@ public class CostRemoveCounter extends CostPartWithList {
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
final String amount = this.getAmount();
|
||||
Integer c = this.convertAmount();
|
||||
int maxCounters = 0;
|
||||
@@ -237,15 +379,18 @@ public class CostRemoveCounter extends CostPartWithList {
|
||||
}
|
||||
}
|
||||
|
||||
final Input inp;
|
||||
CountDownLatch cdl = new CountDownLatch(1);
|
||||
if (this.getZone().equals(ZoneType.Battlefield)) {
|
||||
final Input inp = CostRemoveCounter.removeCounterType(ability, this.getType(), payment, this, c);
|
||||
Singletons.getModel().getMatch().getInput().setInputInterrupt(inp);
|
||||
inp = new InputPayCostRemoveCounterType(cdl, payment, c, ability, this.getType(), this);
|
||||
} else {
|
||||
inp = new InputPayCostRemoveCounterFrom(cdl, this, this.getType(), ability, c, payment);
|
||||
}
|
||||
else {
|
||||
final Input inp = CostRemoveCounter.removeCounterTypeFrom(ability, this.getType(), payment, this, c);
|
||||
Singletons.getModel().getMatch().getInput().setInputInterrupt(inp);
|
||||
}
|
||||
return false;
|
||||
setInputAndWait(inp, cdl);
|
||||
|
||||
if ( !payment.isCanceled() )
|
||||
addListToHash(ability, "CounterRemove");
|
||||
return;
|
||||
}
|
||||
|
||||
maxCounters = source.getCounters(this.counter);
|
||||
@@ -268,13 +413,9 @@ public class CostRemoveCounter extends CostPartWithList {
|
||||
source.setSVar("CostCountersRemoved", "Number$" + Integer.toString(c));
|
||||
source.subtractCounter(this.counter, c);
|
||||
this.setLastPaidAmount(c);
|
||||
payment.setPaidManaPart(this);
|
||||
} else {
|
||||
payment.setCancel(true);
|
||||
payment.getRequirements().finishPaying();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -320,172 +461,4 @@ public class CostRemoveCounter extends CostPartWithList {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* returnType.
|
||||
* </p>
|
||||
*
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param type
|
||||
* a {@link java.lang.String} object.
|
||||
* @param payment
|
||||
* a {@link forge.card.cost.CostPayment} object.
|
||||
* @param costRemoveCounter
|
||||
* TODO
|
||||
* @param nNeeded
|
||||
* the n needed
|
||||
* @return a {@link forge.control.input.Input} object.
|
||||
*/
|
||||
public static Input removeCounterType(final SpellAbility sa, final String type, final CostPayment payment,
|
||||
final CostRemoveCounter costRemoveCounter, final int nNeeded) {
|
||||
final Input target = new Input() {
|
||||
private static final long serialVersionUID = 2685832214519141903L;
|
||||
private List<Card> typeList;
|
||||
private int nRemove = 0;
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
if ((nNeeded == 0) || (nNeeded == this.nRemove)) {
|
||||
this.done();
|
||||
}
|
||||
|
||||
final StringBuilder msg = new StringBuilder("Remove ");
|
||||
final int nLeft = nNeeded - this.nRemove;
|
||||
msg.append(nLeft).append(" ");
|
||||
msg.append(costRemoveCounter.getCounter().getName()).append(" counters from ");
|
||||
msg.append(costRemoveCounter.getDescriptiveType());
|
||||
|
||||
this.typeList = CardLists.getValidCards(sa.getActivatingPlayer().getCardsIn(costRemoveCounter.getZone()), type.split(";"), sa.getActivatingPlayer(), sa.getSourceCard());
|
||||
|
||||
// TODO Tabulate typelist vs nNeeded to see if there are enough counters to remove
|
||||
|
||||
CMatchUI.SINGLETON_INSTANCE.showMessage(msg.toString());
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(final Card card) {
|
||||
if (this.typeList.contains(card)) {
|
||||
if (card.getCounters(costRemoveCounter.getCounter()) > 0) {
|
||||
this.nRemove++;
|
||||
costRemoveCounter.addToList(card);
|
||||
card.subtractCounter(costRemoveCounter.getCounter(), 1);
|
||||
|
||||
if (nNeeded == this.nRemove) {
|
||||
this.done();
|
||||
} else {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void done() {
|
||||
this.stop();
|
||||
costRemoveCounter.addListToHash(sa, "CounterRemove");
|
||||
payment.paidCost(costRemoveCounter);
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
this.stop();
|
||||
costRemoveCounter.addListToHash(sa, "CounterRemove");
|
||||
payment.cancelCost(costRemoveCounter);
|
||||
}
|
||||
};
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* returnType.
|
||||
* </p>
|
||||
*
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param type
|
||||
* a {@link java.lang.String} object.
|
||||
* @param payment
|
||||
* a {@link forge.card.cost.CostPayment} object.
|
||||
* @param costRemoveCounter
|
||||
* TODO
|
||||
* @param nNeeded
|
||||
* the n needed
|
||||
* @return a {@link forge.control.input.Input} object.
|
||||
*/
|
||||
public static Input removeCounterTypeFrom(final SpellAbility sa, final String type, final CostPayment payment,
|
||||
final CostRemoveCounter costRemoveCounter, final int nNeeded) {
|
||||
final Input target = new Input() {
|
||||
private static final long serialVersionUID = 734256837615635021L;
|
||||
private List<Card> typeList;
|
||||
private int nRemove = 0;
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
if (nNeeded == 0) {
|
||||
this.done();
|
||||
}
|
||||
|
||||
this.typeList = new ArrayList<Card>(sa.getActivatingPlayer().getCardsIn(costRemoveCounter.getZone()));
|
||||
this.typeList = CardLists.getValidCards(this.typeList, type.split(";"), sa.getActivatingPlayer(), sa.getSourceCard());
|
||||
|
||||
for (int i = 0; i < nNeeded; i++) {
|
||||
if (this.typeList.size() == 0) {
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
final Card o = GuiChoose
|
||||
.oneOrNone("Remove counter(s) from a card in " + costRemoveCounter.getZone(), this.typeList);
|
||||
|
||||
if (o != null) {
|
||||
final Card card = o;
|
||||
|
||||
if (card.getCounters(costRemoveCounter.getCounter()) > 0) {
|
||||
this.nRemove++;
|
||||
costRemoveCounter.addToList(card);
|
||||
card.subtractCounter(costRemoveCounter.getCounter(), 1);
|
||||
|
||||
if (card.getCounters(costRemoveCounter.getCounter()) == 0) {
|
||||
this.typeList.remove(card);
|
||||
}
|
||||
|
||||
if (nNeeded == this.nRemove) {
|
||||
this.done();
|
||||
} else {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.cancel();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
public void done() {
|
||||
this.stop();
|
||||
costRemoveCounter.addListToHash(sa, "CounterRemove");
|
||||
payment.paidCost(costRemoveCounter);
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
this.stop();
|
||||
costRemoveCounter.addListToHash(sa, "CounterRemove");
|
||||
payment.cancelCost();
|
||||
}
|
||||
};
|
||||
return target;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,7 @@ package forge.card.cost;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import forge.Card;
|
||||
import forge.CardLists;
|
||||
@@ -33,6 +32,7 @@ import forge.game.ai.ComputerUtil;
|
||||
import forge.game.player.AIPlayer;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.gui.GuiDialog;
|
||||
import forge.gui.match.CMatchUI;
|
||||
import forge.view.ButtonUtil;
|
||||
|
||||
@@ -42,6 +42,96 @@ import forge.view.ButtonUtil;
|
||||
public class CostReturn extends CostPartWithList {
|
||||
// Return<Num/Type{/TypeDescription}>
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public static final class InputPayReturnType extends Input {
|
||||
private final SpellAbility sa;
|
||||
private final CostReturn part;
|
||||
private final int nNeeded;
|
||||
private final String type;
|
||||
private final CostPayment payment;
|
||||
private static final long serialVersionUID = 2685832214519141903L;
|
||||
private List<Card> typeList;
|
||||
private int nReturns = 0;
|
||||
private final CountDownLatch cdlDone;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for Constructor.
|
||||
* @param sa
|
||||
* @param part
|
||||
* @param nNeeded
|
||||
* @param cdl
|
||||
* @param type
|
||||
* @param payment
|
||||
*/
|
||||
public InputPayReturnType(CountDownLatch cdl, SpellAbility sa, CostReturn part, int nNeeded, String type,
|
||||
CostPayment payment) {
|
||||
this.sa = sa;
|
||||
this.part = part;
|
||||
this.nNeeded = nNeeded;
|
||||
this.type = type;
|
||||
this.payment = payment;
|
||||
cdlDone = cdl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
if (nNeeded == 0) {
|
||||
this.done();
|
||||
}
|
||||
|
||||
final StringBuilder msg = new StringBuilder("Return ");
|
||||
final int nLeft = nNeeded - this.nReturns;
|
||||
msg.append(nLeft).append(" ");
|
||||
msg.append(type);
|
||||
if (nLeft > 1) {
|
||||
msg.append("s");
|
||||
}
|
||||
|
||||
this.typeList = new ArrayList<Card>(sa.getActivatingPlayer().getCardsIn(ZoneType.Battlefield));
|
||||
this.typeList = CardLists.getValidCards(this.typeList, type.split(";"), sa.getActivatingPlayer(), sa.getSourceCard());
|
||||
CMatchUI.SINGLETON_INSTANCE.showMessage(msg.toString());
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(final Card card) {
|
||||
if (this.typeList.contains(card)) {
|
||||
this.nReturns++;
|
||||
part.addToList(card);
|
||||
Singletons.getModel().getGame().getAction().moveToHand(card);
|
||||
this.typeList.remove(card);
|
||||
// in case nothing else to return
|
||||
if (this.nReturns == nNeeded) {
|
||||
this.done();
|
||||
} else if (this.typeList.size() == 0) {
|
||||
// happen
|
||||
this.cancel();
|
||||
} else {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void done() {
|
||||
this.stop();
|
||||
cdlDone.countDown();
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
this.stop();
|
||||
payment.cancelCost();
|
||||
cdlDone.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new cost return.
|
||||
*
|
||||
@@ -135,7 +225,7 @@ public class CostReturn extends CostPartWithList {
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
final String amount = this.getAmount();
|
||||
Integer c = this.convertAmount();
|
||||
final Player activator = ability.getActivatingPlayer();
|
||||
@@ -150,13 +240,25 @@ public class CostReturn extends CostPartWithList {
|
||||
}
|
||||
}
|
||||
if (this.payCostFromSource()) {
|
||||
final Input inp = CostReturn.returnThis(ability, payment, this);
|
||||
Singletons.getModel().getMatch().getInput().setInputInterrupt(inp);
|
||||
final Card card = ability.getSourceCard();
|
||||
if (card.getController() == ability.getActivatingPlayer() && card.isInPlay()) {
|
||||
boolean confirm = GuiDialog.confirm(card, card.getName() + " - Return to Hand?");
|
||||
if (confirm) {
|
||||
addToList(card);
|
||||
Singletons.getModel().getGame().getAction().moveToHand(card);
|
||||
} else {
|
||||
payment.cancelCost();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final Input inp = CostReturn.returnType(ability, this.getType(), payment, this, c);
|
||||
Singletons.getModel().getMatch().getInput().setInputInterrupt(inp);
|
||||
CountDownLatch cdl = new CountDownLatch(1);
|
||||
final Input target = new InputPayReturnType(cdl, ability, this, c, this.getType(), payment);
|
||||
final Input inp = target;
|
||||
setInputAndWait(inp, cdl);
|
||||
}
|
||||
return false;
|
||||
|
||||
if (!payment.isCanceled())
|
||||
addListToHash(ability, "Returned");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -187,131 +289,5 @@ public class CostReturn extends CostPartWithList {
|
||||
|
||||
// Inputs
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* returnType.
|
||||
* </p>
|
||||
*
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param type
|
||||
* a {@link java.lang.String} object.
|
||||
* @param payment
|
||||
* a {@link forge.card.cost.CostPayment} object.
|
||||
* @param part
|
||||
* TODO
|
||||
* @param nNeeded
|
||||
* the n needed
|
||||
* @return a {@link forge.control.input.Input} object.
|
||||
*/
|
||||
public static Input returnType(final SpellAbility sa, final String type, final CostPayment payment,
|
||||
final CostReturn part, final int nNeeded) {
|
||||
final Input target = new Input() {
|
||||
private static final long serialVersionUID = 2685832214519141903L;
|
||||
private List<Card> typeList;
|
||||
private int nReturns = 0;
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
if (nNeeded == 0) {
|
||||
this.done();
|
||||
}
|
||||
|
||||
final StringBuilder msg = new StringBuilder("Return ");
|
||||
final int nLeft = nNeeded - this.nReturns;
|
||||
msg.append(nLeft).append(" ");
|
||||
msg.append(type);
|
||||
if (nLeft > 1) {
|
||||
msg.append("s");
|
||||
}
|
||||
|
||||
this.typeList = new ArrayList<Card>(sa.getActivatingPlayer().getCardsIn(ZoneType.Battlefield));
|
||||
this.typeList = CardLists.getValidCards(this.typeList, type.split(";"), sa.getActivatingPlayer(), sa.getSourceCard());
|
||||
CMatchUI.SINGLETON_INSTANCE.showMessage(msg.toString());
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(final Card card) {
|
||||
if (this.typeList.contains(card)) {
|
||||
this.nReturns++;
|
||||
part.addToList(card);
|
||||
Singletons.getModel().getGame().getAction().moveToHand(card);
|
||||
this.typeList.remove(card);
|
||||
// in case nothing else to return
|
||||
if (this.nReturns == nNeeded) {
|
||||
this.done();
|
||||
} else if (this.typeList.size() == 0) {
|
||||
// happen
|
||||
this.cancel();
|
||||
} else {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void done() {
|
||||
this.stop();
|
||||
part.addListToHash(sa, "Returned");
|
||||
payment.paidCost(part);
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
this.stop();
|
||||
payment.cancelCost();
|
||||
}
|
||||
};
|
||||
|
||||
return target;
|
||||
} // returnType()
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* returnThis.
|
||||
* </p>
|
||||
*
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param payment
|
||||
* a {@link forge.card.cost.CostPayment} object.
|
||||
* @param part
|
||||
* TODO
|
||||
* @return a {@link forge.control.input.Input} object.
|
||||
*/
|
||||
public static Input returnThis(final SpellAbility sa, final CostPayment payment, final CostReturn part) {
|
||||
final Input target = new Input() {
|
||||
private static final long serialVersionUID = 2685832214519141903L;
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
final Card card = sa.getSourceCard();
|
||||
if (card.getController().isHuman() && card.isInPlay()) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(card.getName());
|
||||
sb.append(" - Return to Hand?");
|
||||
final Object[] possibleValues = { "Yes", "No" };
|
||||
final Object choice = JOptionPane.showOptionDialog(null, sb.toString(), card.getName() + " - Cost",
|
||||
JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, possibleValues,
|
||||
possibleValues[0]);
|
||||
if (choice.equals(0)) {
|
||||
part.addToList(card);
|
||||
Singletons.getModel().getGame().getAction().moveToHand(card);
|
||||
this.stop();
|
||||
part.addListToHash(sa, "Returned");
|
||||
payment.paidCost(part);
|
||||
} else {
|
||||
this.stop();
|
||||
payment.cancelCost();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return target;
|
||||
} // input_sacrifice()
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package forge.card.cost;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import forge.Card;
|
||||
import forge.CardLists;
|
||||
@@ -41,6 +42,108 @@ import forge.view.ButtonUtil;
|
||||
public class CostReveal extends CostPartWithList {
|
||||
// Reveal<Num/Type/TypeDescription>
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public static final class InputPayReveal extends Input {
|
||||
private final CostReveal part;
|
||||
private final String discType;
|
||||
private final List<Card> handList;
|
||||
private final SpellAbility sa;
|
||||
private final CostPayment payment;
|
||||
private final int nNeeded;
|
||||
private static final long serialVersionUID = -329993322080934435L;
|
||||
private int nReveal = 0;
|
||||
private final CountDownLatch cdlDone;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for Constructor.
|
||||
* @param part
|
||||
* @param discType
|
||||
* @param handList
|
||||
* @param sa
|
||||
* @param payment
|
||||
* @param nNeeded
|
||||
*/
|
||||
public InputPayReveal(CountDownLatch cdl, CostReveal part, String discType, List<Card> handList, SpellAbility sa,
|
||||
CostPayment payment, int nNeeded) {
|
||||
this.cdlDone = cdl;
|
||||
this.part = part;
|
||||
this.discType = discType;
|
||||
this.handList = handList;
|
||||
this.sa = sa;
|
||||
this.payment = payment;
|
||||
this.nNeeded = nNeeded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
if (nNeeded == 0) {
|
||||
this.done();
|
||||
}
|
||||
|
||||
/*if (handList.size() + this.nReveal < nNeeded) {
|
||||
this.stop();
|
||||
}*/
|
||||
final StringBuilder type = new StringBuilder("");
|
||||
if (!discType.equals("Card")) {
|
||||
type.append(" ").append(discType);
|
||||
}
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("Select a ");
|
||||
sb.append(part.getDescriptiveType());
|
||||
sb.append(" to reveal.");
|
||||
if (nNeeded > 1) {
|
||||
sb.append(" You have ");
|
||||
sb.append(nNeeded - this.nReveal);
|
||||
sb.append(" remaining.");
|
||||
}
|
||||
CMatchUI.SINGLETON_INSTANCE.showMessage(sb.toString());
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(final Card card) {
|
||||
Zone zone = Singletons.getModel().getGame().getZoneOf(card);
|
||||
if (zone.is(ZoneType.Hand) && handList.contains(card)) {
|
||||
// send in List<Card> for Typing
|
||||
handList.remove(card);
|
||||
part.addToList(card);
|
||||
this.nReveal++;
|
||||
|
||||
// in case no more cards in hand
|
||||
if (this.nReveal == nNeeded) {
|
||||
this.done();
|
||||
} else if (sa.getActivatingPlayer().getZone(ZoneType.Hand).size() == 0) {
|
||||
// really
|
||||
// shouldn't
|
||||
// happen
|
||||
this.cancel();
|
||||
} else {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
this.stop();
|
||||
payment.cancelCost();
|
||||
cdlDone.countDown();
|
||||
}
|
||||
|
||||
public void done() {
|
||||
this.stop();
|
||||
// "Inform" AI of the revealed cards
|
||||
cdlDone.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new cost reveal.
|
||||
*
|
||||
@@ -150,17 +253,15 @@ public class CostReveal extends CostPartWithList {
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
final Player activator = ability.getActivatingPlayer();
|
||||
final String amount = this.getAmount();
|
||||
this.resetList();
|
||||
|
||||
if (this.payCostFromSource()) {
|
||||
this.addToList(source);
|
||||
payment.setPaidManaPart(this);
|
||||
} else if (this.getType().equals("Hand")) {
|
||||
this.setList(new ArrayList<Card>(activator.getCardsIn(ZoneType.Hand)));
|
||||
payment.setPaidManaPart(this);
|
||||
} else {
|
||||
Integer num = this.convertAmount();
|
||||
|
||||
@@ -176,15 +277,13 @@ public class CostReveal extends CostPartWithList {
|
||||
}
|
||||
}
|
||||
if (num > 0) {
|
||||
final Input inp = CostReveal.inputRevealCost(this.getType(), handList, payment, this, ability, num);
|
||||
Singletons.getModel().getMatch().getInput().setInputInterrupt(inp);
|
||||
return false;
|
||||
} else {
|
||||
payment.setPaidManaPart(this);
|
||||
}
|
||||
final CountDownLatch cdl = new CountDownLatch(1);
|
||||
final Input inp = new InputPayReveal(cdl, this, this.getType(), handList, ability, payment, num);;
|
||||
setInputAndWait(inp, cdl);
|
||||
}
|
||||
}
|
||||
this.addListToHash(ability, "Revealed");
|
||||
return true;
|
||||
if ( !payment.isCanceled())
|
||||
this.addListToHash(ability, "Revealed");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -222,100 +321,5 @@ public class CostReveal extends CostPartWithList {
|
||||
|
||||
// Inputs
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* input_discardCost.
|
||||
* </p>
|
||||
*
|
||||
* @param discType
|
||||
* a {@link java.lang.String} object.
|
||||
* @param handList
|
||||
* a {@link forge.CardList} object.
|
||||
* @param payment
|
||||
* a {@link forge.card.cost.CostPayment} object.
|
||||
* @param part
|
||||
* TODO
|
||||
* @param sa
|
||||
* TODO
|
||||
* @param nNeeded
|
||||
* a int.
|
||||
* @return a {@link forge.control.input.Input} object.
|
||||
*/
|
||||
public static Input inputRevealCost(final String discType, final List<Card> handList, final CostPayment payment,
|
||||
final CostReveal part, final SpellAbility sa, final int nNeeded) {
|
||||
final Input target = new Input() {
|
||||
private static final long serialVersionUID = -329993322080934435L;
|
||||
|
||||
private int nReveal = 0;
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
if (nNeeded == 0) {
|
||||
this.done();
|
||||
}
|
||||
|
||||
/*if (handList.size() + this.nReveal < nNeeded) {
|
||||
this.stop();
|
||||
}*/
|
||||
final StringBuilder type = new StringBuilder("");
|
||||
if (!discType.equals("Card")) {
|
||||
type.append(" ").append(discType);
|
||||
}
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("Select a ");
|
||||
sb.append(part.getDescriptiveType());
|
||||
sb.append(" to reveal.");
|
||||
if (nNeeded > 1) {
|
||||
sb.append(" You have ");
|
||||
sb.append(nNeeded - this.nReveal);
|
||||
sb.append(" remaining.");
|
||||
}
|
||||
CMatchUI.SINGLETON_INSTANCE.showMessage(sb.toString());
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(final Card card) {
|
||||
Zone zone = Singletons.getModel().getGame().getZoneOf(card);
|
||||
if (zone.is(ZoneType.Hand) && handList.contains(card)) {
|
||||
// send in List<Card> for Typing
|
||||
handList.remove(card);
|
||||
part.addToList(card);
|
||||
this.nReveal++;
|
||||
|
||||
// in case no more cards in hand
|
||||
if (this.nReveal == nNeeded) {
|
||||
this.done();
|
||||
} else if (sa.getActivatingPlayer().getZone(ZoneType.Hand).size() == 0) {
|
||||
// really
|
||||
// shouldn't
|
||||
// happen
|
||||
this.cancel();
|
||||
} else {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
this.stop();
|
||||
payment.cancelCost();
|
||||
}
|
||||
|
||||
public void done() {
|
||||
this.stop();
|
||||
// "Inform" AI of the revealed cards
|
||||
part.addListToHash(sa, "Revealed");
|
||||
payment.paidCost(part);
|
||||
}
|
||||
};
|
||||
|
||||
return target;
|
||||
} // input_discard()
|
||||
|
||||
}
|
||||
|
||||
@@ -19,20 +19,19 @@ package forge.card.cost;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import forge.Card;
|
||||
import forge.CardLists;
|
||||
import forge.Singletons;
|
||||
import forge.card.ability.AbilityUtils;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.control.input.Input;
|
||||
import forge.game.GameState;
|
||||
import forge.game.ai.ComputerUtil;
|
||||
import forge.game.player.AIPlayer;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.gui.GuiDialog;
|
||||
import forge.gui.match.CMatchUI;
|
||||
import forge.view.ButtonUtil;
|
||||
|
||||
@@ -41,6 +40,73 @@ import forge.view.ButtonUtil;
|
||||
*/
|
||||
public class CostSacrifice extends CostPartWithList {
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public static final class InputPayCostSacrificeFromList extends InputPayCostBase {
|
||||
private final CostSacrifice part;
|
||||
private final SpellAbility sa;
|
||||
private final int nNeeded;
|
||||
private final List<Card> typeList;
|
||||
private static final long serialVersionUID = 2685832214519141903L;
|
||||
private int nSacrifices = 0;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for Constructor.
|
||||
* @param part
|
||||
* @param sa
|
||||
* @param nNeeded
|
||||
* @param payment
|
||||
* @param typeList
|
||||
*/
|
||||
public InputPayCostSacrificeFromList(CountDownLatch cdl, CostSacrifice part, SpellAbility sa, int nNeeded, CostPayment payment,
|
||||
List<Card> typeList) {
|
||||
super(cdl, payment);
|
||||
this.part = part;
|
||||
this.sa = sa;
|
||||
this.nNeeded = nNeeded;
|
||||
this.typeList = typeList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
if (nNeeded == 0) {
|
||||
this.done();
|
||||
}
|
||||
|
||||
final StringBuilder msg = new StringBuilder("Sacrifice ");
|
||||
final int nLeft = nNeeded - this.nSacrifices;
|
||||
msg.append(nLeft).append(" ");
|
||||
msg.append(part.getDescriptiveType());
|
||||
if (nLeft > 1) {
|
||||
msg.append("s");
|
||||
}
|
||||
|
||||
CMatchUI.SINGLETON_INSTANCE.showMessage(msg.toString());
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(final Card card) {
|
||||
if (typeList.contains(card)) {
|
||||
this.nSacrifices++;
|
||||
part.addToList(card);
|
||||
Singletons.getModel().getGame().getAction().sacrifice(card, sa);
|
||||
typeList.remove(card);
|
||||
// in case nothing else to sacrifice
|
||||
if (this.nSacrifices == nNeeded) {
|
||||
this.done();
|
||||
} else if (typeList.size() == 0) {
|
||||
// happen
|
||||
this.cancel();
|
||||
} else {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new cost sacrifice.
|
||||
*
|
||||
@@ -144,7 +210,7 @@ public class CostSacrifice extends CostPartWithList {
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
final String amount = this.getAmount();
|
||||
final String type = this.getType();
|
||||
final Player activator = ability.getActivatingPlayer();
|
||||
@@ -155,33 +221,41 @@ public class CostSacrifice extends CostPartWithList {
|
||||
}
|
||||
|
||||
if (this.payCostFromSource()) {
|
||||
final Input inp = CostSacrifice.sacrificeThis(ability, payment, this);
|
||||
Singletons.getModel().getMatch().getInput().setInputInterrupt(inp);
|
||||
final Card card = ability.getSourceCard();
|
||||
if (card.getController() == ability.getActivatingPlayer() && card.isInPlay()) {
|
||||
if (GuiDialog.confirm(card, card.getName() + " - Sacrifice?")) {
|
||||
this.addToList(card);
|
||||
Singletons.getModel().getGame().getAction().sacrifice(card, ability);
|
||||
} else {
|
||||
payment.cancelCost();
|
||||
}
|
||||
}
|
||||
} else if (amount.equals("All")) {
|
||||
this.setList(list);
|
||||
CostSacrifice.sacrificeAll(ability, payment, this, list);
|
||||
//this.addListToHash(ability, "Sacrificed");
|
||||
return true;
|
||||
// TODO Ask First
|
||||
for (final Card card : list) {
|
||||
payment.getAbility().addCostToHashList(card, "Sacrificed");
|
||||
Singletons.getModel().getGame().getAction().sacrifice(card, ability);
|
||||
}
|
||||
payment.setPaidPart(this);
|
||||
} else {
|
||||
Integer c = this.convertAmount();
|
||||
if (c == null) {
|
||||
final String sVar = ability.getSVar(amount);
|
||||
// Generalize this
|
||||
if (sVar.equals("XChoice")) {
|
||||
if (ability.getSVar(amount).equals("XChoice")) {
|
||||
c = CostUtil.chooseXValue(source, ability, list.size());
|
||||
} else {
|
||||
c = AbilityUtils.calculateAmount(source, amount, ability);
|
||||
}
|
||||
}
|
||||
if (0 == c.intValue()) {
|
||||
payment.setPaidManaPart(this);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
final Input inp = CostSacrifice.sacrificeFromList(ability, payment, this, list, c);
|
||||
Singletons.getModel().getMatch().getInput().setInputInterrupt(inp);
|
||||
final CountDownLatch cdl = new CountDownLatch(1);
|
||||
setInputAndWait(new InputPayCostSacrificeFromList(cdl, this, ability, c, payment, list), cdl);
|
||||
}
|
||||
|
||||
return false;
|
||||
if( !payment.isCanceled())
|
||||
addListToHash(ability, "Sacrificed");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -224,154 +298,4 @@ public class CostSacrifice extends CostPartWithList {
|
||||
|
||||
// Inputs
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* sacrificeAllType.
|
||||
* </p>
|
||||
*
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param payment
|
||||
* a {@link forge.card.cost.CostPayment} object.
|
||||
* @param part
|
||||
* TODO
|
||||
* @param typeList
|
||||
* TODO
|
||||
*/
|
||||
public static void sacrificeAll(final SpellAbility sa, final CostPayment payment, final CostPart part,
|
||||
final List<Card> typeList) {
|
||||
// TODO Ask First
|
||||
for (final Card card : typeList) {
|
||||
payment.getAbility().addCostToHashList(card, "Sacrificed");
|
||||
Singletons.getModel().getGame().getAction().sacrifice(card, sa);
|
||||
}
|
||||
|
||||
payment.setPaidManaPart(part);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* sacrificeFromList.
|
||||
* </p>
|
||||
*
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param payment
|
||||
* a {@link forge.card.cost.CostPayment} object.
|
||||
* @param part
|
||||
* TODO
|
||||
* @param typeList
|
||||
* TODO
|
||||
* @param nNeeded
|
||||
* the n needed
|
||||
* @return a {@link forge.control.input.Input} object.
|
||||
*/
|
||||
public static Input sacrificeFromList(final SpellAbility sa, final CostPayment payment, final CostSacrifice part,
|
||||
final List<Card> typeList, final int nNeeded) {
|
||||
final Input target = new Input() {
|
||||
private static final long serialVersionUID = 2685832214519141903L;
|
||||
private int nSacrifices = 0;
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
if (nNeeded == 0) {
|
||||
this.done();
|
||||
}
|
||||
|
||||
final StringBuilder msg = new StringBuilder("Sacrifice ");
|
||||
final int nLeft = nNeeded - this.nSacrifices;
|
||||
msg.append(nLeft).append(" ");
|
||||
msg.append(part.getDescriptiveType());
|
||||
if (nLeft > 1) {
|
||||
msg.append("s");
|
||||
}
|
||||
|
||||
CMatchUI.SINGLETON_INSTANCE.showMessage(msg.toString());
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(final Card card) {
|
||||
if (typeList.contains(card)) {
|
||||
this.nSacrifices++;
|
||||
part.addToList(card);
|
||||
Singletons.getModel().getGame().getAction().sacrifice(card, sa);
|
||||
typeList.remove(card);
|
||||
// in case nothing else to sacrifice
|
||||
if (this.nSacrifices == nNeeded) {
|
||||
this.done();
|
||||
} else if (typeList.size() == 0) {
|
||||
// happen
|
||||
this.cancel();
|
||||
} else {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void done() {
|
||||
this.stop();
|
||||
part.addListToHash(sa, "Sacrificed");
|
||||
payment.paidCost(part);
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
this.stop();
|
||||
|
||||
payment.cancelCost();
|
||||
}
|
||||
};
|
||||
|
||||
return target;
|
||||
} // sacrificeType()
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* sacrificeThis.
|
||||
* </p>
|
||||
*
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param payment
|
||||
* a {@link forge.card.cost.CostPayment} object.
|
||||
* @param part
|
||||
* TODO
|
||||
* @return a {@link forge.control.input.Input} object.
|
||||
*/
|
||||
public static Input sacrificeThis(final SpellAbility sa, final CostPayment payment, final CostSacrifice part) {
|
||||
final Input target = new Input() {
|
||||
private static final long serialVersionUID = 2685832214519141903L;
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
final Card card = sa.getSourceCard();
|
||||
if (card.getController().isHuman() && card.isInPlay()) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(card.getName());
|
||||
sb.append(" - Sacrifice?");
|
||||
final Object[] possibleValues = { "Yes", "No" };
|
||||
final Object choice = JOptionPane.showOptionDialog(null, sb.toString(), card.getName() + " - Cost",
|
||||
JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, possibleValues,
|
||||
possibleValues[0]);
|
||||
if (choice.equals(0)) {
|
||||
part.addToList(card);
|
||||
part.addListToHash(sa, "Sacrificed");
|
||||
Singletons.getModel().getGame().getAction().sacrifice(card, sa);
|
||||
this.stop();
|
||||
payment.paidCost(part);
|
||||
} else {
|
||||
this.stop();
|
||||
payment.cancelCost();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return target;
|
||||
} // input_sacrifice()
|
||||
}
|
||||
|
||||
@@ -93,14 +93,12 @@ public class CostTap extends CostPart {
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
// if (!canPay(ability, source, ability.getActivatingPlayer(),
|
||||
// payment.getCost()))
|
||||
// return false;
|
||||
|
||||
source.tap();
|
||||
payment.setPaidManaPart(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -19,6 +19,7 @@ package forge.card.cost;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import forge.Card;
|
||||
import forge.CardLists;
|
||||
@@ -41,6 +42,88 @@ import forge.view.ButtonUtil;
|
||||
*/
|
||||
public class CostTapType extends CostPartWithList {
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public static final class InputPayCostTapType extends Input {
|
||||
private final CostTapType tapType;
|
||||
private final int nCards;
|
||||
private final List<Card> cardList;
|
||||
private final CostPayment payment;
|
||||
private static final long serialVersionUID = 6438988130447851042L;
|
||||
private int nTapped = 0;
|
||||
private final CountDownLatch cdlDone;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for Constructor.
|
||||
* @param sa
|
||||
* @param tapType
|
||||
* @param nCards
|
||||
* @param cardList
|
||||
* @param payment
|
||||
*/
|
||||
public InputPayCostTapType(CountDownLatch cdl, CostTapType tapType, int nCards, List<Card> cardList,
|
||||
CostPayment payment) {
|
||||
cdlDone = cdl;
|
||||
this.tapType = tapType;
|
||||
this.nCards = nCards;
|
||||
this.cardList = cardList;
|
||||
this.payment = payment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
|
||||
final int left = nCards - this.nTapped;
|
||||
CMatchUI.SINGLETON_INSTANCE
|
||||
.showMessage("Select a " + tapType.getDescription() + " to tap (" + left + " left)");
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
if (nCards == 0) {
|
||||
this.done();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(final Card card) {
|
||||
Zone zone = Singletons.getModel().getGame().getZoneOf(card);
|
||||
if (zone.is(ZoneType.Battlefield) && cardList.contains(card) && card.isUntapped()) {
|
||||
// send in List<Card> for Typing
|
||||
card.tap();
|
||||
tapType.addToList(card);
|
||||
cardList.remove(card);
|
||||
|
||||
this.nTapped++;
|
||||
|
||||
if (this.nTapped == nCards) {
|
||||
this.done();
|
||||
} else if (cardList.size() == 0) {
|
||||
// happen
|
||||
this.cancel();
|
||||
} else {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
this.stop();
|
||||
payment.cancelCost();
|
||||
cdlDone.countDown();
|
||||
}
|
||||
|
||||
public void done() {
|
||||
this.stop();
|
||||
cdlDone.countDown();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new cost tap type.
|
||||
*
|
||||
@@ -149,7 +232,7 @@ public class CostTapType extends CostPartWithList {
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
List<Card> typeList = new ArrayList<Card>(ability.getActivatingPlayer().getCardsIn(ZoneType.Battlefield));
|
||||
typeList = CardLists.getValidCards(typeList, this.getType().split(";"), ability.getActivatingPlayer(), ability.getSourceCard());
|
||||
typeList = CardLists.filter(typeList, Presets.UNTAPPED);
|
||||
@@ -164,10 +247,10 @@ public class CostTapType extends CostPartWithList {
|
||||
c = AbilityUtils.calculateAmount(source, amount, ability);
|
||||
}
|
||||
}
|
||||
|
||||
final Input inp = CostTapType.inputTapXCost(this, typeList, ability, payment, c);
|
||||
Singletons.getModel().getMatch().getInput().setInputInterrupt(inp);
|
||||
return false;
|
||||
CountDownLatch cdl = new CountDownLatch(1);
|
||||
setInputAndWait(new InputPayCostTapType(cdl, this, c, typeList, payment), cdl);
|
||||
if( !payment.isCanceled())
|
||||
addListToHash(ability, "Tapped");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -207,81 +290,4 @@ public class CostTapType extends CostPartWithList {
|
||||
|
||||
// Inputs
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* input_tapXCost.
|
||||
* </p>
|
||||
*
|
||||
* @param tapType
|
||||
* the tap type
|
||||
* @param cardList
|
||||
* a {@link forge.CardList} object.
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param payment
|
||||
* a {@link forge.card.cost.CostPayment} object.
|
||||
* @param nCards
|
||||
* a int.
|
||||
* @return a {@link forge.control.input.Input} object.
|
||||
*/
|
||||
public static Input inputTapXCost(final CostTapType tapType, final List<Card> cardList, final SpellAbility sa,
|
||||
final CostPayment payment, final int nCards) {
|
||||
final Input target = new Input() {
|
||||
|
||||
private static final long serialVersionUID = 6438988130447851042L;
|
||||
private int nTapped = 0;
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
|
||||
final int left = nCards - this.nTapped;
|
||||
CMatchUI.SINGLETON_INSTANCE
|
||||
.showMessage("Select a " + tapType.getDescription() + " to tap (" + left + " left)");
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
if (nCards == 0) {
|
||||
this.done();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(final Card card) {
|
||||
Zone zone = Singletons.getModel().getGame().getZoneOf(card);
|
||||
if (zone.is(ZoneType.Battlefield) && cardList.contains(card) && card.isUntapped()) {
|
||||
// send in List<Card> for Typing
|
||||
card.tap();
|
||||
tapType.addToList(card);
|
||||
cardList.remove(card);
|
||||
|
||||
this.nTapped++;
|
||||
|
||||
if (this.nTapped == nCards) {
|
||||
this.done();
|
||||
} else if (cardList.size() == 0) {
|
||||
// happen
|
||||
this.cancel();
|
||||
} else {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
this.stop();
|
||||
payment.cancelCost();
|
||||
}
|
||||
|
||||
public void done() {
|
||||
this.stop();
|
||||
tapType.addListToHash(sa, "Tapped");
|
||||
payment.paidCost(tapType);
|
||||
}
|
||||
};
|
||||
|
||||
return target;
|
||||
} // input_tapXCost()
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ public class CostUnattach extends CostPartWithList {
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
this.resetList();
|
||||
Player activator = ability.getActivatingPlayer();
|
||||
Card cardToUnattach = findCardToUnattach(source, activator, ability);
|
||||
@@ -123,14 +123,9 @@ public class CostUnattach extends CostPartWithList {
|
||||
cardToUnattach.unEquipCard(equippingCard);
|
||||
this.addToList(cardToUnattach);
|
||||
this.addListToHash(ability, "Unattached");
|
||||
payment.setPaidManaPart(this);
|
||||
} else {
|
||||
payment.setCancel(true);
|
||||
payment.getRequirements().finishPaying();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private Card findCardToUnattach(final Card source, Player activator, SpellAbility ability) {
|
||||
|
||||
@@ -92,14 +92,12 @@ public class CostUntap extends CostPart {
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
// if (!canPay(ability, source, ability.getActivatingPlayer(),
|
||||
// payment.getCost()))
|
||||
// return false;
|
||||
|
||||
source.untap();
|
||||
payment.setPaidManaPart(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package forge.card.cost;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import forge.Card;
|
||||
import forge.CardLists;
|
||||
@@ -25,7 +26,6 @@ import forge.CardPredicates.Presets;
|
||||
import forge.Singletons;
|
||||
import forge.card.ability.AbilityUtils;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.control.input.Input;
|
||||
import forge.game.GameState;
|
||||
import forge.game.ai.ComputerUtil;
|
||||
import forge.game.player.AIPlayer;
|
||||
@@ -40,6 +40,73 @@ import forge.view.ButtonUtil;
|
||||
*/
|
||||
public class CostUntapType extends CostPartWithList {
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public static final class InputPayCostUntapY extends InputPayCostBase {
|
||||
private final int nCards;
|
||||
private final List<Card> cardList;
|
||||
private final CostUntapType untapType;
|
||||
private static final long serialVersionUID = -7151144318287088542L;
|
||||
private int nUntapped = 0;
|
||||
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for Constructor.
|
||||
* @param nCards
|
||||
* @param cardList
|
||||
* @param untapType
|
||||
* @param sa
|
||||
* @param payment
|
||||
*/
|
||||
public InputPayCostUntapY(CountDownLatch cdl, int nCards, List<Card> cardList, CostUntapType untapType, CostPayment payment) {
|
||||
super(cdl, payment);
|
||||
this.nCards = nCards;
|
||||
this.cardList = cardList;
|
||||
this.untapType = untapType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
if (nCards == 0) {
|
||||
this.done();
|
||||
}
|
||||
|
||||
if (cardList.size() == 0) {
|
||||
this.stop();
|
||||
}
|
||||
|
||||
final int left = nCards - this.nUntapped;
|
||||
CMatchUI.SINGLETON_INSTANCE
|
||||
.showMessage("Select a " + untapType.getDescription() + " to untap (" + left + " left)");
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void selectCard(final Card card) {
|
||||
Zone zone = Singletons.getModel().getGame().getZoneOf(card);
|
||||
if (zone.is(ZoneType.Battlefield) && cardList.contains(card) && card.isTapped()) {
|
||||
// send in List<Card> for Typing
|
||||
card.untap();
|
||||
untapType.addToList(card);
|
||||
cardList.remove(card);
|
||||
|
||||
this.nUntapped++;
|
||||
|
||||
if (this.nUntapped == nCards) {
|
||||
this.done();
|
||||
} else if (cardList.size() == 0) {
|
||||
this.cancel();
|
||||
} else {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new cost untap type.
|
||||
*
|
||||
@@ -162,7 +229,7 @@ public class CostUntapType extends CostPartWithList {
|
||||
* forge.Card, forge.card.cost.Cost_Payment)
|
||||
*/
|
||||
@Override
|
||||
public final boolean payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
public final void payHuman(final SpellAbility ability, final Card source, final CostPayment payment, final GameState game) {
|
||||
final boolean untap = payment.getCost().hasUntapCost();
|
||||
List<Card> typeList = Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield);
|
||||
typeList = CardLists.getValidCards(typeList, this.getType().split(";"), ability.getActivatingPlayer(), ability.getSourceCard());
|
||||
@@ -181,10 +248,11 @@ public class CostUntapType extends CostPartWithList {
|
||||
c = AbilityUtils.calculateAmount(source, amount, ability);
|
||||
}
|
||||
}
|
||||
|
||||
final Input inp = CostUntapType.inputUntapYCost(this, typeList, ability, payment, c);
|
||||
Singletons.getModel().getMatch().getInput().setInputInterrupt(inp);
|
||||
return false;
|
||||
CountDownLatch cdl = new CountDownLatch(1);
|
||||
setInputAndWait(new InputPayCostUntapY(cdl, c, typeList, this, payment), cdl);
|
||||
|
||||
if ( !payment.isCanceled() )
|
||||
addListToHash(ability, "Untapped");
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -227,84 +295,4 @@ public class CostUntapType extends CostPartWithList {
|
||||
|
||||
// Inputs
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* input_untapYCost.
|
||||
* </p>
|
||||
*
|
||||
* @param untapType
|
||||
* the untap type
|
||||
* @param cardList
|
||||
* a {@link forge.CardList} object.
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param payment
|
||||
* a {@link forge.card.cost.CostPayment} object.
|
||||
* @param nCards
|
||||
* a int.
|
||||
* @return a {@link forge.control.input.Input} object.
|
||||
*/
|
||||
public static Input inputUntapYCost(final CostUntapType untapType, final List<Card> cardList, final SpellAbility sa,
|
||||
final CostPayment payment, final int nCards) {
|
||||
final Input target = new Input() {
|
||||
|
||||
private static final long serialVersionUID = -7151144318287088542L;
|
||||
private int nUntapped = 0;
|
||||
|
||||
@Override
|
||||
public void showMessage() {
|
||||
if (nCards == 0) {
|
||||
this.done();
|
||||
}
|
||||
|
||||
if (cardList.size() == 0) {
|
||||
this.stop();
|
||||
}
|
||||
|
||||
final int left = nCards - this.nUntapped;
|
||||
CMatchUI.SINGLETON_INSTANCE
|
||||
.showMessage("Select a " + untapType.getDescription() + " to untap (" + left + " left)");
|
||||
ButtonUtil.enableOnlyCancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(final Card card) {
|
||||
Zone zone = Singletons.getModel().getGame().getZoneOf(card);
|
||||
if (zone.is(ZoneType.Battlefield) && cardList.contains(card) && card.isTapped()) {
|
||||
// send in List<Card> for Typing
|
||||
card.untap();
|
||||
untapType.addToList(card);
|
||||
cardList.remove(card);
|
||||
|
||||
this.nUntapped++;
|
||||
|
||||
if (this.nUntapped == nCards) {
|
||||
this.done();
|
||||
} else if (cardList.size() == 0) {
|
||||
this.cancel();
|
||||
} else {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
this.stop();
|
||||
payment.cancelCost();
|
||||
}
|
||||
|
||||
public void done() {
|
||||
this.stop();
|
||||
untapType.addListToHash(sa, "Untapped");
|
||||
payment.paidCost(untapType);
|
||||
}
|
||||
};
|
||||
|
||||
return target;
|
||||
} // input_untapYCost()
|
||||
}
|
||||
|
||||
41
src/main/java/forge/card/cost/InputPayCostBase.java
Normal file
41
src/main/java/forge/card/cost/InputPayCostBase.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package forge.card.cost;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import forge.control.input.Input;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
abstract class InputPayCostBase extends Input {
|
||||
private static final long serialVersionUID = -2967434867139585579L;
|
||||
|
||||
private final CountDownLatch cdlDone;
|
||||
private final CostPayment payment;
|
||||
/**
|
||||
* TODO: Write javadoc for Constructor.
|
||||
* @param cdl
|
||||
* @param payment
|
||||
*/
|
||||
public InputPayCostBase(CountDownLatch cdl, CostPayment payment0) {
|
||||
cdlDone = cdl;
|
||||
payment = payment0;
|
||||
}
|
||||
|
||||
@Override
|
||||
final public void selectButtonCancel() {
|
||||
this.cancel();
|
||||
}
|
||||
|
||||
final protected void done() {
|
||||
this.stop();
|
||||
cdlDone.countDown();
|
||||
}
|
||||
|
||||
final public void cancel() {
|
||||
this.stop();
|
||||
payment.cancelCost();
|
||||
cdlDone.countDown();
|
||||
}
|
||||
}
|
||||
@@ -176,29 +176,11 @@ public class SpellAbilityRequirements {
|
||||
*/
|
||||
public final void needPayment() {
|
||||
if (!this.isFree) {
|
||||
this.startPaying();
|
||||
} else {
|
||||
this.finishPaying();
|
||||
}
|
||||
}
|
||||
this.payment.setRequirements(this);
|
||||
this.payment.changeCost();
|
||||
this.payment.payCost();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* startPaying.
|
||||
* </p>
|
||||
*/
|
||||
public final void startPaying() {
|
||||
this.payment.setRequirements(this);
|
||||
this.payment.changeCost();
|
||||
this.payment.payCost();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* finishPaying.
|
||||
* </p>
|
||||
*/
|
||||
public final void finishPaying() {
|
||||
if (this.payment.isCanceled()) {
|
||||
final Card c = this.ability.getSourceCard();
|
||||
|
||||
|
||||
@@ -155,7 +155,8 @@ public enum FControl {
|
||||
|
||||
this.shortcuts = KeyboardShortcuts.attachKeyboardShortcuts();
|
||||
this.display = FView.SINGLETON_INSTANCE.getLpnDocument();
|
||||
|
||||
|
||||
FSkin.setProgessBarMessage("About to load current quest.");
|
||||
// Preload quest data if present
|
||||
final File dirQuests = new File(NewConstants.QUEST_SAVE_DIR);
|
||||
final String questname = Singletons.getModel().getQuestPreferences().getPref(QPref.CURRENT_QUEST);
|
||||
@@ -164,6 +165,7 @@ public enum FControl {
|
||||
Singletons.getModel().getQuest().load(QuestDataIO.loadData(data));
|
||||
}
|
||||
|
||||
FSkin.setProgessBarMessage("Will load AI profiles now.");
|
||||
// Preload AI profiles
|
||||
AiProfileUtil.loadAllProfiles();
|
||||
|
||||
@@ -178,6 +180,7 @@ public enum FControl {
|
||||
FView.SINGLETON_INSTANCE.getLpnDocument().addMouseListener(SOverflowUtil.getHideOverflowListener());
|
||||
FView.SINGLETON_INSTANCE.getLpnDocument().addComponentListener(SResizingUtil.getWindowResizeListener());
|
||||
|
||||
FSkin.setProgessBarMessage("Opening main window...");
|
||||
SwingUtilities.invokeLater(new Runnable() { @Override
|
||||
public void run() { Singletons.getView().initialize(); } });
|
||||
}
|
||||
|
||||
@@ -114,7 +114,8 @@ public class InputControl extends MyObservable implements java.io.Serializable {
|
||||
* a boolean.
|
||||
*/
|
||||
public final void resetInput() {
|
||||
this.inputStack.pop();
|
||||
if ( !this.inputStack.isEmpty() )
|
||||
this.inputStack.pop();
|
||||
this.updateObservers();
|
||||
}
|
||||
|
||||
@@ -208,8 +209,9 @@ public class InputControl extends MyObservable implements java.io.Serializable {
|
||||
PhaseHandler ph = game.getPhaseHandler();
|
||||
|
||||
final Input tmp = getActualInput();
|
||||
String message = String.format("%s's %s, priority of %s [%sP] input is %s", ph.getPlayerTurn(), ph.getPhase(), ph.getPriorityPlayer(), ph.isPlayerPriorityAllowed() ? "+" : "-", tmp == null ? "null" : tmp.getClass().getSimpleName());
|
||||
String message = String.format("%s's %s, priority of %s [%sP] input is %s \t stack:%s", ph.getPlayerTurn(), ph.getPhase(), ph.getPriorityPlayer(), ph.isPlayerPriorityAllowed() ? "+" : "-", tmp == null ? "null" : tmp.getClass().getSimpleName(), inputStack);
|
||||
System.out.println(message);
|
||||
|
||||
if (tmp != null) {
|
||||
//System.out.println(ph.getPlayerTurn() + "'s " + ph.getPhase() + ", priority of " + ph.getPriorityPlayer() + " @ input is " + tmp.getClass().getName() );
|
||||
CMessage.SINGLETON_INSTANCE.getInputControl().setInput(tmp);
|
||||
@@ -219,4 +221,18 @@ public class InputControl extends MyObservable implements java.io.Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
*/
|
||||
private final static InputLockUI inpuptLock = new InputLockUI();
|
||||
public void lock() {
|
||||
setInput(inpuptLock);
|
||||
}
|
||||
|
||||
public void unlock() {
|
||||
if ( inputStack.isEmpty() || inputStack.peek() != inpuptLock )
|
||||
throw new RuntimeException("Trying to unlock input which is not locked! Do check when your threads terminate!");
|
||||
resetInput();
|
||||
}
|
||||
|
||||
} // InputControl
|
||||
|
||||
@@ -14,5 +14,10 @@ public class InputLockUI extends Input {
|
||||
ButtonUtil.disableAll();
|
||||
CMatchUI.SINGLETON_INSTANCE.showMessage("Waiting for actions...");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "lockUI";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ import forge.view.ButtonUtil;
|
||||
* @author Forge
|
||||
* @version $Id: InputPayManaCostAbility.java 15673 2012-05-23 14:01:35Z ArsenalNut $
|
||||
*/
|
||||
public class InputPayDiscardCost extends Input {
|
||||
public class InputPayDiscardCostWithCommands extends Input {
|
||||
/**
|
||||
* Constant <code>serialVersionUID=2685832214529141991L</code>.
|
||||
*/
|
||||
@@ -70,7 +70,7 @@ public class InputPayDiscardCost extends Input {
|
||||
* @param unpaidCommand
|
||||
* a {@link forge.Command} object.
|
||||
*/
|
||||
public InputPayDiscardCost(final CostDiscard cost, final SpellAbility sa, final Command paidCommand,
|
||||
public InputPayDiscardCostWithCommands(final CostDiscard cost, final SpellAbility sa, final Command paidCommand,
|
||||
final Command unpaidCommand) {
|
||||
final Card source = sa.getSourceCard();
|
||||
final Player human = Singletons.getControl().getPlayer();
|
||||
@@ -9,6 +9,7 @@ import java.util.Map;
|
||||
import forge.Card;
|
||||
import forge.CardUtil;
|
||||
import forge.Constant;
|
||||
import forge.FThreads;
|
||||
import forge.Singletons;
|
||||
import forge.card.MagicColor;
|
||||
import forge.card.ability.ApiType;
|
||||
@@ -18,7 +19,10 @@ import forge.card.spellability.AbilityManaPart;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.game.GameState;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.gui.GuiChoose;
|
||||
import forge.gui.framework.SDisplayUtil;
|
||||
import forge.gui.match.views.VMessage;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
@@ -33,19 +37,28 @@ public abstract class InputPayManaBase extends Input {
|
||||
protected final Player whoPays;
|
||||
protected final GameState game;
|
||||
protected ManaCostBeingPaid manaCost;
|
||||
protected final SpellAbility saPaidFor;
|
||||
|
||||
protected InputPayManaBase(final GameState game) {
|
||||
protected InputPayManaBase(final GameState game, SpellAbility saToPayFor) {
|
||||
this.game = game;
|
||||
this.whoPays = Singletons.getControl().getPlayer();
|
||||
this.saPaidFor = saToPayFor;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* selectManaPool.
|
||||
* </p>
|
||||
* @param color a String that represents the Color the mana is coming from
|
||||
*/
|
||||
public abstract void selectManaPool(String color);
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void selectCard(final Card card) {
|
||||
if (card.getManaAbility().isEmpty() || card.isInZone(ZoneType.Hand)) {
|
||||
SDisplayUtil.remind(VMessage.SINGLETON_INSTANCE);
|
||||
return;
|
||||
}
|
||||
// only tap card if the mana is needed
|
||||
activateManaAbility(card, this.manaCost);
|
||||
}
|
||||
|
||||
public void selectManaPool(String color) {
|
||||
useManaFromPool(color, this.manaCost);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -103,7 +116,7 @@ public abstract class InputPayManaBase extends Input {
|
||||
*
|
||||
* @return ManaCost the amount of mana remaining to be paid after the mana is activated
|
||||
*/
|
||||
protected static ManaCostBeingPaid activateManaAbility(String color, final SpellAbility saBeingPaidFor, ManaCostBeingPaid manaCost) {
|
||||
protected void useManaFromPool(String color, ManaCostBeingPaid manaCost) {
|
||||
ManaPool mp = Singletons.getControl().getPlayer().getManaPool();
|
||||
|
||||
// Convert Color to short String
|
||||
@@ -111,8 +124,10 @@ public abstract class InputPayManaBase extends Input {
|
||||
if (!color.equalsIgnoreCase("Colorless")) {
|
||||
manaStr = CardUtil.getShortColor(color);
|
||||
}
|
||||
|
||||
this.manaCost = mp.payManaFromPool(saPaidFor, manaCost, manaStr);
|
||||
|
||||
return mp.payManaFromPool(saBeingPaidFor, manaCost, manaStr);
|
||||
onManaAbilityPlayed(saPaidFor.getActivatingPlayer(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,10 +143,10 @@ public abstract class InputPayManaBase extends Input {
|
||||
* a {@link forge.card.mana.ManaCostBeingPaid} object.
|
||||
* @return a {@link forge.card.mana.ManaCostBeingPaid} object.
|
||||
*/
|
||||
protected ManaCostBeingPaid activateManaAbility(final SpellAbility sa, final Card card, ManaCostBeingPaid manaCost) {
|
||||
protected void activateManaAbility(final Card card, ManaCostBeingPaid manaCost) {
|
||||
// make sure computer's lands aren't selected
|
||||
if (card.getController() != whoPays) {
|
||||
return manaCost;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -170,7 +185,7 @@ public abstract class InputPayManaBase extends Input {
|
||||
continue;
|
||||
} else if (ma.isAbility() && ma.getRestrictions().isInstantSpeed()) {
|
||||
continue;
|
||||
} else if (!m.meetsManaRestrictions(sa)) {
|
||||
} else if (!m.meetsManaRestrictions(saPaidFor)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -185,16 +200,16 @@ public abstract class InputPayManaBase extends Input {
|
||||
}
|
||||
}
|
||||
if (abilities.isEmpty()) {
|
||||
return manaCost;
|
||||
return;
|
||||
}
|
||||
|
||||
// Store some information about color costs to help with any mana choices
|
||||
String colorsNeeded = colorRequired.toString();
|
||||
if ("1".equals(colorsNeeded)) { // only colorless left
|
||||
if (sa.getSourceCard() != null
|
||||
&& !sa.getSourceCard().getSVar("ManaNeededToAvoidNegativeEffect").equals("")) {
|
||||
if (saPaidFor.getSourceCard() != null
|
||||
&& !saPaidFor.getSourceCard().getSVar("ManaNeededToAvoidNegativeEffect").equals("")) {
|
||||
colorsNeeded = "";
|
||||
String[] negEffects = sa.getSourceCard().getSVar("ManaNeededToAvoidNegativeEffect").split(",");
|
||||
String[] negEffects = saPaidFor.getSourceCard().getSVar("ManaNeededToAvoidNegativeEffect").split(",");
|
||||
for (String negColor : negEffects) {
|
||||
// convert long color strings to short color strings
|
||||
if (negColor.length() > 1) {
|
||||
@@ -216,8 +231,8 @@ public abstract class InputPayManaBase extends Input {
|
||||
|
||||
// If the card has sunburst or any other ability that tracks mana spent,
|
||||
// skip express Mana choice
|
||||
if (sa.getSourceCard() != null
|
||||
&& sa.getSourceCard().hasKeyword("Sunburst") && sa.isSpell()) {
|
||||
if (saPaidFor.getSourceCard() != null
|
||||
&& saPaidFor.getSourceCard().hasKeyword("Sunburst") && saPaidFor.isSpell()) {
|
||||
colorsNeeded = "WUBRG";
|
||||
skipExpress = true;
|
||||
}
|
||||
@@ -255,7 +270,7 @@ public abstract class InputPayManaBase extends Input {
|
||||
}
|
||||
}
|
||||
|
||||
if ((colorMatches.size() == 0)) {
|
||||
if (colorMatches.isEmpty()) {
|
||||
// can only match colorless just grab the first and move on.
|
||||
choice = false;
|
||||
} else if (colorMatches.size() < abilities.size()) {
|
||||
@@ -282,14 +297,35 @@ public abstract class InputPayManaBase extends Input {
|
||||
// save off color needed for use by any mana and reflected mana
|
||||
subchosen.getManaPart().setExpressChoice(colorsNeeded);
|
||||
|
||||
System.out.println("Chosen sa=" + chosen + " of " + chosen.getSourceCard() + " to pay mana");
|
||||
Player p = chosen.getActivatingPlayer();
|
||||
Singletons.getModel().getGame().getActionPlay().playSpellAbility(chosen, p);
|
||||
|
||||
manaCost = p.getManaPool().payManaFromAbility(sa, manaCost, chosen);
|
||||
|
||||
//AllZone.getHumanPlayer().getZone(ZoneType.Battlefield).updateObservers();
|
||||
// DO NOT REMOVE THIS, otherwise the cards don't always tap (copied)
|
||||
return manaCost;
|
||||
|
||||
p.getGame().getActionPlay().playManaAbilityAsPayment(chosen, p, this);
|
||||
}
|
||||
|
||||
public void onManaAbilityPlayed(final Player p, final SpellAbility saPaymentSrc) {
|
||||
if ( saPaymentSrc != null) // null comes when they've paid from pool
|
||||
this.manaCost = p.getManaPool().payManaFromAbility(saPaidFor, manaCost, saPaymentSrc);
|
||||
|
||||
onManaAbilityPaid();
|
||||
|
||||
FThreads.invokeInEDT(new Runnable( ) {
|
||||
@Override
|
||||
public void run() {
|
||||
if (manaCost.isPaid()) {
|
||||
done();
|
||||
} else if (Singletons.getModel().getMatch().getInput().getInput() == InputPayManaBase.this) {
|
||||
showMessage();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void onManaAbilityPaid() {} // some inputs overload it
|
||||
protected abstract void done();
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PayManaBase (" + manaCost.toString() + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,17 +17,13 @@
|
||||
*/
|
||||
package forge.control.input;
|
||||
|
||||
import forge.Card;
|
||||
import forge.Command;
|
||||
import forge.Singletons;
|
||||
import forge.card.mana.ManaCostBeingPaid;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.game.GameState;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.gui.framework.SDisplayUtil;
|
||||
import forge.gui.match.CMatchUI;
|
||||
import forge.gui.match.views.VMessage;
|
||||
import forge.view.ButtonUtil;
|
||||
|
||||
//if cost is paid, Command.execute() is called
|
||||
@@ -48,7 +44,6 @@ public class InputPayManaExecuteCommands extends InputPayManaBase {
|
||||
|
||||
private String originalManaCost;
|
||||
private String message = "";
|
||||
private SpellAbility fakeAbility;
|
||||
|
||||
|
||||
private Command paidCommand;
|
||||
@@ -93,17 +88,13 @@ public class InputPayManaExecuteCommands extends InputPayManaBase {
|
||||
* a boolean.
|
||||
*/
|
||||
public InputPayManaExecuteCommands(final GameState game, final String prompt, final String manaCost2, final Command paid, final Command unpaid, final boolean showOKButton) {
|
||||
super(game);
|
||||
this.fakeAbility = new SpellAbility(null) {
|
||||
super(game, new SpellAbility(null) {
|
||||
@Override
|
||||
public void resolve() {
|
||||
}
|
||||
public void resolve() {}
|
||||
|
||||
@Override
|
||||
public boolean canPlay() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
public boolean canPlay() { return false; }
|
||||
});
|
||||
this.originalManaCost = manaCost2;
|
||||
this.phyLifeToLose = 0;
|
||||
this.message = prompt;
|
||||
@@ -138,30 +129,14 @@ public class InputPayManaExecuteCommands extends InputPayManaBase {
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final void selectCard(final Card card) {
|
||||
// only tap card if the mana is needed
|
||||
this.manaCost = activateManaAbility(this.fakeAbility, card, this.manaCost);
|
||||
|
||||
if (card.getManaAbility().isEmpty() || card.isInZone(ZoneType.Hand)) {
|
||||
SDisplayUtil.remind(VMessage.SINGLETON_INSTANCE);
|
||||
}
|
||||
|
||||
if (this.manaCost.isPaid()) {
|
||||
this.done();
|
||||
} else {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
|
||||
private void done() {
|
||||
protected void done() {
|
||||
if (this.phyLifeToLose > 0) {
|
||||
Singletons.getControl().getPlayer().payLife(this.phyLifeToLose, null);
|
||||
}
|
||||
this.paidCommand.execute();
|
||||
this.resetManaCost();
|
||||
Singletons.getControl().getPlayer().getManaPool().clearManaPaid(this.fakeAbility, false);
|
||||
Singletons.getControl().getPlayer().getManaPool().clearManaPaid(this.saPaidFor, false);
|
||||
this.stop();
|
||||
}
|
||||
|
||||
@@ -170,7 +145,7 @@ public class InputPayManaExecuteCommands extends InputPayManaBase {
|
||||
public final void selectButtonCancel() {
|
||||
this.unpaidCommand.execute();
|
||||
this.resetManaCost();
|
||||
Singletons.getControl().getPlayer().getManaPool().refundManaPaid(this.fakeAbility, true);
|
||||
Singletons.getControl().getPlayer().getManaPool().refundManaPaid(this.saPaidFor, true);
|
||||
this.stop();
|
||||
}
|
||||
|
||||
@@ -204,20 +179,6 @@ public class InputPayManaExecuteCommands extends InputPayManaBase {
|
||||
CMatchUI.SINGLETON_INSTANCE.showMessage(msg.toString());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.control.input.InputMana#selectManaPool()
|
||||
*/
|
||||
@Override
|
||||
public void selectManaPool(String color) {
|
||||
this.manaCost = activateManaAbility(color, this.fakeAbility, this.manaCost);
|
||||
|
||||
if (this.manaCost.isPaid()) {
|
||||
this.done();
|
||||
} else {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void isClassUpdated() {
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package forge.control.input;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import forge.Card;
|
||||
import forge.Singletons;
|
||||
import forge.card.cost.CostPartMana;
|
||||
@@ -8,7 +10,6 @@ import forge.card.mana.ManaCostBeingPaid;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.game.GameState;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.gui.match.CMatchUI;
|
||||
import forge.view.ButtonUtil;
|
||||
|
||||
@@ -18,21 +19,20 @@ public class InputPayManaOfCostPayment extends InputPayManaBase {
|
||||
|
||||
// I would kill the one who made 2 classes like above
|
||||
private final String originalManaCost;
|
||||
private final SpellAbility sa;
|
||||
private final int manaToAdd;
|
||||
private final CostPayment payment;
|
||||
private final CountDownLatch cdlFinished;
|
||||
|
||||
public InputPayManaOfCostPayment(final GameState game, CostPartMana costMana, SpellAbility spellAbility, final CostPayment payment, int toAdd) {
|
||||
super(game);
|
||||
public InputPayManaOfCostPayment(final GameState game, CostPartMana costMana, SpellAbility spellAbility, final CostPayment payment, int toAdd, CountDownLatch cdl) {
|
||||
super(game, spellAbility);
|
||||
manaCost = new ManaCostBeingPaid(costMana.getManaToPay());
|
||||
manaCost.increaseColorlessMana(toAdd);
|
||||
|
||||
this.costMana = costMana;
|
||||
originalManaCost = costMana.getMana();
|
||||
sa = spellAbility;
|
||||
manaToAdd = toAdd;
|
||||
this.payment = payment;
|
||||
|
||||
cdlFinished = cdl;
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 3467312982164195091L;
|
||||
@@ -46,19 +46,6 @@ public class InputPayManaOfCostPayment extends InputPayManaBase {
|
||||
this.phyLifeToLose = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectCard(final Card card) {
|
||||
// prevent cards from tapping themselves if ability is a
|
||||
// tapability, although it should already be tapped
|
||||
this.manaCost = activateManaAbility(sa, card, this.manaCost);
|
||||
|
||||
if (this.manaCost.isPaid()) {
|
||||
this.done();
|
||||
} else if (Singletons.getModel().getMatch().getInput().getInput() == this) {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectPlayer(final Player player) {
|
||||
if (player == whoPays) {
|
||||
@@ -70,8 +57,9 @@ public class InputPayManaOfCostPayment extends InputPayManaBase {
|
||||
}
|
||||
}
|
||||
|
||||
private void done() {
|
||||
final Card source = sa.getSourceCard();
|
||||
@Override
|
||||
protected void done() {
|
||||
final Card source = saPaidFor.getSourceCard();
|
||||
if (this.phyLifeToLose > 0) {
|
||||
Singletons.getControl().getPlayer().payLife(this.phyLifeToLose, source);
|
||||
}
|
||||
@@ -81,47 +69,39 @@ public class InputPayManaOfCostPayment extends InputPayManaBase {
|
||||
this.stop();
|
||||
|
||||
if (costMana.hasNoXManaCost() || (manaToAdd > 0)) {
|
||||
payment.paidCost(costMana);
|
||||
payment.setPaidPart(costMana);
|
||||
} else {
|
||||
source.setXManaCostPaid(0);
|
||||
final Input inp = new InputPayManaX(game, sa, payment, costMana);
|
||||
final Input inp = new InputPayManaX(game, saPaidFor, payment, costMana, cdlFinished);
|
||||
Singletons.getModel().getMatch().getInput().setInputInterrupt(inp);
|
||||
}
|
||||
|
||||
// If this is a spell with convoke, re-tap all creatures used
|
||||
// for it.
|
||||
// This is done to make sure Taps triggers go off at the right
|
||||
// time
|
||||
// (i.e. AFTER cost payment, they are tapped previously as well
|
||||
// so that
|
||||
// any mana tapabilities can't be used in payment as well as
|
||||
// being tapped for convoke)
|
||||
// If this is a spell with convoke, re-tap all creatures used for it.
|
||||
// This is done to make sure Taps triggers go off at the right time
|
||||
// (i.e. AFTER cost payment, they are tapped previously as well so that
|
||||
// any mana tapabilities can't be used in payment as well as being tapped for convoke)
|
||||
|
||||
if (sa.getTappedForConvoke() != null) {
|
||||
for (final Card c : sa.getTappedForConvoke()) {
|
||||
handleConvokedCards(false);
|
||||
}
|
||||
|
||||
protected void handleConvokedCards(boolean isCancelled) {
|
||||
if (saPaidFor.getTappedForConvoke() != null) {
|
||||
for (final Card c : saPaidFor.getTappedForConvoke()) {
|
||||
c.setTapped(false);
|
||||
c.tap();
|
||||
if (!isCancelled)
|
||||
c.tap();
|
||||
}
|
||||
sa.clearTappedForConvoke();
|
||||
}
|
||||
|
||||
saPaidFor.clearTappedForConvoke();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
// If we're paying for a spell with convoke, untap all creatures
|
||||
// used for it.
|
||||
if (sa.getTappedForConvoke() != null) {
|
||||
for (final Card c : sa.getTappedForConvoke()) {
|
||||
c.setTapped(false);
|
||||
}
|
||||
sa.clearTappedForConvoke();
|
||||
}
|
||||
handleConvokedCards(true);
|
||||
|
||||
this.stop();
|
||||
this.resetManaCost();
|
||||
payment.cancelCost();
|
||||
Singletons.getControl().getPlayer().getZone(ZoneType.Battlefield).updateObservers();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -147,17 +127,6 @@ public class InputPayManaOfCostPayment extends InputPayManaBase {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectManaPool(String color) {
|
||||
manaCost = InputPayManaBase.activateManaAbility(color, sa, this.manaCost);
|
||||
|
||||
if (this.manaCost.isPaid()) {
|
||||
this.done();
|
||||
} else if (Singletons.getModel().getMatch().getInput().getInput() == this) {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void isClassUpdated() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
package forge.control.input;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import forge.Card;
|
||||
import forge.Singletons;
|
||||
import forge.card.mana.ManaCostBeingPaid;
|
||||
@@ -35,61 +36,23 @@ public class InputPayManaSimple extends InputPayManaBase {
|
||||
/** Constant <code>serialVersionUID=3467312982164195091L</code>. */
|
||||
private static final long serialVersionUID = 3467312982164195091L;
|
||||
|
||||
private boolean skipStack;
|
||||
private final SpellAbility spell;
|
||||
private final Card originalCard;
|
||||
private final String originalManaCost;
|
||||
private final CountDownLatch cdlNotify;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Constructor for Input_PayManaCost.
|
||||
* </p>
|
||||
*
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param noStack
|
||||
* a boolean.
|
||||
*/
|
||||
public InputPayManaSimple(final GameState game, final SpellAbility sa, final boolean noStack) {
|
||||
this(game, sa, game.getActionPlay().getSpellCostChange(sa, new ManaCostBeingPaid(sa.getManaCost())));
|
||||
this.skipStack = noStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Constructor for Input_PayManaCost.
|
||||
* </p>
|
||||
*
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
*/
|
||||
public InputPayManaSimple(final GameState game, final SpellAbility sa) {
|
||||
this(game, sa, new ManaCostBeingPaid(sa.getManaCost()));
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Constructor for Input_PayManaCost.
|
||||
* </p>
|
||||
*
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
*
|
||||
* @param manaCostToPay
|
||||
* a {@link forge.card.mana.ManaCostBeingPaid} object.
|
||||
*/
|
||||
public InputPayManaSimple(final GameState game, final SpellAbility sa, final ManaCostBeingPaid manaCostToPay) {
|
||||
super(game);
|
||||
public InputPayManaSimple(final GameState game, final SpellAbility sa, final ManaCostBeingPaid manaCostToPay, final CountDownLatch callOnDone) {
|
||||
super(game, sa);
|
||||
this.originalManaCost = manaCostToPay.toString(); // Change
|
||||
this.originalCard = sa.getSourceCard();
|
||||
this.spell = sa;
|
||||
|
||||
if (sa.getSourceCard().isCopiedSpell() && sa.isSpell()) {
|
||||
this.manaCost = new ManaCostBeingPaid("0");
|
||||
game.getStack().add(this.spell);
|
||||
game.getStack().add(this.saPaidFor);
|
||||
} else {
|
||||
this.manaCost = manaCostToPay;
|
||||
}
|
||||
|
||||
cdlNotify = callOnDone;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,24 +65,9 @@ public class InputPayManaSimple extends InputPayManaBase {
|
||||
this.phyLifeToLose = 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final void selectCard(final Card card) {
|
||||
// this is a hack, to prevent lands being able to use mana to pay their
|
||||
// own abilities from cards like
|
||||
// Kher Keep, Pendelhaven, Blinkmoth Nexus, and Mikokoro, Center of the
|
||||
// Sea, ....
|
||||
|
||||
this.manaCost = activateManaAbility(this.spell, card, this.manaCost);
|
||||
|
||||
// only show message if this is the active input
|
||||
if (Singletons.getModel().getMatch().getInput().getInput() == this) {
|
||||
this.showMessage();
|
||||
}
|
||||
|
||||
protected void onManaAbilityPaid() {
|
||||
if (this.manaCost.isPaid()) {
|
||||
this.originalCard.setSunburstValue(this.manaCost.getSunburst());
|
||||
this.done();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,27 +90,19 @@ public class InputPayManaSimple extends InputPayManaBase {
|
||||
* done.
|
||||
* </p>
|
||||
*/
|
||||
private void done() {
|
||||
@Override
|
||||
protected void done() {
|
||||
if (this.phyLifeToLose > 0) {
|
||||
whoPays.payLife(this.phyLifeToLose, this.originalCard);
|
||||
}
|
||||
if (this.spell.getSourceCard().isCopiedSpell()) {
|
||||
Singletons.getModel().getMatch().getInput().resetInput();
|
||||
} else {
|
||||
whoPays.getManaPool().clearManaPaid(this.spell, false);
|
||||
if (!this.saPaidFor.getSourceCard().isCopiedSpell()) {
|
||||
whoPays.getManaPool().clearManaPaid(this.saPaidFor, false);
|
||||
this.resetManaCost();
|
||||
|
||||
if (this.spell.isSpell()) {
|
||||
this.spell.setSourceCard(game.getAction().moveToStack(this.originalCard));
|
||||
if (this.saPaidFor.isSpell()) {
|
||||
this.saPaidFor.setSourceCard(game.getAction().moveToStack(this.originalCard));
|
||||
}
|
||||
|
||||
if (this.skipStack) {
|
||||
this.spell.resolve();
|
||||
} else {
|
||||
game.getStack().add(this.spell);
|
||||
}
|
||||
Singletons.getModel().getMatch().getInput().resetInput();
|
||||
|
||||
// If this is a spell with convoke, re-tap all creatures used for
|
||||
// it.
|
||||
// This is done to make sure Taps triggers go off at the right time
|
||||
@@ -171,30 +111,33 @@ public class InputPayManaSimple extends InputPayManaBase {
|
||||
// any mana tapabilities can't be used in payment as well as being
|
||||
// tapped for convoke)
|
||||
|
||||
if (this.spell.getTappedForConvoke() != null) {
|
||||
for (final Card c : this.spell.getTappedForConvoke()) {
|
||||
if (this.saPaidFor.getTappedForConvoke() != null) {
|
||||
for (final Card c : this.saPaidFor.getTappedForConvoke()) {
|
||||
c.setTapped(false);
|
||||
c.tap();
|
||||
}
|
||||
this.spell.clearTappedForConvoke();
|
||||
this.saPaidFor.clearTappedForConvoke();
|
||||
}
|
||||
}
|
||||
|
||||
Singletons.getModel().getMatch().getInput().resetInput();
|
||||
cdlNotify.countDown();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public final void selectButtonCancel() {
|
||||
// If this is a spell with convoke, untap all creatures used for it.
|
||||
if (this.spell.getTappedForConvoke() != null) {
|
||||
for (final Card c : this.spell.getTappedForConvoke()) {
|
||||
if (this.saPaidFor.getTappedForConvoke() != null) {
|
||||
for (final Card c : this.saPaidFor.getTappedForConvoke()) {
|
||||
c.setTapped(false);
|
||||
}
|
||||
this.spell.clearTappedForConvoke();
|
||||
this.saPaidFor.clearTappedForConvoke();
|
||||
}
|
||||
|
||||
this.resetManaCost();
|
||||
|
||||
whoPays.getManaPool().refundManaPaid(this.spell, true);
|
||||
whoPays.getManaPool().refundManaPaid(this.saPaidFor, true);
|
||||
whoPays.getZone(ZoneType.Battlefield).updateObservers(); // DO
|
||||
|
||||
this.stop();
|
||||
@@ -224,24 +167,6 @@ public class InputPayManaSimple extends InputPayManaBase {
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.control.input.InputMana#selectManaPool(String)
|
||||
*/
|
||||
@Override
|
||||
public void selectManaPool(String color) {
|
||||
this.manaCost = InputPayManaBase.activateManaAbility(color, this.spell, this.manaCost);
|
||||
|
||||
// only show message if this is the active input
|
||||
if (Singletons.getModel().getMatch().getInput().getInput() == this) {
|
||||
this.showMessage();
|
||||
}
|
||||
|
||||
if (this.manaCost.isPaid()) {
|
||||
this.originalCard.setSunburstValue(this.manaCost.getSunburst());
|
||||
this.done();
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void isClassUpdated() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package forge.control.input;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import forge.Card;
|
||||
import forge.Singletons;
|
||||
import forge.card.cost.CostPartMana;
|
||||
import forge.card.cost.CostPayment;
|
||||
import forge.card.mana.ManaCostBeingPaid;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.game.GameState;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.gui.match.CMatchUI;
|
||||
import forge.view.ButtonUtil;
|
||||
|
||||
@@ -19,20 +19,21 @@ public class InputPayManaX extends InputPayManaBase {
|
||||
private String colorsPaid;
|
||||
private final CostPartMana costMana;
|
||||
private final CostPayment payment;
|
||||
private final SpellAbility sa;
|
||||
private final CountDownLatch cdlFinished;
|
||||
|
||||
|
||||
public InputPayManaX(final GameState game, final SpellAbility sa0, final CostPayment payment0, final CostPartMana costMana0)
|
||||
public InputPayManaX(final GameState game, final SpellAbility sa0, final CostPayment payment0, final CostPartMana costMana0, final CountDownLatch cdl)
|
||||
{
|
||||
super(game);
|
||||
sa = sa0;
|
||||
super(game, sa0);
|
||||
|
||||
payment = payment0;
|
||||
xPaid = 0;
|
||||
colorX = sa.hasParam("XColor") ? sa.getParam("XColor") : "";
|
||||
colorsPaid = sa.getSourceCard().getColorsPaid();
|
||||
colorX = saPaidFor.hasParam("XColor") ? saPaidFor.getParam("XColor") : "";
|
||||
colorsPaid = saPaidFor.getSourceCard().getColorsPaid();
|
||||
costMana = costMana0;
|
||||
strX = Integer.toString(costMana.getXMana());
|
||||
manaCost = new ManaCostBeingPaid(strX);
|
||||
cdlFinished = cdl;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -47,7 +48,7 @@ public class InputPayManaX extends InputPayManaBase {
|
||||
}
|
||||
|
||||
StringBuilder msg = new StringBuilder("Pay X Mana Cost for ");
|
||||
msg.append(sa.getSourceCard().getName()).append("\n").append(this.xPaid);
|
||||
msg.append(saPaidFor.getSourceCard().getName()).append("\n").append(this.xPaid);
|
||||
msg.append(" Paid so far.");
|
||||
if (costMana.isxCantBe0()) {
|
||||
msg.append(" X Can't be 0.");
|
||||
@@ -59,8 +60,12 @@ public class InputPayManaX extends InputPayManaBase {
|
||||
// selectCard
|
||||
@Override
|
||||
public void selectCard(final Card card) {
|
||||
this.manaCost = activateManaAbility(sa, card,
|
||||
this.colorX.isEmpty() ? this.manaCost : new ManaCostBeingPaid(this.colorX));
|
||||
activateManaAbility(card, this.colorX.isEmpty() ? this.manaCost : new ManaCostBeingPaid(this.colorX));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onManaAbilityPaid() {
|
||||
if (this.manaCost.isPaid()) {
|
||||
if (!this.colorsPaid.contains(this.manaCost.getColorsPaid())) {
|
||||
this.colorsPaid += this.manaCost.getColorsPaid();
|
||||
@@ -68,43 +73,24 @@ public class InputPayManaX extends InputPayManaBase {
|
||||
this.manaCost = new ManaCostBeingPaid(strX);
|
||||
this.xPaid++;
|
||||
}
|
||||
|
||||
if (Singletons.getModel().getMatch().getInput().getInput() == this) {
|
||||
this.showMessage();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonCancel() {
|
||||
this.stop();
|
||||
payment.cancelCost();
|
||||
Singletons.getControl().getPlayer().getZone(ZoneType.Battlefield).updateObservers();
|
||||
cdlFinished.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectButtonOK() {
|
||||
this.stop();
|
||||
payment.getCard().setXManaCostPaid(this.xPaid);
|
||||
payment.paidCost(costMana);
|
||||
payment.getCard().setColorsPaid(this.colorsPaid);
|
||||
payment.getCard().setSunburstValue(this.colorsPaid.length());
|
||||
done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectManaPool(String color) {
|
||||
this.manaCost = activateManaAbility(color, sa,
|
||||
this.colorX.isEmpty() ? this.manaCost : new ManaCostBeingPaid(this.colorX));
|
||||
if (this.manaCost.isPaid()) {
|
||||
if (!this.colorsPaid.contains(this.manaCost.getColorsPaid())) {
|
||||
this.colorsPaid += this.manaCost.getColorsPaid();
|
||||
}
|
||||
this.manaCost = new ManaCostBeingPaid(strX);
|
||||
this.xPaid++;
|
||||
}
|
||||
|
||||
if (Singletons.getModel().getMatch().getInput().getInput() == this) {
|
||||
this.showMessage();
|
||||
}
|
||||
useManaFromPool(color, this.colorX.isEmpty() ? this.manaCost : new ManaCostBeingPaid(this.colorX));
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -113,4 +99,14 @@ public class InputPayManaX extends InputPayManaBase {
|
||||
@Override
|
||||
public void isClassUpdated() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
payment.getCard().setXManaCostPaid(this.xPaid);
|
||||
payment.setPaidPart(costMana);
|
||||
payment.getCard().setColorsPaid(this.colorsPaid);
|
||||
payment.getCard().setSunburstValue(this.colorsPaid.length());
|
||||
cdlFinished.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,12 @@ package forge.deck;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.apache.commons.lang.time.StopWatch;
|
||||
|
||||
import forge.deck.io.DeckGroupSerializer;
|
||||
import forge.deck.io.DeckSerializer;
|
||||
import forge.deck.io.OldDeckParser;
|
||||
import forge.gui.toolbox.FSkin;
|
||||
import forge.properties.NewConstants;
|
||||
import forge.util.storage.IStorage;
|
||||
import forge.util.storage.StorageImmediatelySerialized;
|
||||
@@ -44,6 +47,9 @@ public class CardCollections {
|
||||
* @param file the file
|
||||
*/
|
||||
public CardCollections() {
|
||||
FSkin.setProgessBarMessage("Loading decks");
|
||||
StopWatch sw = new StopWatch();
|
||||
sw.start();
|
||||
this.constructed = new StorageImmediatelySerialized<Deck>(new DeckSerializer(new File(NewConstants.DECK_CONSTRUCTED_DIR), true));
|
||||
this.draft = new StorageImmediatelySerialized<DeckGroup>(new DeckGroupSerializer(new File(NewConstants.DECK_DRAFT_DIR)));
|
||||
this.sealed = new StorageImmediatelySerialized<DeckGroup>(new DeckGroupSerializer(new File(NewConstants.DECK_SEALED_DIR)));
|
||||
@@ -51,8 +57,10 @@ public class CardCollections {
|
||||
this.scheme = new StorageImmediatelySerialized<Deck>(new DeckSerializer(new File(NewConstants.DECK_SCHEME_DIR)));
|
||||
this.plane = new StorageImmediatelySerialized<Deck>(new DeckSerializer(new File(NewConstants.DECK_PLANE_DIR)));
|
||||
|
||||
System.out.printf("Read decks: %d constructed, %d sealed, %d draft, %d cubes, %d scheme, %d planar.%n", constructed.size(), sealed.size(), draft.size(), cube.size(), scheme.size(), plane.size());
|
||||
|
||||
sw.stop();
|
||||
System.out.printf("Read decks (%d ms): %d constructed, %d sealed, %d draft, %d cubes, %d scheme, %d planar.%n", sw.getTime(), constructed.size(), sealed.size(), draft.size(), cube.size(), scheme.size(), plane.size());
|
||||
// int sum = constructed.size() + sealed.size() + draft.size() + cube.size() + scheme.size() + plane.size();
|
||||
// FSkin.setProgessBarMessage(String.format("Loaded %d decks in %f sec", sum, sw.getTime() / 1000f ));
|
||||
// remove this after most people have been switched to new layout
|
||||
final OldDeckParser oldParser = new OldDeckParser(this.constructed, this.draft, this.sealed, this.cube);
|
||||
oldParser.tryParse();
|
||||
|
||||
@@ -2,7 +2,7 @@ package forge.game;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.Card;
|
||||
@@ -25,7 +25,9 @@ import forge.card.spellability.Target;
|
||||
import forge.card.spellability.TargetSelection;
|
||||
import forge.card.staticability.StaticAbility;
|
||||
import forge.control.input.InputControl;
|
||||
import forge.control.input.InputPayManaBase;
|
||||
import forge.control.input.InputPayManaSimple;
|
||||
import forge.error.BugReporter;
|
||||
import forge.game.ai.ComputerUtilCard;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
@@ -387,6 +389,7 @@ public class GameActionPlay {
|
||||
ability = ability.getSubAbility();
|
||||
}
|
||||
|
||||
System.out.println("Playing:" + sa.getDescription() + " of " + sa.getSourceCard() + " new = " + newAbility);
|
||||
if (newAbility) {
|
||||
final TargetSelection ts = new TargetSelection(sa.getTarget(), sa);
|
||||
CostPayment payment = null;
|
||||
@@ -405,15 +408,25 @@ public class GameActionPlay {
|
||||
} else {
|
||||
manaCost = this.getSpellCostChange(sa, new ManaCostBeingPaid(sa.getManaCost()));
|
||||
}
|
||||
|
||||
if (!manaCost.isPaid()) {
|
||||
CountDownLatch cdlWaitForPayment = new CountDownLatch(1);
|
||||
matchInput.setInput(new InputPayManaSimple(game, sa, manaCost, cdlWaitForPayment));
|
||||
try {
|
||||
cdlWaitForPayment.await();
|
||||
} catch (Exception e) {
|
||||
BugReporter.reportException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (manaCost.isPaid()) {
|
||||
if (sa.isSpell() && !source.isCopiedSpell()) {
|
||||
sa.setSourceCard(game.getAction().moveToStack(source));
|
||||
}
|
||||
|
||||
game.getStack().add(sa);
|
||||
} else {
|
||||
matchInput.setInput(new InputPayManaSimple(game, sa, manaCost));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,12 +461,22 @@ public class GameActionPlay {
|
||||
} else {
|
||||
manaCost = this.getSpellCostChange(sa, new ManaCostBeingPaid(sa.getManaCost()));
|
||||
}
|
||||
|
||||
final CountDownLatch cdlWaitForPayment = new CountDownLatch(1);
|
||||
|
||||
if( !manaCost.isPaid() ) {
|
||||
matchInput.setInput(new InputPayManaSimple(game, sa, getSpellCostChange(sa, new ManaCostBeingPaid(sa.getManaCost())), cdlWaitForPayment));
|
||||
try {
|
||||
cdlWaitForPayment.await();
|
||||
} catch (Exception e) {
|
||||
BugReporter.reportException(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (manaCost.isPaid()) {
|
||||
AbilityUtils.resolve(sa, false);
|
||||
return;
|
||||
} else {
|
||||
matchInput.setInput(new InputPayManaSimple(game, sa, true));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -550,4 +573,23 @@ public class GameActionPlay {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
* @param chosen
|
||||
* @param p
|
||||
* @param inputPayManaBase
|
||||
* @param manaCost
|
||||
* @param saPaidFor
|
||||
*/
|
||||
public void playManaAbilityAsPayment(final SpellAbility chosen, final Player p, final InputPayManaBase inputPayManaBase) {
|
||||
Runnable proc = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
p.getGame().getActionPlay().playSpellAbility(chosen, p);
|
||||
inputPayManaBase.onManaAbilityPlayed(p, chosen);
|
||||
}
|
||||
};
|
||||
FThreads.invokeInNewThread(proc, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ import forge.card.spellability.AbilitySub;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.SpellAbilityRestriction;
|
||||
import forge.control.input.Input;
|
||||
import forge.control.input.InputPayDiscardCost;
|
||||
import forge.control.input.InputPayDiscardCostWithCommands;
|
||||
import forge.control.input.InputPayManaExecuteCommands;
|
||||
import forge.control.input.InputPayReturnCost;
|
||||
import forge.game.event.CardDamagedEvent;
|
||||
@@ -602,7 +602,7 @@ public final class GameActionUtil {
|
||||
toSet = new InputPayReturnCost((CostReturn) costPart, ability, paid, unpaid);
|
||||
}
|
||||
else if (costPart instanceof CostDiscard) {
|
||||
toSet = new InputPayDiscardCost((CostDiscard) costPart, ability, paid, unpaid);
|
||||
toSet = new InputPayDiscardCostWithCommands((CostDiscard) costPart, ability, paid, unpaid);
|
||||
}
|
||||
else if (costPart instanceof CostPartMana) {
|
||||
toSet = new InputPayManaExecuteCommands(game, source + "\r\n", ability.getManaCost().toString(), paid, unpaid);
|
||||
|
||||
@@ -179,7 +179,7 @@ public class MatchController {
|
||||
|
||||
getInput().clearInput();
|
||||
getInput().resetInput();
|
||||
getInput().setNewInput(currentGame);
|
||||
//getInput().setNewInput(currentGame);
|
||||
|
||||
|
||||
// Thread thGame = new GameInputUpdatesThread(this, currentGame);
|
||||
|
||||
@@ -739,7 +739,7 @@ public class PhaseHandler extends MyObservable implements java.io.Serializable {
|
||||
} else {
|
||||
// pass the priority to other player
|
||||
this.pPlayerPriority = nextPlayer;
|
||||
Singletons.getModel().getMatch().getInput().resetInput();
|
||||
Singletons.getModel().getMatch().getInput().updateObservers();
|
||||
|
||||
}
|
||||
game.getStack().chooseOrderOfSimultaneousStackEntryAll();
|
||||
|
||||
@@ -1290,26 +1290,18 @@ public class MagicStack extends MyObservable {
|
||||
ComputerUtil.playStack(sa, (AIPlayer) activePlayer, game);
|
||||
}
|
||||
} else {
|
||||
// If only one, just add as necessary
|
||||
if (activePlayerSAs.size() == 1) {
|
||||
SpellAbility next = activePlayerSAs.get(0);
|
||||
List<SpellAbility> orderedSAs = activePlayerSAs;
|
||||
if (activePlayerSAs.size() > 1) { // give a dual list form to create instead of needing to do it one at a time
|
||||
orderedSAs = GuiChoose.order("Select order for Simultaneous Spell Abilities", "Resolve first", 0, activePlayerSAs, null, null);
|
||||
}
|
||||
int size = orderedSAs.size();
|
||||
for (int i = size - 1; i >= 0; i--) {
|
||||
SpellAbility next = orderedSAs.get(i);
|
||||
if (next.isTrigger()) {
|
||||
game.getActionPlay().playSpellAbility(next, activePlayer);
|
||||
} else {
|
||||
this.add(next);
|
||||
}
|
||||
} else {
|
||||
// Otherwise, gave a dual list form to create instead of needing to do it one at a time
|
||||
List<SpellAbility> orderedSAs = GuiChoose.order("Select order for Simultaneous Spell Abilities", "Resolve first", 0, activePlayerSAs, null, null);
|
||||
int size = orderedSAs.size();
|
||||
for (int i = size - 1; i >= 0; i--) {
|
||||
SpellAbility next = orderedSAs.get(i);
|
||||
if (next.isTrigger()) {
|
||||
game.getActionPlay().playSpellAbility(next, activePlayer);
|
||||
} else {
|
||||
this.add(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -458,6 +458,26 @@ public enum FSkin {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void setProgessBarMessage(final String message) {
|
||||
setProgessBarMessage(message, 0);
|
||||
}
|
||||
public static void setProgessBarMessage(final String message, final int cnt) {
|
||||
final FProgressBar barProgress = FView.SINGLETON_INSTANCE.getSplash().getProgressBar();
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if ( cnt > 0 ) {
|
||||
barProgress.reset();
|
||||
barProgress.setMaximum(4);
|
||||
}
|
||||
barProgress.setShowETA(false);
|
||||
barProgress.setShowCount(cnt > 0);
|
||||
barProgress.setDescription(message);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads two sprites: the default (which should be a complete
|
||||
@@ -487,19 +507,12 @@ public enum FSkin {
|
||||
if (FSkin.preferredName.isEmpty()) { FSkin.loadLight("default"); }
|
||||
|
||||
// Everything OK?
|
||||
|
||||
final FProgressBar barProgress = FView.SINGLETON_INSTANCE.getSplash().getProgressBar();
|
||||
setProgessBarMessage("Processing image sprites: ", 4);
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
barProgress.reset();
|
||||
barProgress.setShowETA(false);
|
||||
barProgress.setDescription("Processing image sprites: ");
|
||||
}
|
||||
});
|
||||
|
||||
// Grab and test various sprite files.
|
||||
barProgress.setMaximum(4);
|
||||
final File f1 = new File(DEFAULT_DIR + FILE_ICON_SPRITE);
|
||||
final File f2 = new File(preferredDir + FILE_ICON_SPRITE);
|
||||
final File f3 = new File(DEFAULT_DIR + FILE_FOIL_SPRITE);
|
||||
@@ -567,14 +580,7 @@ public enum FSkin {
|
||||
UIManager.put("Table.alternateRowColor", new Color(240, 240, 240));
|
||||
|
||||
// Images loaded; can start UI init.
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
barProgress.setShowETA(false);
|
||||
barProgress.setShowCount(false);
|
||||
barProgress.setDescription("Creating display components.");
|
||||
}
|
||||
});
|
||||
setProgessBarMessage("Creating display components.");
|
||||
|
||||
// Clear references to buffered images
|
||||
FSkin.bimDefaultSprite.flush();
|
||||
|
||||
@@ -117,11 +117,12 @@ public enum FModel {
|
||||
}
|
||||
|
||||
// initialize log file
|
||||
final File logFile = new File(NewConstants.LOG_FILE);
|
||||
final boolean deleteSucceeded = logFile.delete();
|
||||
File logFile = new File(NewConstants.LOG_FILE);
|
||||
|
||||
if (logFile.exists() && !deleteSucceeded && (logFile.length() != 0)) {
|
||||
throw new IllegalStateException("Could not delete existing logFile:" + logFile.getAbsolutePath());
|
||||
int i = 0;
|
||||
while (logFile.exists() && !logFile.delete()) {
|
||||
String pathname = logFile.getPath().replaceAll("[0-9]{0,2}.log$", String.valueOf(i++) + ".log");
|
||||
logFile = new File(pathname);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user