mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 03:38:01 +00:00
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:
@@ -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)) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user