mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
InputSelectCards made synchronous, select cards to sacrifice uses that input instead on GuiChoose...
Added check to MagicStack add to prevent spells being added by EDT.
This commit is contained in:
7
.gitattributes
vendored
7
.gitattributes
vendored
@@ -13814,10 +13814,11 @@ src/main/java/forge/control/input/InputPayManaOfCostPayment.java -text
|
|||||||
src/main/java/forge/control/input/InputPayManaSimple.java svneol=native#text/plain
|
src/main/java/forge/control/input/InputPayManaSimple.java svneol=native#text/plain
|
||||||
src/main/java/forge/control/input/InputPayManaX.java -text
|
src/main/java/forge/control/input/InputPayManaX.java -text
|
||||||
src/main/java/forge/control/input/InputPayReturnCost.java -text
|
src/main/java/forge/control/input/InputPayReturnCost.java -text
|
||||||
src/main/java/forge/control/input/InputPaySacCost.java -text
|
|
||||||
src/main/java/forge/control/input/InputPayment.java -text
|
src/main/java/forge/control/input/InputPayment.java -text
|
||||||
src/main/java/forge/control/input/InputSelectMany.java -text
|
src/main/java/forge/control/input/InputSelectCards.java -text
|
||||||
src/main/java/forge/control/input/InputSelectManyCards.java -text
|
src/main/java/forge/control/input/InputSelectCardsFromList.java -text
|
||||||
|
src/main/java/forge/control/input/InputSelectList.java -text
|
||||||
|
src/main/java/forge/control/input/InputSelectListBase.java -text
|
||||||
src/main/java/forge/control/input/InputSynchronized.java -text
|
src/main/java/forge/control/input/InputSynchronized.java -text
|
||||||
src/main/java/forge/control/input/InputSyncronizedBase.java -text
|
src/main/java/forge/control/input/InputSyncronizedBase.java -text
|
||||||
src/main/java/forge/control/input/package-info.java svneol=native#text/plain
|
src/main/java/forge/control/input/package-info.java svneol=native#text/plain
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import com.google.common.collect.Iterables;
|
|||||||
import forge.Card;
|
import forge.Card;
|
||||||
import forge.CardLists;
|
import forge.CardLists;
|
||||||
import forge.CardPredicates;
|
import forge.CardPredicates;
|
||||||
|
import forge.FThreads;
|
||||||
import forge.CardPredicates.Presets;
|
import forge.CardPredicates.Presets;
|
||||||
import forge.Command;
|
import forge.Command;
|
||||||
import forge.CounterType;
|
import forge.CounterType;
|
||||||
@@ -44,8 +45,7 @@ import forge.card.spellability.SpellPermanent;
|
|||||||
import forge.card.spellability.Target;
|
import forge.card.spellability.Target;
|
||||||
import forge.card.trigger.Trigger;
|
import forge.card.trigger.Trigger;
|
||||||
import forge.card.trigger.TriggerHandler;
|
import forge.card.trigger.TriggerHandler;
|
||||||
import forge.control.input.InputBase;
|
import forge.control.input.InputSelectCards;
|
||||||
import forge.control.input.InputSelectManyCards;
|
|
||||||
import forge.game.ai.ComputerUtilCard;
|
import forge.game.ai.ComputerUtilCard;
|
||||||
import forge.game.ai.ComputerUtilCombat;
|
import forge.game.ai.ComputerUtilCombat;
|
||||||
import forge.game.event.TokenCreatedEvent;
|
import forge.game.event.TokenCreatedEvent;
|
||||||
@@ -477,41 +477,27 @@ public class CardFactoryCreatures {
|
|||||||
private static void getCard_PhyrexianDreadnought(final Card card, final String cardName) {
|
private static void getCard_PhyrexianDreadnought(final Card card, final String cardName) {
|
||||||
final Player player = card.getController();
|
final Player player = card.getController();
|
||||||
|
|
||||||
final InputBase target = new InputSelectManyCards(0, Integer.MAX_VALUE) {
|
final Ability sacOrSac = new Ability(card, ManaCost.NO_COST) {
|
||||||
|
@Override
|
||||||
|
public void resolve() {
|
||||||
|
if (player.isHuman()) {
|
||||||
|
final InputSelectCards target = new InputSelectCards(0, Integer.MAX_VALUE) {
|
||||||
private static final long serialVersionUID = 2698036349873486664L;
|
private static final long serialVersionUID = 2698036349873486664L;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
String toDisplay = cardName + " - Select any number of creatures to sacrifice. ";
|
String toDisplay = cardName + " - Select any number of creatures to sacrifice. ";
|
||||||
toDisplay += "Currently, (" + selected.size() + ") selected with a total power of: "
|
toDisplay += "Currently, (" + selected.size() + ") selected with a total power of: " + getTotalPower();
|
||||||
+ getTotalPower();
|
|
||||||
toDisplay += " Click OK when Done.";
|
toDisplay += " Click OK when Done.";
|
||||||
return toDisplay;
|
return toDisplay;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean canCancelWithSomethingSelected() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCancel() {
|
|
||||||
Singletons.getModel().getGame().getAction().sacrifice(card, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isValidChoice(Card c) {
|
protected boolean isValidChoice(Card c) {
|
||||||
Zone zone = Singletons.getModel().getGame().getZoneOf(c);
|
Zone zone = Singletons.getModel().getGame().getZoneOf(c);
|
||||||
return c.isCreature() && zone.is(ZoneType.Battlefield, player);
|
return c.isCreature() && zone.is(ZoneType.Battlefield, player);
|
||||||
} // selectCard()
|
} // selectCard()
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDone() {
|
|
||||||
for (final Card sac : selected) {
|
|
||||||
Singletons.getModel().getGame().getAction().sacrifice(sac, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean hasEnoughTargets() {
|
protected boolean hasEnoughTargets() {
|
||||||
return getTotalPower() >= 12;
|
return getTotalPower() >= 12;
|
||||||
@@ -526,10 +512,16 @@ public class CardFactoryCreatures {
|
|||||||
}
|
}
|
||||||
}; // Input
|
}; // Input
|
||||||
|
|
||||||
final Ability sacOrSac = new Ability(card, ManaCost.NO_COST) {
|
target.setCancelWithSelectedAllowed(true);
|
||||||
@Override
|
FThreads.setInputAndWait(target);
|
||||||
public void resolve() {
|
if(!target.hasCancelled()) {
|
||||||
if (player.isHuman()) {
|
for (final Card sac : target.getSelected()) {
|
||||||
|
Singletons.getModel().getGame().getAction().sacrifice(sac, null);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Singletons.getModel().getGame().getAction().sacrifice(card, null);
|
||||||
|
}
|
||||||
|
|
||||||
Singletons.getModel().getMatch().getInput().setInput(target);
|
Singletons.getModel().getMatch().getInput().setInput(target);
|
||||||
}
|
}
|
||||||
} // end resolve
|
} // end resolve
|
||||||
|
|||||||
@@ -24,8 +24,9 @@ import javax.swing.JOptionPane;
|
|||||||
import forge.Card;
|
import forge.Card;
|
||||||
import forge.CardLists;
|
import forge.CardLists;
|
||||||
import forge.Command;
|
import forge.Command;
|
||||||
|
import forge.FThreads;
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.control.input.InputSelectManyCards;
|
import forge.control.input.InputSelectCards;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.zone.Zone;
|
import forge.game.zone.Zone;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
@@ -45,7 +46,7 @@ class CardFactoryLands {
|
|||||||
* TODO: Write javadoc for this type.
|
* TODO: Write javadoc for this type.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private static final class InputRevealCardType extends InputSelectManyCards {
|
private static final class InputRevealCardType extends InputSelectCards {
|
||||||
private final String type;
|
private final String type;
|
||||||
private final Card card;
|
private final Card card;
|
||||||
private static final long serialVersionUID = -2774066137824255680L;
|
private static final long serialVersionUID = -2774066137824255680L;
|
||||||
@@ -73,21 +74,6 @@ class CardFactoryLands {
|
|||||||
Zone zone = Singletons.getModel().getGame().getZoneOf(c);
|
Zone zone = Singletons.getModel().getGame().getZoneOf(c);
|
||||||
return zone.is(ZoneType.Hand) && c.isType(type) && c.getController() == card.getController();
|
return zone.is(ZoneType.Hand) && c.isType(type) && c.getController() == card.getController();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDone() {
|
|
||||||
if (selected.isEmpty()) {
|
|
||||||
onCancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
String cardName = selected.get(0).getName();
|
|
||||||
JOptionPane.showMessageDialog(null, "Revealed card: " + cardName, cardName, JOptionPane.PLAIN_MESSAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCancel() {
|
|
||||||
card.setTapped(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -226,7 +212,16 @@ class CardFactoryLands {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void humanExecute() {
|
public void humanExecute() {
|
||||||
Singletons.getModel().getMatch().getInput().setInput(new InputRevealCardType(0, 1, type, card));
|
InputSelectCards inp = new InputRevealCardType(0, 1, type, card);
|
||||||
|
FThreads.setInputAndWait(inp);
|
||||||
|
|
||||||
|
if ( inp.hasCancelled() || inp.getSelected().isEmpty() ) {
|
||||||
|
card.setTapped(true);
|
||||||
|
} else {
|
||||||
|
String cardName = inp.getSelected().get(0).getName();
|
||||||
|
JOptionPane.showMessageDialog(null, "Revealed card: " + cardName, cardName, JOptionPane.PLAIN_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
} // execute()
|
} // execute()
|
||||||
|
|
||||||
private void revealCard(final Card c) {
|
private void revealCard(final Card c) {
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import forge.CardUtil;
|
|||||||
import forge.Command;
|
import forge.Command;
|
||||||
import forge.Constant;
|
import forge.Constant;
|
||||||
import forge.CounterType;
|
import forge.CounterType;
|
||||||
|
import forge.FThreads;
|
||||||
import forge.GameEntity;
|
import forge.GameEntity;
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.card.ability.AbilityFactory;
|
import forge.card.ability.AbilityFactory;
|
||||||
@@ -64,7 +65,7 @@ import forge.card.trigger.TriggerHandler;
|
|||||||
import forge.card.trigger.TriggerType;
|
import forge.card.trigger.TriggerType;
|
||||||
import forge.control.input.Input;
|
import forge.control.input.Input;
|
||||||
import forge.control.input.InputBase;
|
import forge.control.input.InputBase;
|
||||||
import forge.control.input.InputSelectManyCards;
|
import forge.control.input.InputSelectCards;
|
||||||
import forge.game.GameState;
|
import forge.game.GameState;
|
||||||
import forge.game.ai.ComputerUtil;
|
import forge.game.ai.ComputerUtil;
|
||||||
import forge.game.ai.ComputerUtilCard;
|
import forge.game.ai.ComputerUtilCard;
|
||||||
@@ -3152,26 +3153,6 @@ public class CardFactoryUtil {
|
|||||||
};
|
};
|
||||||
haunterDiesWork.setDescription(hauntDescription);
|
haunterDiesWork.setDescription(hauntDescription);
|
||||||
|
|
||||||
final InputSelectManyCards target = new InputSelectManyCards(1, 1) {
|
|
||||||
private static final long serialVersionUID = 1981791992623774490L;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDone() {
|
|
||||||
haunterDiesWork.setTargetCard(selected.get(0));
|
|
||||||
Singletons.getModel().getGame().getStack().add(haunterDiesWork);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean isValidChoice(Card c) {
|
|
||||||
Zone zone = Singletons.getModel().getGame().getZoneOf(c);
|
|
||||||
if (!zone.is(ZoneType.Battlefield) || !c.isCreature()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return c.canBeTargetedBy(haunterDiesWork);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
target.setMessage("Choose target creature to haunt.");
|
|
||||||
|
|
||||||
final Ability haunterDiesSetup = new Ability(card, ManaCost.ZERO) {
|
final Ability haunterDiesSetup = new Ability(card, ManaCost.ZERO) {
|
||||||
@Override
|
@Override
|
||||||
public void resolve() {
|
public void resolve() {
|
||||||
@@ -3189,7 +3170,25 @@ public class CardFactoryUtil {
|
|||||||
// need to do it this way because I don't know quite how to
|
// need to do it this way because I don't know quite how to
|
||||||
// make TriggerHandler respect BeforePayMana.
|
// make TriggerHandler respect BeforePayMana.
|
||||||
if (card.getController().isHuman()) {
|
if (card.getController().isHuman()) {
|
||||||
Singletons.getModel().getMatch().getInput().setInput(target);
|
|
||||||
|
final InputSelectCards target = new InputSelectCards(1, 1) {
|
||||||
|
private static final long serialVersionUID = 1981791992623774490L;
|
||||||
|
@Override
|
||||||
|
protected boolean isValidChoice(Card c) {
|
||||||
|
Zone zone = Singletons.getModel().getGame().getZoneOf(c);
|
||||||
|
if (!zone.is(ZoneType.Battlefield) || !c.isCreature()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return c.canBeTargetedBy(haunterDiesWork);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
target.setMessage("Choose target creature to haunt.");
|
||||||
|
|
||||||
|
FThreads.setInputAndWait(target);
|
||||||
|
if (!target.hasCancelled()) {
|
||||||
|
haunterDiesWork.setTargetCard(target.getSelected().get(0));
|
||||||
|
Singletons.getModel().getGame().getStack().add(haunterDiesWork);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// AI choosing what to haunt
|
// AI choosing what to haunt
|
||||||
final List<Card> oppCreats = CardLists.filterControlledBy(creats, card.getController().getOpponent());
|
final List<Card> oppCreats = CardLists.filterControlledBy(creats, card.getController().getOpponent());
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import forge.card.cardfactory.CardFactoryUtil;
|
|||||||
import forge.card.cost.CostDiscard;
|
import forge.card.cost.CostDiscard;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.zone.PlayerZone;
|
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.gui.match.CMatchUI;
|
import forge.gui.match.CMatchUI;
|
||||||
import forge.view.ButtonUtil;
|
import forge.view.ButtonUtil;
|
||||||
@@ -108,74 +107,40 @@ public class InputPayDiscardCostWithCommands extends InputSyncronizedBase implem
|
|||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
public void selectButtonCancel() {
|
public void selectButtonCancel() {
|
||||||
this.cancel();
|
for (Card selected : this.discardCost.getList()) {
|
||||||
|
selected.setUsedToPay(false);
|
||||||
|
}
|
||||||
|
this.bPaid = false;
|
||||||
|
this.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
public void selectButtonOK() {
|
public void selectButtonOK() {
|
||||||
this.done();
|
for (Card selected : this.discardCost.getList()) {
|
||||||
|
selected.setUsedToPay(false);
|
||||||
|
Singletons.getControl().getPlayer().discard(selected, this.ability);
|
||||||
|
}
|
||||||
|
this.discardCost.addListToHash(this.ability, "Discarded");
|
||||||
|
this.bPaid = true;
|
||||||
|
this.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
public void selectCard(final Card card) {
|
public void selectCard(final Card card) {
|
||||||
if (this.choiceList.contains(card) && this.numChosen < numRequired) {
|
|
||||||
this.numChosen++;
|
|
||||||
this.discardCost.addToList(card);
|
|
||||||
card.setUsedToPay(true);
|
|
||||||
this.choiceList.remove(card);
|
|
||||||
this.showMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* unselectCard.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param card
|
|
||||||
* a {@link forge.Card} object.
|
|
||||||
* @param zone
|
|
||||||
* a {@link forge.game.zone.PlayerZone} object.
|
|
||||||
*/
|
|
||||||
public void unselectCard(final Card card, final PlayerZone zone) {
|
|
||||||
if (this.discardCost.getList().contains(card)) {
|
if (this.discardCost.getList().contains(card)) {
|
||||||
this.numChosen--;
|
this.numChosen--;
|
||||||
card.setUsedToPay(false);
|
card.setUsedToPay(false);
|
||||||
this.discardCost.getList().remove(card);
|
this.discardCost.getList().remove(card);
|
||||||
this.choiceList.add(card);
|
this.choiceList.add(card);
|
||||||
|
}
|
||||||
|
else if (this.choiceList.contains(card) && this.numChosen < numRequired) {
|
||||||
|
this.numChosen++;
|
||||||
|
this.discardCost.addToList(card);
|
||||||
|
card.setUsedToPay(true);
|
||||||
|
this.choiceList.remove(card);
|
||||||
|
}
|
||||||
this.showMessage();
|
this.showMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* executes paid commmand.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void done() {
|
|
||||||
for (Card selected : this.discardCost.getList()) {
|
|
||||||
selected.setUsedToPay(false);
|
|
||||||
Singletons.getControl().getPlayer().discard(selected, this.ability);
|
|
||||||
}
|
|
||||||
this.discardCost.addListToHash(ability, "Discarded");
|
|
||||||
bPaid = true;
|
|
||||||
this.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* executes unpaid commmand.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void cancel() {
|
|
||||||
for (Card selected : this.discardCost.getList()) {
|
|
||||||
selected.setUsedToPay(false);
|
|
||||||
}
|
|
||||||
bPaid = false;
|
|
||||||
this.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,188 +0,0 @@
|
|||||||
/*
|
|
||||||
* Forge: Play Magic: the Gathering.
|
|
||||||
* Copyright (C) 2011 Forge Team
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package forge.control.input;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import forge.Card;
|
|
||||||
import forge.CardLists;
|
|
||||||
import forge.Command;
|
|
||||||
import forge.Singletons;
|
|
||||||
import forge.card.cardfactory.CardFactoryUtil;
|
|
||||||
import forge.card.cost.CostSacrifice;
|
|
||||||
import forge.card.spellability.SpellAbility;
|
|
||||||
import forge.game.player.Player;
|
|
||||||
import forge.game.zone.PlayerZone;
|
|
||||||
import forge.game.zone.ZoneType;
|
|
||||||
import forge.gui.match.CMatchUI;
|
|
||||||
import forge.view.ButtonUtil;
|
|
||||||
|
|
||||||
//if cost is paid, Command.execute() is called
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Input_PayManaCost_Ability class.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Forge
|
|
||||||
* @version $Id: InputPayManaCostAbility.java 15673 2012-05-23 14:01:35Z ArsenalNut $
|
|
||||||
*/
|
|
||||||
public class InputPaySacCost extends InputBase {
|
|
||||||
/**
|
|
||||||
* Constant <code>serialVersionUID=2685832214529141991L</code>.
|
|
||||||
*/
|
|
||||||
private static final long serialVersionUID = 2685832214529141991L;
|
|
||||||
|
|
||||||
private int numChosen = 0;
|
|
||||||
private int numRequired = 0;
|
|
||||||
private List<Card> choiceList;
|
|
||||||
private CostSacrifice sacCost;
|
|
||||||
private SpellAbility ability;
|
|
||||||
private Command paid;
|
|
||||||
private Command unpaid;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Constructor for Input_PayManaCost_Ability.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param cost
|
|
||||||
* a {@link forge.card.cost.CostSacrifice} object.
|
|
||||||
* @param sa
|
|
||||||
* a {@link forge.card.spellability.SpellAbility} object.
|
|
||||||
* @param paidCommand
|
|
||||||
* a {@link forge.Command} object.
|
|
||||||
* @param unpaidCommand
|
|
||||||
* a {@link forge.Command} object.
|
|
||||||
*/
|
|
||||||
public InputPaySacCost(final CostSacrifice cost, final SpellAbility sa, final Command paidCommand,
|
|
||||||
final Command unpaidCommand) {
|
|
||||||
final Card source = sa.getSourceCard();
|
|
||||||
|
|
||||||
this.ability = sa;
|
|
||||||
this.sacCost = cost;
|
|
||||||
Player human = Singletons.getControl().getPlayer();
|
|
||||||
this.choiceList = CardLists.getValidCards(human.getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), human, source);
|
|
||||||
String amountString = cost.getAmount();
|
|
||||||
this.numRequired = amountString.matches("[0-9][0-9]?") ? Integer.parseInt(amountString)
|
|
||||||
: CardFactoryUtil.xCount(source, source.getSVar(amountString));
|
|
||||||
this.paid = paidCommand;
|
|
||||||
this.unpaid = unpaidCommand;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
public void showMessage() {
|
|
||||||
final StringBuilder msg = new StringBuilder("Sacrifice ");
|
|
||||||
final int nLeft = this.numRequired - this.numChosen;
|
|
||||||
msg.append(nLeft).append(" ");
|
|
||||||
msg.append(this.sacCost.getDescriptiveType());
|
|
||||||
if (nLeft > 1) {
|
|
||||||
msg.append("s");
|
|
||||||
}
|
|
||||||
if (!this.sacCost.getList().isEmpty()) {
|
|
||||||
msg.append("\r\nSelected:\r\n");
|
|
||||||
for (Card selected : this.sacCost.getList()) {
|
|
||||||
msg.append(selected + "\r\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CMatchUI.SINGLETON_INSTANCE.showMessage(msg.toString());
|
|
||||||
if (nLeft > 0) {
|
|
||||||
ButtonUtil.enableOnlyCancel();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ButtonUtil.enableAllFocusOk();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
public void selectButtonCancel() {
|
|
||||||
this.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
public void selectButtonOK() {
|
|
||||||
this.done();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
public void selectCard(final Card card) {
|
|
||||||
if (this.choiceList.contains(card) && this.numChosen < numRequired) {
|
|
||||||
this.numChosen++;
|
|
||||||
this.sacCost.addToList(card);
|
|
||||||
card.setUsedToPay(true);
|
|
||||||
this.choiceList.remove(card);
|
|
||||||
this.showMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* unselectCard.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param card
|
|
||||||
* a {@link forge.Card} object.
|
|
||||||
* @param zone
|
|
||||||
* a {@link forge.game.zone.PlayerZone} object.
|
|
||||||
*/
|
|
||||||
public void unselectCard(final Card card, final PlayerZone zone) {
|
|
||||||
if (this.sacCost.getList().contains(card)) {
|
|
||||||
this.numChosen--;
|
|
||||||
card.setUsedToPay(false);
|
|
||||||
this.sacCost.getList().remove(card);
|
|
||||||
this.choiceList.add(card);
|
|
||||||
this.showMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* executes paid commmand.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void done() {
|
|
||||||
this.stop();
|
|
||||||
// actually sacrifice the cards
|
|
||||||
for (Card selected : this.sacCost.getList()) {
|
|
||||||
selected.setUsedToPay(false);
|
|
||||||
Singletons.getModel().getGame().getAction().sacrifice(selected, this.ability);
|
|
||||||
}
|
|
||||||
this.sacCost.addListToHash(ability, "Sacrificed");
|
|
||||||
this.paid.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* executes unpaid commmand.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void cancel() {
|
|
||||||
this.stop();
|
|
||||||
for (Card selected : this.sacCost.getList()) {
|
|
||||||
selected.setUsedToPay(false);
|
|
||||||
}
|
|
||||||
this.unpaid.execute();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
37
src/main/java/forge/control/input/InputSelectCards.java
Normal file
37
src/main/java/forge/control/input/InputSelectCards.java
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package forge.control.input;
|
||||||
|
|
||||||
|
import forge.Card;
|
||||||
|
|
||||||
|
public abstract class InputSelectCards extends InputSelectListBase<Card> {
|
||||||
|
private static final long serialVersionUID = -6609493252672573139L;
|
||||||
|
|
||||||
|
protected InputSelectCards(int min, int max) {
|
||||||
|
|
||||||
|
super(min, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void selectCard(final Card c) {
|
||||||
|
selectEntity(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.control.input.InputSelectListBase#onSelectStateChanged(forge.GameEntity, boolean)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void onSelectStateChanged(Card c, boolean newState) {
|
||||||
|
c.setUsedToPay(newState); // UI supports card highlighting though this abstraction-breaking mechanism
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.control.input.InputSyncronizedBase#afterStop()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void afterStop() {
|
||||||
|
for(Card c : selected)
|
||||||
|
c.setUsedToPay(false);
|
||||||
|
super.afterStop(); // It's ultimatelly important to keep call to super class!
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package forge.control.input;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import forge.Card;
|
||||||
|
|
||||||
|
public class InputSelectCardsFromList extends InputSelectCards {
|
||||||
|
private static final long serialVersionUID = 6230360322294805986L;
|
||||||
|
|
||||||
|
private final List<Card> validChoices;
|
||||||
|
|
||||||
|
public InputSelectCardsFromList(int min, int max, List<Card> validCards) {
|
||||||
|
super(min, max);
|
||||||
|
this.validChoices = validCards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected final boolean isValidChoice(Card choice) {
|
||||||
|
return validChoices.contains(choice);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
12
src/main/java/forge/control/input/InputSelectList.java
Normal file
12
src/main/java/forge/control/input/InputSelectList.java
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package forge.control.input;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: Write javadoc for this type.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface InputSelectList<T> extends InputSynchronized {
|
||||||
|
boolean hasCancelled();
|
||||||
|
List<T> getSelected();
|
||||||
|
}
|
||||||
@@ -7,22 +7,23 @@ import forge.GameEntity;
|
|||||||
import forge.gui.match.CMatchUI;
|
import forge.gui.match.CMatchUI;
|
||||||
import forge.view.ButtonUtil;
|
import forge.view.ButtonUtil;
|
||||||
|
|
||||||
/**
|
public abstract class InputSelectListBase<T extends GameEntity> extends InputSyncronizedBase implements InputSelectList<T> {
|
||||||
* TODO: Write javadoc for this type.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public abstract class InputSelectMany<T extends GameEntity> extends InputBase {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = -2305549394512889450L;
|
private static final long serialVersionUID = -2305549394512889450L;
|
||||||
|
|
||||||
protected final List<T> selected = new ArrayList<T>();
|
protected final List<T> selected;
|
||||||
|
protected boolean bCancelled = false;
|
||||||
protected final int min;
|
protected final int min;
|
||||||
protected final int max;
|
protected final int max;
|
||||||
|
public boolean allowUnselect = false;
|
||||||
|
private boolean allowCancelWithNotEmptyList = false;
|
||||||
|
|
||||||
private String message = "Source-Card-Name - Select %d more card(s)";
|
private String message = "Source-Card-Name - Select %d more card(s)";
|
||||||
|
|
||||||
protected InputSelectMany(int min, int max) {
|
|
||||||
|
|
||||||
|
|
||||||
|
protected InputSelectListBase(int min, int max) {
|
||||||
|
selected = new ArrayList<T>();
|
||||||
if (min > max) {
|
if (min > max) {
|
||||||
throw new IllegalArgumentException("Min must not be greater than Max");
|
throw new IllegalArgumentException("Min must not be greater than Max");
|
||||||
}
|
}
|
||||||
@@ -35,7 +36,7 @@ public abstract class InputSelectMany<T extends GameEntity> extends InputBase {
|
|||||||
String msgToShow = getMessage();
|
String msgToShow = getMessage();
|
||||||
CMatchUI.SINGLETON_INSTANCE.showMessage(msgToShow);
|
CMatchUI.SINGLETON_INSTANCE.showMessage(msgToShow);
|
||||||
|
|
||||||
boolean canCancel = (min == 0 && selected.isEmpty()) || canCancelWithSomethingSelected();
|
boolean canCancel = (min == 0 && selected.isEmpty()) || isCancelWithSelectedAllowed();
|
||||||
boolean canOk = hasEnoughTargets();
|
boolean canOk = hasEnoughTargets();
|
||||||
|
|
||||||
if (canOk && canCancel) {
|
if (canOk && canCancel) {
|
||||||
@@ -65,9 +66,18 @@ public abstract class InputSelectMany<T extends GameEntity> extends InputBase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void selectButtonCancel() {
|
public final void selectButtonCancel() {
|
||||||
|
bCancelled = true;
|
||||||
this.stop();
|
this.stop();
|
||||||
// for a next use
|
}
|
||||||
selected.clear();
|
|
||||||
|
@Override
|
||||||
|
public final boolean hasCancelled() {
|
||||||
|
return bCancelled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final List<T> getSelected() {
|
||||||
|
return selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -77,8 +87,6 @@ public abstract class InputSelectMany<T extends GameEntity> extends InputBase {
|
|||||||
// if it does, uncomment the 5 lines below, use them as method body
|
// if it does, uncomment the 5 lines below, use them as method body
|
||||||
|
|
||||||
this.stop();
|
this.stop();
|
||||||
// for a next use
|
|
||||||
selected.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMessage(String message0) {
|
public void setMessage(String message0) {
|
||||||
@@ -86,27 +94,41 @@ public abstract class InputSelectMany<T extends GameEntity> extends InputBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// must define these
|
// must define these
|
||||||
protected abstract void onDone();
|
|
||||||
protected abstract boolean isValidChoice(T choice);
|
protected abstract boolean isValidChoice(T choice);
|
||||||
|
|
||||||
// might re-define later
|
// might re-define later
|
||||||
protected void onCancel() {}
|
|
||||||
protected boolean canCancelWithSomethingSelected() { return false; }
|
|
||||||
protected boolean hasEnoughTargets() { return selected.size() >= min; }
|
protected boolean hasEnoughTargets() { return selected.size() >= min; }
|
||||||
protected boolean hasAllTargets() { return selected.size() >= max; }
|
protected boolean hasAllTargets() { return selected.size() >= max; }
|
||||||
|
protected void onSelectStateChanged(T c, boolean newState) {} // Select card inputs may highlight selected cards with this method
|
||||||
|
|
||||||
protected void selectEntity(T c) {
|
protected void selectEntity(T c) {
|
||||||
|
if (!isValidChoice(c)) {
|
||||||
if (selected.contains(c) || !isValidChoice(c)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( selected.contains(c) ) {
|
||||||
|
if ( allowUnselect ) {
|
||||||
|
this.selected.remove(c);
|
||||||
|
onSelectStateChanged(c, false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
this.selected.add(c);
|
this.selected.add(c);
|
||||||
this.showMessage();
|
onSelectStateChanged(c, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (hasAllTargets()) {
|
if (hasAllTargets()) {
|
||||||
selectButtonOK();
|
selectButtonOK();
|
||||||
|
} else {
|
||||||
|
this.showMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public final boolean isUnselectAllowed() { return allowUnselect; }
|
||||||
|
public final void setUnselectAllowed(boolean allow) { this.allowUnselect = allow; }
|
||||||
|
|
||||||
|
public final boolean isCancelWithSelectedAllowed() { return allowCancelWithNotEmptyList; }
|
||||||
|
public final void setCancelWithSelectedAllowed(boolean allow) { this.allowCancelWithNotEmptyList = allow ; }
|
||||||
}
|
}
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package forge.control.input;
|
|
||||||
|
|
||||||
import forge.Card;
|
|
||||||
|
|
||||||
public abstract class InputSelectManyCards extends InputSelectMany<Card> {
|
|
||||||
private static final long serialVersionUID = -6609493252672573139L;
|
|
||||||
|
|
||||||
protected InputSelectManyCards(int min, int max) {
|
|
||||||
|
|
||||||
super(min, max);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void selectCard(final Card c) {
|
|
||||||
selectEntity(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -66,6 +66,7 @@ public class GameActionPlay {
|
|||||||
* a {@link forge.card.spellability.SpellAbility} object.
|
* a {@link forge.card.spellability.SpellAbility} object.
|
||||||
*/
|
*/
|
||||||
public final void playSpellAbilityWithoutPayingManaCost(final SpellAbility sa) {
|
public final void playSpellAbilityWithoutPayingManaCost(final SpellAbility sa) {
|
||||||
|
FThreads.checkEDT("GameActionPlay.playSpellAbilityWithoutPayingManaCost", false);
|
||||||
final Card source = sa.getSourceCard();
|
final Card source = sa.getSourceCard();
|
||||||
setSplitCardState(source, sa); // Split card support
|
setSplitCardState(source, sa); // Split card support
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ import forge.card.spellability.AbilityStatic;
|
|||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.control.input.InputBase;
|
import forge.control.input.InputBase;
|
||||||
import forge.control.input.InputPayManaExecuteCommands;
|
import forge.control.input.InputPayManaExecuteCommands;
|
||||||
import forge.control.input.InputSelectManyCards;
|
import forge.control.input.InputSelectCards;
|
||||||
import forge.game.GameActionUtil;
|
import forge.game.GameActionUtil;
|
||||||
import forge.game.GameState;
|
import forge.game.GameState;
|
||||||
import forge.game.ai.ComputerUtil;
|
import forge.game.ai.ComputerUtil;
|
||||||
@@ -460,26 +460,20 @@ public class Upkeep extends Phase {
|
|||||||
@Override
|
@Override
|
||||||
public void resolve() {
|
public void resolve() {
|
||||||
final List<Card> targets = CardLists.getTargetableCards(abyssGetTargets, this);
|
final List<Card> targets = CardLists.getTargetableCards(abyssGetTargets, this);
|
||||||
final InputBase chooseArt = new InputSelectManyCards(1, 1) {
|
if (player.isHuman() && targets.size() > 0) {
|
||||||
|
final InputSelectCards chooseArt = new InputSelectCards(1, 1) {
|
||||||
private static final long serialVersionUID = 4820011040853968644L;
|
private static final long serialVersionUID = 4820011040853968644L;
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getMessage() {
|
|
||||||
return abyss.getName() + " - Select one nonartifact creature to destroy";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isValidChoice(Card choice) {
|
protected boolean isValidChoice(Card choice) {
|
||||||
return choice.isCreature() && !choice.isArtifact() && canTarget(choice) && choice.getController() == player;
|
return choice.isCreature() && !choice.isArtifact() && canTarget(choice) && choice.getController() == player;
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDone() {
|
|
||||||
game.getAction().destroyNoRegeneration(selected.get(0));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
if (player.isHuman() && targets.size() > 0) {
|
chooseArt.setMessage(abyss.getName() + " - Select one nonartifact creature to destroy");
|
||||||
Singletons.getModel().getMatch().getInput().setInput(chooseArt); // Input
|
FThreads.setInputAndWait(chooseArt); // Input
|
||||||
|
if (!chooseArt.hasCancelled()) {
|
||||||
|
game.getAction().destroyNoRegeneration(chooseArt.getSelected().get(0));
|
||||||
|
}
|
||||||
|
|
||||||
} else { // computer
|
} else { // computer
|
||||||
|
|
||||||
final List<Card> indestruct = CardLists.getKeyword(targets, "Indestructible");
|
final List<Card> indestruct = CardLists.getKeyword(targets, "Indestructible");
|
||||||
|
|||||||
@@ -11,12 +11,15 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||||
|
|
||||||
import forge.Card;
|
import forge.Card;
|
||||||
|
import forge.FThreads;
|
||||||
import forge.GameEntity;
|
import forge.GameEntity;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.control.input.Input;
|
import forge.control.input.Input;
|
||||||
import forge.control.input.InputBlock;
|
import forge.control.input.InputBlock;
|
||||||
import forge.control.input.InputCleanup;
|
import forge.control.input.InputCleanup;
|
||||||
import forge.control.input.InputPassPriority;
|
import forge.control.input.InputPassPriority;
|
||||||
|
import forge.control.input.InputSelectCards;
|
||||||
|
import forge.control.input.InputSelectCardsFromList;
|
||||||
import forge.deck.CardPool;
|
import forge.deck.CardPool;
|
||||||
import forge.deck.Deck;
|
import forge.deck.Deck;
|
||||||
import forge.deck.DeckSection;
|
import forge.deck.DeckSection;
|
||||||
@@ -212,26 +215,18 @@ public class PlayerControllerHuman extends PlayerController {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<Card> choosePermanentsToSacrifice(List<Card> validTargets, int amount, SpellAbility sa, boolean destroy, boolean isOptional) {
|
public List<Card> choosePermanentsToSacrifice(List<Card> validTargets, int amount, SpellAbility sa, boolean destroy, boolean isOptional) {
|
||||||
List<Card> result = new ArrayList<Card>();
|
int max = Math.min(amount, validTargets.size());
|
||||||
|
if (max == 0)
|
||||||
|
return new ArrayList<Card>();
|
||||||
|
|
||||||
for (int i = 0; i < amount; i++) {
|
InputSelectCards inp = new InputSelectCardsFromList(isOptional ? 0 : amount, max, validTargets);
|
||||||
if (validTargets.isEmpty()) {
|
// TODO: Either compose a message here, or pass it as parameter from caller.
|
||||||
break;
|
inp.setMessage("Select cards to sacrifice");
|
||||||
}
|
|
||||||
Card c;
|
FThreads.setInputAndWait(inp);
|
||||||
if (isOptional) {
|
if( inp.hasCancelled() )
|
||||||
c = GuiChoose.oneOrNone("Select a card to sacrifice", validTargets);
|
return new ArrayList<Card>();
|
||||||
} else {
|
else return inp.getSelected();
|
||||||
c = GuiChoose.one("Select a card to sacrifice", validTargets);
|
|
||||||
}
|
|
||||||
if (c != null) {
|
|
||||||
result.add(c);
|
|
||||||
validTargets.remove(c);
|
|
||||||
} else {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import forge.CardLists;
|
|||||||
import forge.CardPredicates;
|
import forge.CardPredicates;
|
||||||
import forge.FThreads;
|
import forge.FThreads;
|
||||||
import forge.CardPredicates.Presets;
|
import forge.CardPredicates.Presets;
|
||||||
import forge.Command;
|
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.card.ability.AbilityUtils;
|
import forge.card.ability.AbilityUtils;
|
||||||
import forge.card.cardfactory.CardFactory;
|
import forge.card.cardfactory.CardFactory;
|
||||||
@@ -393,6 +392,7 @@ public class MagicStack extends MyObservable {
|
|||||||
* a {@link forge.card.spellability.SpellAbility} object.
|
* a {@link forge.card.spellability.SpellAbility} object.
|
||||||
*/
|
*/
|
||||||
public final void add(final SpellAbility sp) {
|
public final void add(final SpellAbility sp) {
|
||||||
|
FThreads.checkEDT("MagicStack.add", false);
|
||||||
final ArrayList<TargetChoices> chosenTargets = sp.getAllTargetChoices();
|
final ArrayList<TargetChoices> chosenTargets = sp.getAllTargetChoices();
|
||||||
|
|
||||||
if (sp.isManaAbility()) { // Mana Abilities go straight through
|
if (sp.isManaAbility()) { // Mana Abilities go straight through
|
||||||
@@ -530,17 +530,15 @@ public class MagicStack extends MyObservable {
|
|||||||
|
|
||||||
if (activating.isHuman()) {
|
if (activating.isHuman()) {
|
||||||
sa.getSourceCard().addMultiKickerMagnitude(-1);
|
sa.getSourceCard().addMultiKickerMagnitude(-1);
|
||||||
final Command paidCommand = new Command() {
|
final Runnable paidCommand = new Runnable() {
|
||||||
private static final long serialVersionUID = -6037161763374971106L;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() {
|
public void run() {
|
||||||
abilityIncreaseMultikicker.resolve();
|
abilityIncreaseMultikicker.resolve();
|
||||||
|
|
||||||
final ManaCostBeingPaid manaCost = MagicStack.this.getMultiKickerSpellCostChange(abilityIncreaseMultikicker);
|
final ManaCostBeingPaid manaCost = MagicStack.this.getMultiKickerSpellCostChange(abilityIncreaseMultikicker);
|
||||||
|
|
||||||
if (manaCost.isPaid()) {
|
if (manaCost.isPaid()) {
|
||||||
this.execute();
|
this.run();
|
||||||
} else {
|
} else {
|
||||||
String prompt;
|
String prompt;
|
||||||
int mkCostPaid = game.getActionPlay().getCostCuttingGetMultiKickerManaCostPaid();
|
int mkCostPaid = game.getActionPlay().getCostCuttingGetMultiKickerManaCostPaid();
|
||||||
@@ -555,13 +553,13 @@ public class MagicStack extends MyObservable {
|
|||||||
InputPayManaExecuteCommands toSet = new InputPayManaExecuteCommands(game, prompt, manaCost.toString());
|
InputPayManaExecuteCommands toSet = new InputPayManaExecuteCommands(game, prompt, manaCost.toString());
|
||||||
FThreads.setInputAndWait(toSet);
|
FThreads.setInputAndWait(toSet);
|
||||||
if ( toSet.isPaid() ) {
|
if ( toSet.isPaid() ) {
|
||||||
this.execute();
|
this.run();
|
||||||
} else
|
} else
|
||||||
MagicStack.this.push(sa);
|
MagicStack.this.push(sa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
paidCommand.execute();
|
paidCommand.run();
|
||||||
} else {
|
} else {
|
||||||
// computer
|
// computer
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import forge.CardPredicates;
|
|||||||
import forge.CardUtil;
|
import forge.CardUtil;
|
||||||
import forge.Constant;
|
import forge.Constant;
|
||||||
import forge.CounterType;
|
import forge.CounterType;
|
||||||
|
import forge.FThreads;
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.card.CardType;
|
import forge.card.CardType;
|
||||||
import forge.card.spellability.AbilityManaPart;
|
import forge.card.spellability.AbilityManaPart;
|
||||||
@@ -611,7 +612,7 @@ public final class GuiDisplayUtil {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Card forgeCard = c.toForgeCard(p);
|
final Card forgeCard = c.toForgeCard(p);
|
||||||
|
|
||||||
final GameState game = Singletons.getModel().getGame();
|
final GameState game = Singletons.getModel().getGame();
|
||||||
if (forgeCard.getType().contains("Land")) {
|
if (forgeCard.getType().contains("Land")) {
|
||||||
@@ -628,10 +629,15 @@ public final class GuiDisplayUtil {
|
|||||||
return; // happens if cancelled
|
return; // happens if cancelled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FThreads.invokeInNewThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
sa.setActivatingPlayer(p);
|
sa.setActivatingPlayer(p);
|
||||||
game.getAction().moveToHand(forgeCard); // this is really needed
|
game.getAction().moveToHand(forgeCard); // this is really needed
|
||||||
game.getActionPlay().playSpellAbilityWithoutPayingManaCost(sa);
|
game.getActionPlay().playSpellAbilityWithoutPayingManaCost(sa);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,9 +41,6 @@ import forge.control.input.Input;
|
|||||||
import forge.control.input.InputAttack;
|
import forge.control.input.InputAttack;
|
||||||
import forge.control.input.InputBlock;
|
import forge.control.input.InputBlock;
|
||||||
import forge.control.input.InputPayManaBase;
|
import forge.control.input.InputPayManaBase;
|
||||||
import forge.control.input.InputPayManaExecuteCommands;
|
|
||||||
import forge.control.input.InputPayManaSimple;
|
|
||||||
import forge.control.input.InputPaySacCost;
|
|
||||||
import forge.game.GameState;
|
import forge.game.GameState;
|
||||||
import forge.game.phase.CombatUtil;
|
import forge.game.phase.CombatUtil;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
@@ -56,6 +53,7 @@ import forge.gui.framework.ICDoc;
|
|||||||
import forge.gui.match.CMatchUI;
|
import forge.gui.match.CMatchUI;
|
||||||
import forge.gui.match.controllers.CMessage;
|
import forge.gui.match.controllers.CMessage;
|
||||||
import forge.gui.toolbox.FLabel;
|
import forge.gui.toolbox.FLabel;
|
||||||
|
import forge.view.arcane.CardPanel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controls Swing components of a player's field instance.
|
* Controls Swing components of a player's field instance.
|
||||||
@@ -390,10 +388,14 @@ public class CField implements ICDoc {
|
|||||||
|
|
||||||
final Input input = CMessage.SINGLETON_INSTANCE.getInputControl().getInput();
|
final Input input = CMessage.SINGLETON_INSTANCE.getInputControl().getInput();
|
||||||
|
|
||||||
if (c != null && c.isInZone(ZoneType.Battlefield)) {
|
if (c == null || !c.isInZone(ZoneType.Battlefield)) {
|
||||||
if (c.isTapped() && (input instanceof InputPayManaSimple || input instanceof InputPayManaExecuteCommands)) {
|
return;
|
||||||
final forge.view.arcane.CardPanel cardPanel = CField.this.view.getTabletop().getCardPanel(c.getUniqueNumber());
|
}
|
||||||
for (final forge.view.arcane.CardPanel cp : cardPanel.getAttachedPanels()) {
|
|
||||||
|
// Why does CField filter cards here? That's Input's responsibility to detect incorrect choices!
|
||||||
|
if (c.isTapped() && input instanceof InputPayManaBase) {
|
||||||
|
final CardPanel cardPanel = CField.this.view.getTabletop().getCardPanel(c.getUniqueNumber());
|
||||||
|
for (final CardPanel cp : cardPanel.getAttachedPanels()) {
|
||||||
if (cp.getCard().isUntapped()) {
|
if (cp.getCard().isUntapped()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -402,9 +404,8 @@ public class CField implements ICDoc {
|
|||||||
|
|
||||||
final List<Card> att = Singletons.getModel().getGame().getCombat().getAttackerList();
|
final List<Card> att = Singletons.getModel().getGame().getCombat().getAttackerList();
|
||||||
if ((c.isTapped() || c.hasSickness() || (c.hasKeyword("Vigilance") && att.contains(c))) && (input instanceof InputAttack)) {
|
if ((c.isTapped() || c.hasSickness() || (c.hasKeyword("Vigilance") && att.contains(c))) && (input instanceof InputAttack)) {
|
||||||
final forge.view.arcane.CardPanel cardPanel = CField.this.view.getTabletop().getCardPanel(
|
final CardPanel cardPanel = CField.this.view.getTabletop().getCardPanel(c.getUniqueNumber());
|
||||||
c.getUniqueNumber());
|
for (final CardPanel cp : cardPanel.getAttachedPanels()) {
|
||||||
for (final forge.view.arcane.CardPanel cp : cardPanel.getAttachedPanels()) {
|
|
||||||
if (cp.getCard().isUntapped() && !cp.getCard().hasSickness()) {
|
if (cp.getCard().isUntapped() && !cp.getCard().hasSickness()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -412,8 +413,7 @@ public class CField implements ICDoc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (e.isMetaDown()) {
|
if (e.isMetaDown()) {
|
||||||
if (att.contains(c) && (input instanceof InputAttack)
|
if (att.contains(c) && input instanceof InputAttack && !c.hasKeyword("CARDNAME attacks each turn if able.")) {
|
||||||
&& !c.hasKeyword("CARDNAME attacks each turn if able.")) {
|
|
||||||
c.untap();
|
c.untap();
|
||||||
Singletons.getModel().getGame().getCombat().removeFromCombat(c);
|
Singletons.getModel().getGame().getCombat().removeFromCombat(c);
|
||||||
CombatUtil.showCombat();
|
CombatUtil.showCombat();
|
||||||
@@ -424,9 +424,6 @@ public class CField implements ICDoc {
|
|||||||
((InputBlock) input).removeFromAllBlocking(c);
|
((InputBlock) input).removeFromAllBlocking(c);
|
||||||
CombatUtil.showCombat();
|
CombatUtil.showCombat();
|
||||||
}
|
}
|
||||||
else if (input instanceof InputPaySacCost) {
|
|
||||||
((InputPaySacCost) input).unselectCard(c, Singletons.getControl().getPlayer().getZone(ZoneType.Battlefield));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
//Yosei, the Morning Star required cards to be chosen on computer side
|
//Yosei, the Morning Star required cards to be chosen on computer side
|
||||||
//earlier it was enforced that cards must be in player zone
|
//earlier it was enforced that cards must be in player zone
|
||||||
@@ -437,7 +434,7 @@ public class CField implements ICDoc {
|
|||||||
//in weird case card has no controller revert to default behaviour
|
//in weird case card has no controller revert to default behaviour
|
||||||
input.selectCard(c);
|
input.selectCard(c);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
|
|||||||
Reference in New Issue
Block a user