mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 20:58:03 +00:00
Support selecting cards further back in stack if tapped card not selectable
This commit is contained in:
@@ -173,12 +173,28 @@ public abstract class VCardDisplayArea extends VDisplayArea {
|
|||||||
ThreadUtil.invokeInGameThread(new Runnable() { //must invoke in game thread in case a dialog needs to be shown
|
ThreadUtil.invokeInGameThread(new Runnable() { //must invoke in game thread in case a dialog needs to be shown
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
FControl.getInputProxy().selectCard(getCard(), null);
|
if (!selectCard()) {
|
||||||
|
//if no cards in stack can be selected, just show zoom/details for card
|
||||||
|
CardZoom.show(getCard());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean selectCard() {
|
||||||
|
if (FControl.getInputProxy().selectCard(getCard(), null)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//if panel can't do anything with card selection, try selecting an attached panel
|
||||||
|
for (CardAreaPanel panel : attachedPanels) {
|
||||||
|
if (panel.selectCard()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean longPress(float x, float y) {
|
public boolean longPress(float x, float y) {
|
||||||
CardZoom.show(getCard());
|
CardZoom.show(getCard());
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import forge.util.ITriggerEvent;
|
|||||||
public interface Input {
|
public interface Input {
|
||||||
void showMessageInitial();
|
void showMessageInitial();
|
||||||
|
|
||||||
void selectCard(Card c, ITriggerEvent triggerEvent);
|
boolean selectCard(Card c, ITriggerEvent triggerEvent);
|
||||||
|
|
||||||
void selectAbility(SpellAbility ab);
|
void selectAbility(SpellAbility ab);
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ public class InputAttack extends InputSyncronizedBase {
|
|||||||
|
|
||||||
setCurrentDefender(defenders.isEmpty() ? null : defenders.get(0));
|
setCurrentDefender(defenders.isEmpty() ? null : defenders.get(0));
|
||||||
|
|
||||||
if ( null == currentDefender ) {
|
if (null == currentDefender) {
|
||||||
System.err.println("InputAttack has no potential defenders!");
|
System.err.println("InputAttack has no potential defenders!");
|
||||||
return; // should even throw here!
|
return; // should even throw here!
|
||||||
}
|
}
|
||||||
@@ -77,8 +77,8 @@ public class InputAttack extends InputSyncronizedBase {
|
|||||||
List<Card> possibleAttackers = playerAttacks.getCardsIn(ZoneType.Battlefield);
|
List<Card> possibleAttackers = playerAttacks.getCardsIn(ZoneType.Battlefield);
|
||||||
for (Card c : Iterables.filter(possibleAttackers, CardPredicates.Presets.CREATURES)) {
|
for (Card c : Iterables.filter(possibleAttackers, CardPredicates.Presets.CREATURES)) {
|
||||||
if (c.hasKeyword("CARDNAME attacks each turn if able.")) {
|
if (c.hasKeyword("CARDNAME attacks each turn if able.")) {
|
||||||
for(GameEntity def : defenders ) {
|
for(GameEntity def : defenders) {
|
||||||
if( CombatUtil.canAttack(c, def, combat) ) {
|
if(CombatUtil.canAttack(c, def, combat)) {
|
||||||
combat.addAttacker(c, currentDefender);
|
combat.addAttacker(c, currentDefender);
|
||||||
GuiBase.getInterface().fireEvent(new UiEventAttackerDeclared(c, currentDefender));
|
GuiBase.getInterface().fireEvent(new UiEventAttackerDeclared(c, currentDefender));
|
||||||
break;
|
break;
|
||||||
@@ -123,7 +123,7 @@ public class InputAttack extends InputSyncronizedBase {
|
|||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
protected final void onCardSelected(final Card card, final ITriggerEvent triggerEvent) {
|
protected final boolean onCardSelected(final Card card, final ITriggerEvent triggerEvent) {
|
||||||
final List<Card> att = combat.getAttackers();
|
final List<Card> att = combat.getAttackers();
|
||||||
if (triggerEvent != null && triggerEvent.getButton() == 3 && att.contains(card) && !card.hasKeyword("CARDNAME attacks each turn if able.")
|
if (triggerEvent != null && triggerEvent.getButton() == 3 && att.contains(card) && !card.hasKeyword("CARDNAME attacks each turn if able.")
|
||||||
&& !card.hasStartOfKeyword("CARDNAME attacks specific player each combat if able")) {
|
&& !card.hasStartOfKeyword("CARDNAME attacks specific player each combat if able")) {
|
||||||
@@ -135,32 +135,37 @@ public class InputAttack extends InputSyncronizedBase {
|
|||||||
this.activateBand(null);
|
this.activateBand(null);
|
||||||
|
|
||||||
GuiBase.getInterface().fireEvent(new UiEventAttackerDeclared(card, null));
|
GuiBase.getInterface().fireEvent(new UiEventAttackerDeclared(card, null));
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (combat.isAttacking(card, currentDefender)) {
|
if (combat.isAttacking(card, currentDefender)) {
|
||||||
// Activate band by selecting/deselecting a band member
|
// Activate band by selecting/deselecting a band member
|
||||||
|
boolean validAction = true;
|
||||||
if (this.activeBand == null) {
|
if (this.activeBand == null) {
|
||||||
this.activateBand(combat.getBandOfAttacker(card));
|
this.activateBand(combat.getBandOfAttacker(card));
|
||||||
} else if (this.activeBand.getAttackers().contains(card)) {
|
}
|
||||||
|
else if (this.activeBand.getAttackers().contains(card)) {
|
||||||
this.activateBand(null);
|
this.activateBand(null);
|
||||||
} else { // Join a band by selecting a non-active band member after activating a band
|
}
|
||||||
|
else { // Join a band by selecting a non-active band member after activating a band
|
||||||
if (this.activeBand.canJoinBand(card)) {
|
if (this.activeBand.canJoinBand(card)) {
|
||||||
combat.removeFromCombat(card);
|
combat.removeFromCombat(card);
|
||||||
declareAttacker(card);
|
declareAttacker(card);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
flashIncorrectAction();
|
flashIncorrectAction();
|
||||||
|
validAction = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateMessage();
|
updateMessage();
|
||||||
return;
|
return validAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( card.getController().isOpponentOf(playerAttacks) ) {
|
if (card.getController().isOpponentOf(playerAttacks)) {
|
||||||
if ( defenders.contains(card) ) { // planeswalker?
|
if (defenders.contains(card)) { // planeswalker?
|
||||||
setCurrentDefender(card);
|
setCurrentDefender(card);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +174,7 @@ public class InputAttack extends InputSyncronizedBase {
|
|||||||
this.activateBand(null);
|
this.activateBand(null);
|
||||||
updateMessage();
|
updateMessage();
|
||||||
flashIncorrectAction();
|
flashIncorrectAction();
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(combat.isAttacking(card)) {
|
if(combat.isAttacking(card)) {
|
||||||
@@ -178,12 +183,12 @@ public class InputAttack extends InputSyncronizedBase {
|
|||||||
|
|
||||||
declareAttacker(card);
|
declareAttacker(card);
|
||||||
showCombat();
|
showCombat();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
flashIncorrectAction();
|
|
||||||
}
|
|
||||||
} // selectCard()
|
|
||||||
|
|
||||||
|
flashIncorrectAction();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Write javadoc for this method.
|
* TODO: Write javadoc for this method.
|
||||||
@@ -199,8 +204,8 @@ public class InputAttack extends InputSyncronizedBase {
|
|||||||
|
|
||||||
private final void setCurrentDefender(GameEntity def) {
|
private final void setCurrentDefender(GameEntity def) {
|
||||||
currentDefender = def;
|
currentDefender = def;
|
||||||
for( GameEntity ge: defenders ) {
|
for(GameEntity ge: defenders) {
|
||||||
if ( ge instanceof Card) {
|
if (ge instanceof Card) {
|
||||||
GuiBase.getInterface().setUsedToPay((Card)ge, ge == def);
|
GuiBase.getInterface().setUsedToPay((Card)ge, ge == def);
|
||||||
}
|
}
|
||||||
else if (ge instanceof Player) {
|
else if (ge instanceof Player) {
|
||||||
|
|||||||
@@ -71,12 +71,14 @@ public abstract class InputBase implements java.io.Serializable, Input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void selectCard(final Card c, final ITriggerEvent triggerEvent) {
|
public final boolean selectCard(final Card c, final ITriggerEvent triggerEvent) {
|
||||||
if (isFinished()) { return; }
|
if (isFinished()) { return false; }
|
||||||
onCardSelected(c, triggerEvent);
|
return onCardSelected(c, triggerEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onCardSelected(final Card c, final ITriggerEvent triggerEvent) {}
|
protected boolean onCardSelected(final Card c, final ITriggerEvent triggerEvent) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
protected void onPlayerSelected(final Player p, final ITriggerEvent triggerEvent) {}
|
protected void onPlayerSelected(final Player p, final ITriggerEvent triggerEvent) {}
|
||||||
protected void onCancel() {}
|
protected void onCancel() {}
|
||||||
protected void onOk() {}
|
protected void onOk() {}
|
||||||
|
|||||||
@@ -97,22 +97,24 @@ public class InputBlock extends InputSyncronizedBase {
|
|||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
public final void onCardSelected(final Card card, final ITriggerEvent triggerEvent) {
|
public final boolean onCardSelected(final Card card, final ITriggerEvent triggerEvent) {
|
||||||
|
boolean isCorrectAction = false;
|
||||||
if (triggerEvent != null && triggerEvent.getButton() == 3 && card.getController() == defender) {
|
if (triggerEvent != null && triggerEvent.getButton() == 3 && card.getController() == defender) {
|
||||||
combat.removeFromCombat(card);
|
combat.removeFromCombat(card);
|
||||||
GuiBase.getInterface().fireEvent(new UiEventBlockerAssigned(card, (Card)null));
|
GuiBase.getInterface().fireEvent(new UiEventBlockerAssigned(card, (Card)null));
|
||||||
} else {
|
isCorrectAction = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
// is attacking?
|
// is attacking?
|
||||||
boolean isCorrectAction = false;
|
|
||||||
|
|
||||||
if (combat.isAttacking(card)) {
|
if (combat.isAttacking(card)) {
|
||||||
setCurrentAttacker(card);
|
setCurrentAttacker(card);
|
||||||
isCorrectAction = true;
|
isCorrectAction = true;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// Make sure this card is valid to even be a blocker
|
// Make sure this card is valid to even be a blocker
|
||||||
if (this.currentAttacker != null && card.isCreature() && defender.getZone(ZoneType.Battlefield).contains(card)) {
|
if (this.currentAttacker != null && card.isCreature() && defender.getZone(ZoneType.Battlefield).contains(card)) {
|
||||||
isCorrectAction = CombatUtil.canBlock(this.currentAttacker, card, combat);
|
isCorrectAction = CombatUtil.canBlock(this.currentAttacker, card, combat);
|
||||||
if ( isCorrectAction ) {
|
if (isCorrectAction) {
|
||||||
combat.addBlocker(this.currentAttacker, card);
|
combat.addBlocker(this.currentAttacker, card);
|
||||||
GuiBase.getInterface().fireEvent(new UiEventBlockerAssigned(card, currentAttacker));
|
GuiBase.getInterface().fireEvent(new UiEventBlockerAssigned(card, currentAttacker));
|
||||||
}
|
}
|
||||||
@@ -124,8 +126,8 @@ public class InputBlock extends InputSyncronizedBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.showMessage();
|
this.showMessage();
|
||||||
} // selectCard()
|
return isCorrectAction;
|
||||||
|
}
|
||||||
|
|
||||||
private void setCurrentAttacker(Card card) {
|
private void setCurrentAttacker(Card card) {
|
||||||
currentAttacker = card;
|
currentAttacker = card;
|
||||||
|
|||||||
@@ -111,13 +111,13 @@ public class InputConfirmMulligan extends InputSyncronizedBase {
|
|||||||
volatile boolean cardSelectLocked = false;
|
volatile boolean cardSelectLocked = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCardSelected(final Card c0, final ITriggerEvent triggerEvent) { // the only place that would cause troubles - input is supposed only to confirm, not to fire abilities
|
protected boolean onCardSelected(final Card c0, final ITriggerEvent triggerEvent) { // the only place that would cause troubles - input is supposed only to confirm, not to fire abilities
|
||||||
boolean fromHand = player.getZone(ZoneType.Hand).contains(c0);
|
boolean fromHand = player.getZone(ZoneType.Hand).contains(c0);
|
||||||
boolean isSerumPowder = c0.getName().equals("Serum Powder");
|
boolean isSerumPowder = c0.getName().equals("Serum Powder");
|
||||||
boolean isLegalChoice = fromHand && (isCommander || isSerumPowder);
|
boolean isLegalChoice = fromHand && (isCommander || isSerumPowder);
|
||||||
if (!isLegalChoice || cardSelectLocked) {
|
if (!isLegalChoice || cardSelectLocked) {
|
||||||
flashIncorrectAction();
|
flashIncorrectAction();
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSerumPowder && SGuiDialog.confirm(c0, "Use " + c0.getName() + "'s ability?")) {
|
if (isSerumPowder && SGuiDialog.confirm(c0, "Use " + c0.getName() + "'s ability?")) {
|
||||||
@@ -132,7 +132,7 @@ public class InputConfirmMulligan extends InputSyncronizedBase {
|
|||||||
cardSelectLocked = false;
|
cardSelectLocked = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCommander) { // allow to choose cards for partial paris
|
if (isCommander) { // allow to choose cards for partial paris
|
||||||
@@ -151,6 +151,7 @@ public class InputConfirmMulligan extends InputSyncronizedBase {
|
|||||||
ButtonUtil.enableAllFocusOk();
|
ButtonUtil.enableAllFocusOk();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean isKeepHand() {
|
public final boolean isKeepHand() {
|
||||||
|
|||||||
@@ -59,10 +59,20 @@ public class InputLockUI implements Input {
|
|||||||
GuiBase.getInterface().showPromptMessage(message);
|
GuiBase.getInterface().showPromptMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void selectCard(Card c, ITriggerEvent triggerEvent) {}
|
@Override
|
||||||
@Override public void selectAbility(SpellAbility ab) {}
|
public boolean selectCard(Card c, ITriggerEvent triggerEvent) {
|
||||||
@Override public void selectPlayer(Player player, ITriggerEvent triggerEvent) {}
|
return false;
|
||||||
@Override public void selectButtonOK() {}
|
}
|
||||||
@Override public void selectButtonCancel() {}
|
@Override
|
||||||
|
public void selectAbility(SpellAbility ab) {
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void selectPlayer(Player player, ITriggerEvent triggerEvent) {
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void selectButtonOK() {
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void selectButtonCancel() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,15 +60,16 @@ public class InputPassPriority extends InputSyncronizedBase {
|
|||||||
public SpellAbility getChosenSa() { return chosenSa; }
|
public SpellAbility getChosenSa() { return chosenSa; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCardSelected(final Card card, final ITriggerEvent triggerEvent) {
|
protected boolean onCardSelected(final Card card, final ITriggerEvent triggerEvent) {
|
||||||
//remove unplayable unless triggerEvent specified, in which case unplayable may be shown as disabled options
|
//remove unplayable unless triggerEvent specified, in which case unplayable may be shown as disabled options
|
||||||
List<SpellAbility> abilities = card.getAllPossibleAbilities(player, triggerEvent == null);
|
List<SpellAbility> abilities = card.getAllPossibleAbilities(player, triggerEvent == null);
|
||||||
if (abilities.isEmpty()) {
|
if (abilities.isEmpty()) {
|
||||||
flashIncorrectAction();
|
flashIncorrectAction();
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
selectAbility(player.getController().getAbilityToPlay(abilities, triggerEvent));
|
selectAbility(player.getController().getAbilityToPlay(abilities, triggerEvent));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -49,13 +49,13 @@ public abstract class InputPayMana extends InputSyncronizedBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCardSelected(final Card card, final ITriggerEvent triggerEvent) {
|
protected boolean onCardSelected(final Card card, final ITriggerEvent triggerEvent) {
|
||||||
if (card.getManaAbility().isEmpty()) {
|
if (card.getManaAbility().isEmpty()) {
|
||||||
flashIncorrectAction();
|
flashIncorrectAction();
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
// only tap card if the mana is needed
|
// only tap card if the mana is needed
|
||||||
activateManaAbility(card, this.manaCost);
|
return activateManaAbility(card, this.manaCost);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -123,18 +123,18 @@ public abstract class InputPayMana extends InputSyncronizedBase {
|
|||||||
* a {@link forge.game.mana.ManaCostBeingPaid} object.
|
* a {@link forge.game.mana.ManaCostBeingPaid} object.
|
||||||
* @return a {@link forge.game.mana.ManaCostBeingPaid} object.
|
* @return a {@link forge.game.mana.ManaCostBeingPaid} object.
|
||||||
*/
|
*/
|
||||||
protected void activateManaAbility(final Card card, ManaCostBeingPaid manaCost) {
|
protected boolean activateManaAbility(final Card card, ManaCostBeingPaid manaCost) {
|
||||||
activateManaAbility(card, manaCost, null);
|
return activateManaAbility(card, manaCost, null);
|
||||||
}
|
}
|
||||||
protected void activateManaAbility(final Card card, ManaCostBeingPaid manaCost, SpellAbility chosenAbility) {
|
protected boolean activateManaAbility(final Card card, ManaCostBeingPaid manaCost, SpellAbility chosenAbility) {
|
||||||
if ( locked ) {
|
if (locked) {
|
||||||
System.err.print("Should wait till previous call to playAbility finishes.");
|
System.err.print("Should wait till previous call to playAbility finishes.");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure computer's lands aren't selected
|
// make sure computer's lands aren't selected
|
||||||
if (card.getController() != player) {
|
if (card.getController() != player) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte colorCanUse = 0;
|
byte colorCanUse = 0;
|
||||||
@@ -149,7 +149,7 @@ public abstract class InputPayMana extends InputSyncronizedBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (colorCanUse == 0) { // no mana cost or something
|
if (colorCanUse == 0) { // no mana cost or something
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<SpellAbility> abilities = new ArrayList<SpellAbility>();
|
List<SpellAbility> abilities = new ArrayList<SpellAbility>();
|
||||||
@@ -157,7 +157,7 @@ public abstract class InputPayMana extends InputSyncronizedBase {
|
|||||||
|
|
||||||
final String typeRes = manaCost.getSourceRestriction();
|
final String typeRes = manaCost.getSourceRestriction();
|
||||||
if (StringUtils.isNotBlank(typeRes) && !card.isType(typeRes)) {
|
if (StringUtils.isNotBlank(typeRes) && !card.isType(typeRes)) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean guessAbilityWithRequiredColors = true;
|
boolean guessAbilityWithRequiredColors = true;
|
||||||
@@ -179,7 +179,7 @@ public abstract class InputPayMana extends InputSyncronizedBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (abilities.isEmpty() || (chosenAbility != null && !abilities.contains(chosenAbility))) {
|
if (abilities.isEmpty() || (chosenAbility != null && !abilities.contains(chosenAbility))) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store some information about color costs to help with any mana choices
|
// Store some information about color costs to help with any mana choices
|
||||||
@@ -251,6 +251,7 @@ public abstract class InputPayMana extends InputSyncronizedBase {
|
|||||||
};
|
};
|
||||||
locked = true;
|
locked = true;
|
||||||
game.getAction().invoke(proc);
|
game.getAction().invoke(proc);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -92,9 +92,9 @@ public class InputPayManaX extends InputPayMana {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCardSelected(final Card card, final ITriggerEvent triggerEvent) {
|
protected boolean onCardSelected(final Card card, final ITriggerEvent triggerEvent) {
|
||||||
// don't allow here the cards that produce only wrong colors
|
// don't allow here the cards that produce only wrong colors
|
||||||
activateManaAbility(card, this.manaCost);
|
return activateManaAbility(card, this.manaCost);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ public final class InputProliferate extends InputSelectManyBase<GameEntity> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCardSelected(final Card card, final ITriggerEvent triggerEvent) {
|
protected boolean onCardSelected(final Card card, final ITriggerEvent triggerEvent) {
|
||||||
if (!card.hasCounters()) {
|
if (!card.hasCounters()) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean entityWasSelected = chosenCounters.containsKey(card);
|
boolean entityWasSelected = chosenCounters.containsKey(card);
|
||||||
@@ -64,6 +64,7 @@ public final class InputProliferate extends InputSelectManyBase<GameEntity> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
refresh();
|
refresh();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -136,11 +136,12 @@ public class InputProxy implements Observer {
|
|||||||
* a {@link forge.game.card.Card} object.
|
* a {@link forge.game.card.Card} object.
|
||||||
* @param triggerEvent
|
* @param triggerEvent
|
||||||
*/
|
*/
|
||||||
public final void selectCard(final Card card, final ITriggerEvent triggerEvent) {
|
public final boolean selectCard(final Card card, final ITriggerEvent triggerEvent) {
|
||||||
Input inp = getInput();
|
Input inp = getInput();
|
||||||
if (inp != null) {
|
if (inp != null) {
|
||||||
inp.selectCard(card, triggerEvent);
|
return inp.selectCard(card, triggerEvent);
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void selectAbility(SpellAbility ab) {
|
public final void selectAbility(SpellAbility ab) {
|
||||||
|
|||||||
@@ -38,11 +38,11 @@ public final class InputSelectCardsForConvoke extends InputSelectManyBase<Card>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCardSelected(final Card card, final ITriggerEvent triggerEvent) {
|
protected boolean onCardSelected(final Card card, final ITriggerEvent triggerEvent) {
|
||||||
if (!availableCreatures.contains(card)) {
|
if (!availableCreatures.contains(card)) {
|
||||||
// Not in untapped creatures list provided. Not a legal Convoke selection.
|
// Not in untapped creatures list provided. Not a legal Convoke selection.
|
||||||
flashIncorrectAction();
|
flashIncorrectAction();
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean entityWasSelected = chosenCards.containsKey(card);
|
boolean entityWasSelected = chosenCards.containsKey(card);
|
||||||
@@ -57,11 +57,12 @@ public final class InputSelectCardsForConvoke extends InputSelectManyBase<Card>
|
|||||||
|
|
||||||
if (remainingCost.getColorlessManaAmount() > 0 && (chosenColor == 0 || !remainingCost.needsColor(chosenColor, player.getManaPool()))) {
|
if (remainingCost.getColorlessManaAmount() > 0 && (chosenColor == 0 || !remainingCost.needsColor(chosenColor, player.getManaPool()))) {
|
||||||
registerConvoked(card, ManaCostShard.COLORLESS, chosenColor);
|
registerConvoked(card, ManaCostShard.COLORLESS, chosenColor);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
for (ManaCostShard shard : remainingCost.getDistinctShards()) {
|
for (ManaCostShard shard : remainingCost.getDistinctShards()) {
|
||||||
if (shard.canBePaidWithManaOfColor(chosenColor)) {
|
if (shard.canBePaidWithManaOfColor(chosenColor)) {
|
||||||
registerConvoked(card, shard, chosenColor);
|
registerConvoked(card, shard, chosenColor);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
showMessage("The colors provided by " + card.toString() + " you've chosen cannot be used to decrease the manacost of " + remainingCost.toString());
|
showMessage("The colors provided by " + card.toString() + " you've chosen cannot be used to decrease the manacost of " + remainingCost.toString());
|
||||||
@@ -70,6 +71,7 @@ public final class InputSelectCardsForConvoke extends InputSelectManyBase<Card>
|
|||||||
}
|
}
|
||||||
|
|
||||||
refresh();
|
refresh();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerConvoked(Card card, ManaCostShard shard, byte chosenColor) {
|
private void registerConvoked(Card card, ManaCostShard shard, byte chosenColor) {
|
||||||
|
|||||||
@@ -25,11 +25,12 @@ public class InputSelectEntitiesFromList<T extends GameEntity> extends InputSele
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCardSelected(final Card c, final ITriggerEvent triggerEvent) {
|
protected boolean onCardSelected(final Card c, final ITriggerEvent triggerEvent) {
|
||||||
if (!selectEntity(c)) {
|
if (!selectEntity(c)) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
refresh();
|
refresh();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -104,33 +104,33 @@ public final class InputSelectTargets extends InputSyncronizedBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final void onCardSelected(final Card card, final ITriggerEvent triggerEvent) {
|
protected final boolean onCardSelected(final Card card, final ITriggerEvent triggerEvent) {
|
||||||
if (!tgt.isUniqueTargets() && targetDepth.containsKey(card)) {
|
if (!tgt.isUniqueTargets() && targetDepth.containsKey(card)) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// leave this in temporarily, there some seriously wrong things going on here
|
// leave this in temporarily, there some seriously wrong things going on here
|
||||||
// Can be targeted doesn't check if the target is a valid type, only if a card is generally "targetable"
|
// Can be targeted doesn't check if the target is a valid type, only if a card is generally "targetable"
|
||||||
if (!card.canBeTargetedBy(sa)) {
|
if (!card.canBeTargetedBy(sa)) {
|
||||||
showMessage(sa.getHostCard() + " - Cannot target this card (Shroud? Protection? Restrictions).");
|
showMessage(sa.getHostCard() + " - Cannot target this card (Shroud? Protection? Restrictions).");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
// If all cards must be from the same zone
|
// If all cards must be from the same zone
|
||||||
if (tgt.isSingleZone() && lastTarget != null && !card.getController().equals(lastTarget.getController())) {
|
if (tgt.isSingleZone() && lastTarget != null && !card.getController().equals(lastTarget.getController())) {
|
||||||
showMessage(sa.getHostCard() + " - Cannot target this card (not in the same zone)");
|
showMessage(sa.getHostCard() + " - Cannot target this card (not in the same zone)");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If all cards must be from different zones
|
// If all cards must be from different zones
|
||||||
if (tgt.isDifferentZone() && lastTarget != null && !card.getController().equals(lastTarget.getController().getOpponent())) {
|
if (tgt.isDifferentZone() && lastTarget != null && !card.getController().equals(lastTarget.getController().getOpponent())) {
|
||||||
showMessage(sa.getHostCard() + " - Cannot target this card (not in different zones)");
|
showMessage(sa.getHostCard() + " - Cannot target this card (not in different zones)");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the cards can't share a creature type
|
// If the cards can't share a creature type
|
||||||
if (tgt.isWithoutSameCreatureType() && lastTarget != null && card.sharesCreatureTypeWith(lastTarget)) {
|
if (tgt.isWithoutSameCreatureType() && lastTarget != null && card.sharesCreatureTypeWith(lastTarget)) {
|
||||||
showMessage(sa.getHostCard() + " - Cannot target this card (should not share a creature type)");
|
showMessage(sa.getHostCard() + " - Cannot target this card (should not share a creature type)");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If all cards must have different controllers
|
// If all cards must have different controllers
|
||||||
@@ -144,17 +144,18 @@ public final class InputSelectTargets extends InputSyncronizedBase {
|
|||||||
}
|
}
|
||||||
if (targetedControllers.contains(card.getController())) {
|
if (targetedControllers.contains(card.getController())) {
|
||||||
showMessage(sa.getHostCard() + " - Cannot target this card (must have different controllers)");
|
showMessage(sa.getHostCard() + " - Cannot target this card (must have different controllers)");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!choices.contains(card)) {
|
if (!choices.contains(card)) {
|
||||||
if (card.isPlaneswalker() && sa.getApi() == ApiType.DealDamage) {
|
if (card.isPlaneswalker() && sa.getApi() == ApiType.DealDamage) {
|
||||||
showMessage(sa.getHostCard() + " - To deal an opposing Planeswalker direct damage, target its controller and then redirect the damage on resolution.");
|
showMessage(sa.getHostCard() + " - To deal an opposing Planeswalker direct damage, target its controller and then redirect the damage on resolution.");
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
showMessage(sa.getHostCard() + " - The selected card is not a valid choice to be targeted.");
|
showMessage(sa.getHostCard() + " - The selected card is not a valid choice to be targeted.");
|
||||||
}
|
}
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tgt.isDividedAsYouChoose()) {
|
if (tgt.isDividedAsYouChoose()) {
|
||||||
@@ -179,8 +180,8 @@ public final class InputSelectTargets extends InputSyncronizedBase {
|
|||||||
sb.append(apiBasedMessage);
|
sb.append(apiBasedMessage);
|
||||||
sb.append(card.toString());
|
sb.append(card.toString());
|
||||||
Integer chosen = SGuiChoose.oneOrNone(sb.toString(), choices);
|
Integer chosen = SGuiChoose.oneOrNone(sb.toString(), choices);
|
||||||
if (null == chosen) {
|
if (chosen == null) {
|
||||||
return;
|
return true; //still return true since there was a valid choice
|
||||||
}
|
}
|
||||||
allocatedPortion = chosen;
|
allocatedPortion = chosen;
|
||||||
} else { // otherwise assign the rest of the damage/protection
|
} else { // otherwise assign the rest of the damage/protection
|
||||||
@@ -190,6 +191,7 @@ public final class InputSelectTargets extends InputSyncronizedBase {
|
|||||||
tgt.addDividedAllocation(card, allocatedPortion);
|
tgt.addDividedAllocation(card, allocatedPortion);
|
||||||
}
|
}
|
||||||
addTarget(card);
|
addTarget(card);
|
||||||
|
return true;
|
||||||
} // selectCard()
|
} // selectCard()
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -727,11 +727,12 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
|||||||
private static final long serialVersionUID = 8338626212893374798L;
|
private static final long serialVersionUID = 8338626212893374798L;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCardSelected(Card c, ITriggerEvent triggerEvent) {
|
protected boolean onCardSelected(Card c, ITriggerEvent triggerEvent) {
|
||||||
Card firstCard = Iterables.getFirst(this.selected, null);
|
Card firstCard = Iterables.getFirst(this.selected, null);
|
||||||
if(firstCard != null && !CardPredicates.sharesColorWith(firstCard).apply(c))
|
if (firstCard != null && !CardPredicates.sharesColorWith(firstCard).apply(c)) {
|
||||||
return;
|
return false;
|
||||||
super.onCardSelected(c, triggerEvent);
|
}
|
||||||
|
return super.onCardSelected(c, triggerEvent);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
inp.setMessage("Select " + Lang.nounWithAmount(num, "card" ) + " of same color to reveal.");
|
inp.setMessage("Select " + Lang.nounWithAmount(num, "card" ) + " of same color to reveal.");
|
||||||
@@ -817,9 +818,9 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCardSelected(Card c, ITriggerEvent triggerEvent) {
|
protected boolean onCardSelected(Card c, ITriggerEvent triggerEvent) {
|
||||||
if (!isValidChoice(c) || c.getCounters(counterType) <= getTimesSelected(c)) {
|
if (!isValidChoice(c) || c.getCounters(counterType) <= getTimesSelected(c)) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tc = getTimesSelected(c);
|
int tc = getTimesSelected(c);
|
||||||
@@ -827,6 +828,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
|||||||
|
|
||||||
onSelectStateChanged(c, true);
|
onSelectStateChanged(c, true);
|
||||||
refresh();
|
refresh();
|
||||||
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user