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.
*/
public final ArrayList<SpellAbility> getSpellAbilities() {
final ArrayList<SpellAbility> res = new ArrayList<SpellAbility>(this.getCharacteristics().getSpellAbility());
res.addAll(this.getManaAbility());
final ArrayList<SpellAbility> res = new ArrayList<SpellAbility>(this.getManaAbility());
res.addAll(this.getCharacteristics().getSpellAbility());
return res;
}
@@ -8669,7 +8669,7 @@ public class Card extends GameEntity implements Comparable<Card> {
* @param player
* @return
*/
public List<SpellAbility> getAllPossibleAbilities(Player player) {
public List<SpellAbility> getAllPossibleAbilities(Player player, boolean removeUnplayable) {
// this can only be called by the Human
final List<SpellAbility> abilities = new ArrayList<SpellAbility>();
@@ -8678,14 +8678,16 @@ public class Card extends GameEntity implements Comparable<Card> {
abilities.add(sa);
abilities.addAll(GameActionUtil.getAlternativeCosts(sa));
}
for (int iSa = 0; iSa < abilities.size();) {
SpellAbility sa = abilities.get(iSa);
for (int i = abilities.size() - 1; i >= 0; i--) {
SpellAbility sa = abilities.get(i);
sa.setActivatingPlayer(player);
if (!sa.canPlay())
abilities.remove(iSa);
else
iSa++;
if (removeUnplayable && !sa.canPlay()) {
abilities.remove(i);
}
else if (!sa.isPossible()) {
abilities.remove(i);
}
}
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);
}
/* (non-Javadoc)
* @see forge.card.spellability.SpellAbility#resolve()
*/
/** {@inheritDoc} */
@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} */
@Override
public boolean canPlay() {
final Game game = getActivatingPlayer().getGame();
if (game.getStack().isSplitSecondOnStack()) {
return false;
}
final Card card = this.getSourceCard();
Player activator = this.getActivatingPlayer();
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")

View File

@@ -180,6 +180,28 @@ public abstract class SpellAbility extends GameObject implements ISpellAbility {
* @return a boolean.
*/
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
/**

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
*/
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()) {
return null;
}
if (abilities.size() == 1) {
if (abilities.size() == 1 && !abilities.get(0).promptIfOnlyPossibleAbility()) {
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");
int shortcut = KeyEvent.VK_1; //use number keys as shortcuts for abilities 1-9
for (final SpellAbility ab : abilities) {
GuiUtils.addMenuItem(menu, ab.toString(),
GuiUtils.addMenuItem(menu, ab.toString(),
shortcut > 0 ? KeyStroke.getKeyStroke(shortcut, 0) : null,
new Runnable() {
@Override
public void run() {
CMessage.SINGLETON_INSTANCE.getInputControl().selectAbility(ab);
}
});
}, ab.getActivatingPlayer() == null || ab.canPlay()); //check getActivatingPlayer() to account for playing lands
shortcut++;
if (shortcut > KeyEvent.VK_9) {
shortcut = 0; //stop adding shortcuts after 9

View File

@@ -63,7 +63,7 @@ public class InputPassPriority extends InputSyncronizedBase {
@Override
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()) {
flashIncorrectAction();
return;

View File

@@ -102,7 +102,7 @@ public class CField implements ICDoc {
// TODO: "can play" check needed!
// 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) {
game.getAction().invoke(new Runnable(){ @Override public void run(){
HumanPlay.playSpellAbility(player, ab);