Show unplayable activated abilities disabled unless activator or zone restriction

Prompt for single activated ability unless mana ability
Show mana abilities before other abilities to match card order
This commit is contained in:
drdev
2013-11-10 21:48:55 +00:00
parent be2ec80f0c
commit c9f491a483
7 changed files with 80 additions and 30 deletions

View File

@@ -2658,8 +2658,8 @@ public class Card extends GameEntity implements Comparable<Card> {
* @return a {@link java.util.ArrayList} object. * @return a {@link java.util.ArrayList} object.
*/ */
public final ArrayList<SpellAbility> getSpellAbilities() { public final ArrayList<SpellAbility> getSpellAbilities() {
final ArrayList<SpellAbility> res = new ArrayList<SpellAbility>(this.getCharacteristics().getSpellAbility()); final ArrayList<SpellAbility> res = new ArrayList<SpellAbility>(this.getManaAbility());
res.addAll(this.getManaAbility()); res.addAll(this.getCharacteristics().getSpellAbility());
return res; return res;
} }
@@ -8669,7 +8669,7 @@ public class Card extends GameEntity implements Comparable<Card> {
* @param player * @param player
* @return * @return
*/ */
public List<SpellAbility> getAllPossibleAbilities(Player player) { public List<SpellAbility> getAllPossibleAbilities(Player player, boolean removeUnplayable) {
// this can only be called by the Human // this can only be called by the Human
final List<SpellAbility> abilities = new ArrayList<SpellAbility>(); final List<SpellAbility> abilities = new ArrayList<SpellAbility>();
@@ -8678,14 +8678,16 @@ public class Card extends GameEntity implements Comparable<Card> {
abilities.add(sa); abilities.add(sa);
abilities.addAll(GameActionUtil.getAlternativeCosts(sa)); abilities.addAll(GameActionUtil.getAlternativeCosts(sa));
} }
for (int iSa = 0; iSa < abilities.size();) { for (int i = abilities.size() - 1; i >= 0; i--) {
SpellAbility sa = abilities.get(iSa); SpellAbility sa = abilities.get(i);
sa.setActivatingPlayer(player); sa.setActivatingPlayer(player);
if (!sa.canPlay()) if (removeUnplayable && !sa.canPlay()) {
abilities.remove(iSa); abilities.remove(i);
else }
iSa++; else if (!sa.isPossible()) {
abilities.remove(i);
}
} }
if (isLand() && player.canPlayLand(this)) { if (isLand() && player.canPlayLand(this)) {

View File

@@ -117,8 +117,19 @@ public abstract class AbilityActivated extends SpellAbility implements java.io.S
return CostPayment.canPayAdditionalCosts(this.getPayCosts(), this); return CostPayment.canPayAdditionalCosts(this.getPayCosts(), this);
} }
/* (non-Javadoc) /** {@inheritDoc} */
* @see forge.card.spellability.SpellAbility#resolve() @Override
*/ public boolean isPossible() {
//consider activated abilities possible always and simply disable if not currently playable
//the exception is to consider them not possible if there's a zone or activator restriction that's not met
return this.getRestrictions().checkZoneRestrictions(this.getSourceCard(), this) &&
this.getRestrictions().checkActivatorRestrictions(this.getSourceCard(), this);
}
/** {@inheritDoc} */
@Override
public boolean promptIfOnlyPossibleAbility() {
return !this.isManaAbility(); //prompt user for non-mana activated abilities even is only possible ability
}
} }

View File

@@ -68,16 +68,18 @@ public abstract class Spell extends SpellAbility implements java.io.Serializable
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public boolean canPlay() { public boolean canPlay() {
final Game game = getActivatingPlayer().getGame();
if (game.getStack().isSplitSecondOnStack()) {
return false;
}
final Card card = this.getSourceCard(); final Card card = this.getSourceCard();
Player activator = this.getActivatingPlayer(); Player activator = this.getActivatingPlayer();
if (activator == null) { if (activator == null) {
activator = this.getSourceCard().getController(); activator = card.getController();
if (activator == null) {
return false;
}
}
final Game game = activator.getGame();
if (game.getStack().isSplitSecondOnStack()) {
return false;
} }
if (!(card.isInstant() || activator.canCastSorcery() || card.hasKeyword("Flash") if (!(card.isInstant() || activator.canCastSorcery() || card.hasKeyword("Flash")

View File

@@ -180,6 +180,28 @@ public abstract class SpellAbility extends GameObject implements ISpellAbility {
* @return a boolean. * @return a boolean.
*/ */
public abstract boolean canPlay(); public abstract boolean canPlay();
/**
* <p>
* isPossible.
* </p>
*
* @return a boolean.
*/
public boolean isPossible() {
return canPlay(); //by default, ability is only possible if it can be played
}
/**
* <p>
* promptIfOnlyPossibleAbility.
* </p>
*
* @return a boolean.
*/
public boolean promptIfOnlyPossibleAbility() {
return false; //by default, don't prompt user if ability is only possible ability
}
// all Spell's and Abilities must override this method // all Spell's and Abilities must override this method
/** /**

View File

@@ -85,29 +85,42 @@ public class PlayerControllerHuman extends PlayerController {
* Uses GUI to learn which spell the player (human in our case) would like to play * Uses GUI to learn which spell the player (human in our case) would like to play
*/ */
public SpellAbility getAbilityToPlay(List<SpellAbility> abilities, MouseEvent triggerEvent) { public SpellAbility getAbilityToPlay(List<SpellAbility> abilities, MouseEvent triggerEvent) {
if (triggerEvent == null) {
List<SpellAbility> playableAbilities = new ArrayList<SpellAbility>();
for (SpellAbility ab : abilities) {
if (ab.canPlay()) {
playableAbilities.add(ab);
}
}
if (playableAbilities.isEmpty()) {
return null;
}
if (playableAbilities.size() == 1 && !playableAbilities.get(0).promptIfOnlyPossibleAbility()) {
return playableAbilities.get(0);
}
return GuiChoose.oneOrNone("Choose ability to play", playableAbilities);
}
if (abilities.isEmpty()) { if (abilities.isEmpty()) {
return null; return null;
} }
if (abilities.size() == 1) { if (abilities.size() == 1 && !abilities.get(0).promptIfOnlyPossibleAbility()) {
return abilities.get(0); return abilities.get(0);
} }
if (triggerEvent == null) {
return GuiChoose.oneOrNone("Choose ability to play", abilities);
}
//show menu if mouse triggered ability //show menu if mouse was trigger for ability
final JPopupMenu menu = new JPopupMenu("Abilities"); final JPopupMenu menu = new JPopupMenu("Abilities");
int shortcut = KeyEvent.VK_1; //use number keys as shortcuts for abilities 1-9 int shortcut = KeyEvent.VK_1; //use number keys as shortcuts for abilities 1-9
for (final SpellAbility ab : abilities) { for (final SpellAbility ab : abilities) {
GuiUtils.addMenuItem(menu, ab.toString(), GuiUtils.addMenuItem(menu, ab.toString(),
shortcut > 0 ? KeyStroke.getKeyStroke(shortcut, 0) : null, shortcut > 0 ? KeyStroke.getKeyStroke(shortcut, 0) : null,
new Runnable() { new Runnable() {
@Override @Override
public void run() { public void run() {
CMessage.SINGLETON_INSTANCE.getInputControl().selectAbility(ab); CMessage.SINGLETON_INSTANCE.getInputControl().selectAbility(ab);
} }
}); }, ab.getActivatingPlayer() == null || ab.canPlay()); //check getActivatingPlayer() to account for playing lands
shortcut++; shortcut++;
if (shortcut > KeyEvent.VK_9) { if (shortcut > KeyEvent.VK_9) {
shortcut = 0; //stop adding shortcuts after 9 shortcut = 0; //stop adding shortcuts after 9

View File

@@ -63,7 +63,7 @@ public class InputPassPriority extends InputSyncronizedBase {
@Override @Override
protected void onCardSelected(final Card card, final MouseEvent triggerEvent) { protected void onCardSelected(final Card card, final MouseEvent triggerEvent) {
List<SpellAbility> abilities = card.getAllPossibleAbilities(player); List<SpellAbility> abilities = card.getAllPossibleAbilities(player, false);
if (abilities.isEmpty()) { if (abilities.isEmpty()) {
flashIncorrectAction(); flashIncorrectAction();
return; return;

View File

@@ -102,7 +102,7 @@ public class CField implements ICDoc {
// TODO: "can play" check needed! // TODO: "can play" check needed!
// should I check for who owns these cards? Are there any abilities to be played from opponent's graveyard? // should I check for who owns these cards? Are there any abilities to be played from opponent's graveyard?
final SpellAbility ab = player.getController().getAbilityToPlay(c.getAllPossibleAbilities(player)); final SpellAbility ab = player.getController().getAbilityToPlay(c.getAllPossibleAbilities(player, true));
if ( null != ab) { if ( null != ab) {
game.getAction().invoke(new Runnable(){ @Override public void run(){ game.getAction().invoke(new Runnable(){ @Override public void run(){
HumanPlay.playSpellAbility(player, ab); HumanPlay.playSpellAbility(player, ab);