mirror of
https://github.com/correl/mage.git
synced 2024-11-28 19:19:55 +00:00
* UI: added playable/activatable cards highlight in all zone and windows (mana abilities, commander, graveyard, revealed, etc);
This commit is contained in:
parent
fe52ffd56a
commit
f6123037ec
15 changed files with 302 additions and 192 deletions
|
@ -606,10 +606,13 @@ public final class GamePanel extends javax.swing.JPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void updateGame(GameView game) {
|
public synchronized void updateGame(GameView game) {
|
||||||
updateGame(game, null);
|
updateGame(game, false, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void updateGame(GameView game, Map<String, Serializable> options) {
|
public synchronized void updateGame(GameView game, boolean showPlayable, Map<String, Serializable> options, Set<UUID> targets) {
|
||||||
|
|
||||||
|
prepareSelectableView(game, showPlayable, options, targets);
|
||||||
|
|
||||||
if (playerId == null && game.getWatchedHands() == null) {
|
if (playerId == null && game.getWatchedHands() == null) {
|
||||||
this.handContainer.setVisible(false);
|
this.handContainer.setVisible(false);
|
||||||
} else {
|
} else {
|
||||||
|
@ -622,14 +625,6 @@ public final class GamePanel extends javax.swing.JPanel {
|
||||||
}
|
}
|
||||||
if (playerId != null) {
|
if (playerId != null) {
|
||||||
handCards.put(YOUR_HAND, game.getHand());
|
handCards.put(YOUR_HAND, game.getHand());
|
||||||
// Mark playable
|
|
||||||
if (game.getCanPlayInHand() != null) {
|
|
||||||
for (CardView card : handCards.get(YOUR_HAND).values()) {
|
|
||||||
if (game.getCanPlayInHand().contains(card.getId())) {
|
|
||||||
card.setPlayable(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Get opponents hand cards if available (only possible for players)
|
// Get opponents hand cards if available (only possible for players)
|
||||||
if (game.getOpponentHands() != null) {
|
if (game.getOpponentHands() != null) {
|
||||||
for (Map.Entry<String, SimpleCardsView> hand : game.getOpponentHands().entrySet()) {
|
for (Map.Entry<String, SimpleCardsView> hand : game.getOpponentHands().entrySet()) {
|
||||||
|
@ -1183,25 +1178,23 @@ public final class GamePanel extends javax.swing.JPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ask(String question, GameView gameView, int messageId, Map<String, Serializable> options) {
|
public void ask(String question, GameView gameView, int messageId, Map<String, Serializable> options) {
|
||||||
updateGame(gameView);
|
updateGame(gameView, false, options, null);
|
||||||
this.feedbackPanel.getFeedback(FeedbackMode.QUESTION, question, false, options, messageId, true, gameView.getPhase());
|
this.feedbackPanel.getFeedback(FeedbackMode.QUESTION, question, false, options, messageId, true, gameView.getPhase());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prepareSelectableView(GameView gameView, Map<String, Serializable> options, Set<UUID> targets) {
|
private void prepareSelectableView(GameView gameView, boolean showPlayable, Map<String, Serializable> options, Set<UUID> targets) {
|
||||||
// make cards/perm selectable
|
// make cards/perm selectable/chooseable/playable
|
||||||
// highlighting chosen
|
// playable must be used for ask dialog only (priority and mana pay)
|
||||||
// code calls after each selects or updates, no needs in switch off cards
|
|
||||||
|
|
||||||
Zone needZone = Zone.ALL;
|
Zone needZone = Zone.ALL;
|
||||||
if (options.containsKey("targetZone")) {
|
if (options != null && options.containsKey("targetZone")) {
|
||||||
needZone = (Zone) options.get("targetZone");
|
needZone = (Zone) options.get("targetZone");
|
||||||
}
|
}
|
||||||
|
|
||||||
List<UUID> needChoosen = null;
|
List<UUID> needChoosen;
|
||||||
if (options.containsKey("chosen")) {
|
if (options != null && options.containsKey("chosen")) {
|
||||||
needChoosen = (List<UUID>) options.get("chosen");
|
needChoosen = (List<UUID>) options.get("chosen");
|
||||||
}
|
} else {
|
||||||
if (needChoosen == null) {
|
|
||||||
needChoosen = new ArrayList<>();
|
needChoosen = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1212,7 +1205,14 @@ public final class GamePanel extends javax.swing.JPanel {
|
||||||
needSelectable = new HashSet<>();
|
needSelectable = new HashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needChoosen.size() == 0 && needSelectable.size() == 0) {
|
Set<UUID> needPlayable;
|
||||||
|
if (showPlayable && gameView.getCanPlayObjects() != null) {
|
||||||
|
needPlayable = gameView.getCanPlayObjects();
|
||||||
|
} else {
|
||||||
|
needPlayable = new HashSet<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needChoosen.size() == 0 && needSelectable.size() == 0 && needPlayable.size() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1225,6 +1225,9 @@ public final class GamePanel extends javax.swing.JPanel {
|
||||||
if (needChoosen.contains(card.getId())) {
|
if (needChoosen.contains(card.getId())) {
|
||||||
card.setSelected(true);
|
card.setSelected(true);
|
||||||
}
|
}
|
||||||
|
if (needPlayable.contains(card.getId())) {
|
||||||
|
card.setPlayable(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1237,6 +1240,7 @@ public final class GamePanel extends javax.swing.JPanel {
|
||||||
if (needChoosen.contains(card.getKey())) {
|
if (needChoosen.contains(card.getKey())) {
|
||||||
card.getValue().setSelected(true);
|
card.getValue().setSelected(true);
|
||||||
}
|
}
|
||||||
|
// play from stack unsupported
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1250,6 +1254,9 @@ public final class GamePanel extends javax.swing.JPanel {
|
||||||
if (needChoosen.contains(perm.getKey())) {
|
if (needChoosen.contains(perm.getKey())) {
|
||||||
perm.getValue().setSelected(true);
|
perm.getValue().setSelected(true);
|
||||||
}
|
}
|
||||||
|
if (needPlayable.contains(perm.getKey())) {
|
||||||
|
perm.getValue().setPlayable(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1264,6 +1271,9 @@ public final class GamePanel extends javax.swing.JPanel {
|
||||||
if (needChoosen.contains(card.getKey())) {
|
if (needChoosen.contains(card.getKey())) {
|
||||||
card.getValue().setSelected(true);
|
card.getValue().setSelected(true);
|
||||||
}
|
}
|
||||||
|
if (needPlayable.contains(card.getKey())) {
|
||||||
|
card.getValue().setPlayable(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1278,6 +1288,26 @@ public final class GamePanel extends javax.swing.JPanel {
|
||||||
if (needChoosen.contains(card.getKey())) {
|
if (needChoosen.contains(card.getKey())) {
|
||||||
card.getValue().setSelected(true);
|
card.getValue().setSelected(true);
|
||||||
}
|
}
|
||||||
|
if (needPlayable.contains(card.getKey())) {
|
||||||
|
card.getValue().setPlayable(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// command
|
||||||
|
if (needZone == Zone.COMMAND || needZone == Zone.ALL) {
|
||||||
|
for (PlayerView player : gameView.getPlayers()) {
|
||||||
|
for (CommandObjectView com : player.getCommandObjectList()) {
|
||||||
|
if (needSelectable.contains(com.getId())) {
|
||||||
|
com.setChoosable(true);
|
||||||
|
}
|
||||||
|
if (needChoosen.contains(com.getId())) {
|
||||||
|
com.setSelected(true);
|
||||||
|
}
|
||||||
|
if (needPlayable.contains(com.getId())) {
|
||||||
|
com.setPlayable(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1291,6 +1321,9 @@ public final class GamePanel extends javax.swing.JPanel {
|
||||||
if (needChoosen.contains(card.getKey())) {
|
if (needChoosen.contains(card.getKey())) {
|
||||||
card.getValue().setSelected(true);
|
card.getValue().setSelected(true);
|
||||||
}
|
}
|
||||||
|
if (needPlayable.contains(card.getKey())) {
|
||||||
|
card.getValue().setPlayable(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1315,10 +1348,8 @@ public final class GamePanel extends javax.swing.JPanel {
|
||||||
switch (needType) {
|
switch (needType) {
|
||||||
case PICK_ABILITY:
|
case PICK_ABILITY:
|
||||||
popupMenuType = PopUpMenuType.TRIGGER_ORDER;
|
popupMenuType = PopUpMenuType.TRIGGER_ORDER;
|
||||||
prepareSelectableView(gameView, options, targets);
|
|
||||||
break;
|
break;
|
||||||
case PICK_TARGET:
|
case PICK_TARGET:
|
||||||
prepareSelectableView(gameView, options, targets);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logger.warn("Unknown query type in pick target: " + needType + " in " + message);
|
logger.warn("Unknown query type in pick target: " + needType + " in " + message);
|
||||||
|
@ -1327,7 +1358,8 @@ public final class GamePanel extends javax.swing.JPanel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateGame(gameView);
|
updateGame(gameView, false, options, targets);
|
||||||
|
|
||||||
Map<String, Serializable> options0 = options == null ? new HashMap<>() : options;
|
Map<String, Serializable> options0 = options == null ? new HashMap<>() : options;
|
||||||
ShowCardsDialog dialog = null;
|
ShowCardsDialog dialog = null;
|
||||||
if (cardView != null && !cardView.isEmpty()) {
|
if (cardView != null && !cardView.isEmpty()) {
|
||||||
|
@ -1359,7 +1391,8 @@ public final class GamePanel extends javax.swing.JPanel {
|
||||||
PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"),
|
PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"),
|
||||||
false);
|
false);
|
||||||
|
|
||||||
updateGame(gameView, options);
|
updateGame(gameView, true, options, null);
|
||||||
|
|
||||||
boolean controllingPlayer = false;
|
boolean controllingPlayer = false;
|
||||||
for (PlayerView playerView : gameView.getPlayers()) {
|
for (PlayerView playerView : gameView.getPlayers()) {
|
||||||
if (playerView.getPlayerId().equals(playerId)) {
|
if (playerView.getPlayerId().equals(playerId)) {
|
||||||
|
@ -1393,13 +1426,13 @@ public final class GamePanel extends javax.swing.JPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void playMana(String message, GameView gameView, Map<String, Serializable> options, int messageId) {
|
public void playMana(String message, GameView gameView, Map<String, Serializable> options, int messageId) {
|
||||||
updateGame(gameView);
|
updateGame(gameView, true, options, null);
|
||||||
DialogManager.getManager(gameId).fadeOut();
|
DialogManager.getManager(gameId).fadeOut();
|
||||||
this.feedbackPanel.getFeedback(FeedbackMode.CANCEL, message, gameView.getSpecial(), options, messageId, true, gameView.getPhase());
|
this.feedbackPanel.getFeedback(FeedbackMode.CANCEL, message, gameView.getSpecial(), options, messageId, true, gameView.getPhase());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void playXMana(String message, GameView gameView, int messageId) {
|
public void playXMana(String message, GameView gameView, int messageId) {
|
||||||
updateGame(gameView);
|
updateGame(gameView, true, null, null);
|
||||||
DialogManager.getManager(gameId).fadeOut();
|
DialogManager.getManager(gameId).fadeOut();
|
||||||
this.feedbackPanel.getFeedback(FeedbackMode.CONFIRM, message, gameView.getSpecial(), null, messageId, true, gameView.getPhase());
|
this.feedbackPanel.getFeedback(FeedbackMode.CONFIRM, message, gameView.getSpecial(), null, messageId, true, gameView.getPhase());
|
||||||
}
|
}
|
||||||
|
|
|
@ -274,7 +274,7 @@ public class CallbackClientImpl implements CallbackClient {
|
||||||
if (panel != null) {
|
if (panel != null) {
|
||||||
appendJsonEvent("GAME_UPDATE", callback.getObjectId(), callback.getData());
|
appendJsonEvent("GAME_UPDATE", callback.getObjectId(), callback.getData());
|
||||||
|
|
||||||
panel.updateGame((GameView) callback.getData());
|
panel.updateGame((GameView) callback.getData(), true, null, null); // update after undo
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
|
|
||||||
package mage.client.util;
|
package mage.client.util;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.cards.repository.CardInfo;
|
import mage.cards.repository.CardInfo;
|
||||||
import mage.cards.repository.CardRepository;
|
import mage.cards.repository.CardRepository;
|
||||||
import mage.view.*;
|
import mage.view.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public final class CardsViewUtil {
|
public final class CardsViewUtil {
|
||||||
|
@ -55,9 +54,8 @@ public final class CardsViewUtil {
|
||||||
CardView cardView = new CardView((EmblemView) commandObject);
|
CardView cardView = new CardView((EmblemView) commandObject);
|
||||||
cards.put(commandObject.getId(), cardView);
|
cards.put(commandObject.getId(), cardView);
|
||||||
} else if (commandObject instanceof PlaneView) {
|
} else if (commandObject instanceof PlaneView) {
|
||||||
CardView cardView = null;
|
CardView cardView = new CardView((PlaneView) commandObject);
|
||||||
cardView = new CardView((PlaneView) commandObject);
|
cards.put(commandObject.getId(), cardView);
|
||||||
cards.put(commandObject.getId(), cardView);
|
|
||||||
} else if (commandObject instanceof CommanderView) {
|
} else if (commandObject instanceof CommanderView) {
|
||||||
cards.put(commandObject.getId(), (CommanderView) commandObject);
|
cards.put(commandObject.getId(), (CommanderView) commandObject);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ import java.util.stream.Collectors;
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
public class CardView extends SimpleCardView {
|
public class CardView extends SimpleCardView implements SelectableObjectView {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,18 @@
|
||||||
|
|
||||||
|
|
||||||
package mage.view;
|
package mage.view;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author Plopman
|
* @author Plopman
|
||||||
*/
|
*/
|
||||||
public interface CommandObjectView extends Serializable {
|
public interface CommandObjectView extends SelectableObjectView {
|
||||||
public String getExpansionSetCode();
|
|
||||||
|
|
||||||
public String getName();
|
String getExpansionSetCode();
|
||||||
|
|
||||||
public UUID getId();
|
String getName();
|
||||||
|
|
||||||
public List<String> getRules();
|
UUID getId();
|
||||||
|
|
||||||
|
List<String> getRules();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
package mage.view;
|
package mage.view;
|
||||||
|
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.game.command.Emblem;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.cards.Card;
|
|
||||||
import mage.game.command.Emblem;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author noxx
|
* @author noxx
|
||||||
|
@ -15,24 +16,24 @@ public class EmblemView implements CommandObjectView, Serializable {
|
||||||
protected String name;
|
protected String name;
|
||||||
protected String expansionSetCode;
|
protected String expansionSetCode;
|
||||||
protected List<String> rules;
|
protected List<String> rules;
|
||||||
|
protected boolean isPlayable = false;
|
||||||
|
|
||||||
public EmblemView(Emblem emblem, Card sourceCard) {
|
public EmblemView(Emblem emblem, Card sourceCard) {
|
||||||
id = emblem.getId();
|
this.id = emblem.getId();
|
||||||
name = "Emblem " + sourceCard.getName();
|
this.name = "Emblem " + sourceCard.getName();
|
||||||
if (emblem.getExpansionSetCodeForImage() == null) {
|
if (emblem.getExpansionSetCodeForImage() == null) {
|
||||||
expansionSetCode = sourceCard.getExpansionSetCode();
|
this.expansionSetCode = sourceCard.getExpansionSetCode();
|
||||||
} else {
|
} else {
|
||||||
expansionSetCode = emblem.getExpansionSetCodeForImage();
|
this.expansionSetCode = emblem.getExpansionSetCodeForImage();
|
||||||
}
|
}
|
||||||
|
this.rules = emblem.getAbilities().getRules(sourceCard.getName());
|
||||||
rules = emblem.getAbilities().getRules(sourceCard.getName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public EmblemView(Emblem emblem) {
|
public EmblemView(Emblem emblem) {
|
||||||
id = emblem.getId();
|
this.id = emblem.getId();
|
||||||
name = emblem.getName();
|
this.name = emblem.getName();
|
||||||
expansionSetCode = emblem.getExpansionSetCodeForImage();
|
this.expansionSetCode = emblem.getExpansionSetCodeForImage();
|
||||||
rules = emblem.getAbilities().getRules(emblem.getName());
|
this.rules = emblem.getAbilities().getRules(emblem.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -54,4 +55,37 @@ public class EmblemView implements CommandObjectView, Serializable {
|
||||||
public List<String> getRules() {
|
public List<String> getRules() {
|
||||||
return rules;
|
return rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPlayable() {
|
||||||
|
return isPlayable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPlayable(boolean isPlayable) {
|
||||||
|
this.isPlayable = isPlayable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isChoosable() {
|
||||||
|
// unsupported
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setChoosable(boolean isChoosable) {
|
||||||
|
// unsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSelected() {
|
||||||
|
// unsupported
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSelected(boolean selected) {
|
||||||
|
// unsupported
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ public class GameView implements Serializable {
|
||||||
private final int priorityTime;
|
private final int priorityTime;
|
||||||
private final List<PlayerView> players = new ArrayList<>();
|
private final List<PlayerView> players = new ArrayList<>();
|
||||||
private CardsView hand;
|
private CardsView hand;
|
||||||
private Set<UUID> canPlayInHand;
|
private Set<UUID> canPlayObjects;
|
||||||
private Map<String, SimpleCardsView> opponentHands;
|
private Map<String, SimpleCardsView> opponentHands;
|
||||||
private Map<String, SimpleCardsView> watchedHands;
|
private Map<String, SimpleCardsView> watchedHands;
|
||||||
private final CardsView stack = new CardsView();
|
private final CardsView stack = new CardsView();
|
||||||
|
@ -300,12 +300,12 @@ public class GameView implements Serializable {
|
||||||
return isPlayer;
|
return isPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<UUID> getCanPlayInHand() {
|
public Set<UUID> getCanPlayObjects() {
|
||||||
return canPlayInHand;
|
return canPlayObjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCanPlayInHand(Set<UUID> canPlayInHand) {
|
public void setCanPlayObjects(Set<UUID> canPlayObjects) {
|
||||||
this.canPlayInHand = canPlayInHand;
|
this.canPlayObjects = canPlayObjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSpellsCastCurrentTurn() {
|
public int getSpellsCastCurrentTurn() {
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
package mage.view;
|
package mage.view;
|
||||||
|
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.game.command.Plane;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import mage.cards.Card;
|
|
||||||
import mage.game.command.Plane;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author spjspj
|
* @author spjspj
|
||||||
|
@ -16,23 +17,24 @@ public class PlaneView implements CommandObjectView, Serializable {
|
||||||
protected String expansionSetCode;
|
protected String expansionSetCode;
|
||||||
protected List<String> rules;
|
protected List<String> rules;
|
||||||
|
|
||||||
public PlaneView(Plane plane, Card sourceCard) {
|
protected boolean isPlayable = false;
|
||||||
id = plane.getId();
|
|
||||||
name = "Plane " + sourceCard.getName();
|
|
||||||
if (plane.getExpansionSetCodeForImage() == null) {
|
|
||||||
expansionSetCode = sourceCard.getExpansionSetCode();
|
|
||||||
} else {
|
|
||||||
expansionSetCode = plane.getExpansionSetCodeForImage();
|
|
||||||
}
|
|
||||||
|
|
||||||
rules = plane.getAbilities().getRules(sourceCard.getName());
|
public PlaneView(Plane plane, Card sourceCard) {
|
||||||
|
this.id = plane.getId();
|
||||||
|
this.name = "Plane " + sourceCard.getName();
|
||||||
|
if (plane.getExpansionSetCodeForImage() == null) {
|
||||||
|
this.expansionSetCode = sourceCard.getExpansionSetCode();
|
||||||
|
} else {
|
||||||
|
this.expansionSetCode = plane.getExpansionSetCodeForImage();
|
||||||
|
}
|
||||||
|
this.rules = plane.getAbilities().getRules(sourceCard.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlaneView(Plane plane) {
|
public PlaneView(Plane plane) {
|
||||||
id = plane.getId();
|
this.id = plane.getId();
|
||||||
name = plane.getName();
|
this.name = plane.getName();
|
||||||
expansionSetCode = plane.getExpansionSetCodeForImage();
|
this.expansionSetCode = plane.getExpansionSetCodeForImage();
|
||||||
rules = plane.getAbilities().getRules(plane.getName());
|
this.rules = plane.getAbilities().getRules(plane.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -54,4 +56,36 @@ public class PlaneView implements CommandObjectView, Serializable {
|
||||||
public List<String> getRules() {
|
public List<String> getRules() {
|
||||||
return rules;
|
return rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPlayable() {
|
||||||
|
return isPlayable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPlayable(boolean isPlayable) {
|
||||||
|
this.isPlayable = isPlayable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isChoosable() {
|
||||||
|
// unsupported
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setChoosable(boolean isChoosable) {
|
||||||
|
// unsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSelected() {
|
||||||
|
// unsupported
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSelected(boolean selected) {
|
||||||
|
// unsupported
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package mage.view;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author JayDi85
|
||||||
|
*/
|
||||||
|
public interface SelectableObjectView {
|
||||||
|
|
||||||
|
boolean isPlayable();
|
||||||
|
|
||||||
|
void setPlayable(boolean isPlayable);
|
||||||
|
|
||||||
|
boolean isChoosable();
|
||||||
|
|
||||||
|
void setChoosable(boolean isChoosable);
|
||||||
|
|
||||||
|
boolean isSelected();
|
||||||
|
|
||||||
|
void setSelected(boolean selected);
|
||||||
|
}
|
|
@ -1,14 +1,10 @@
|
||||||
|
|
||||||
package mage.server.game;
|
package mage.server.game;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import mage.cards.Cards;
|
import mage.cards.Cards;
|
||||||
import mage.choices.Choice;
|
import mage.choices.Choice;
|
||||||
import mage.constants.ManaType;
|
import mage.constants.ManaType;
|
||||||
import mage.constants.PlayerAction;
|
import mage.constants.PlayerAction;
|
||||||
|
import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.Table;
|
import mage.game.Table;
|
||||||
import mage.interfaces.callback.ClientCallback;
|
import mage.interfaces.callback.ClientCallback;
|
||||||
|
@ -20,6 +16,11 @@ import mage.server.util.ThreadExecutor;
|
||||||
import mage.view.*;
|
import mage.view.*;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
*/
|
*/
|
||||||
|
@ -152,7 +153,7 @@ public class GameSessionPlayer extends GameSessionWatcher {
|
||||||
UserRequestMessage userRequestMessage = new UserRequestMessage(
|
UserRequestMessage userRequestMessage = new UserRequestMessage(
|
||||||
"User request",
|
"User request",
|
||||||
"Allow user <b>" + watcher.get().getName() + "</b> for this match to see your hand cards?<br>"
|
"Allow user <b>" + watcher.get().getName() + "</b> for this match to see your hand cards?<br>"
|
||||||
+ "(You can revoke this every time using related popup menu item of your battlefield.)");
|
+ "(You can revoke this every time using related popup menu item of your battlefield.)");
|
||||||
userRequestMessage.setRelatedUser(watcherId, watcher.get().getName());
|
userRequestMessage.setRelatedUser(watcherId, watcher.get().getName());
|
||||||
userRequestMessage.setGameId(game.getId());
|
userRequestMessage.setGameId(game.getId());
|
||||||
userRequestMessage.setButton1("Accept", PlayerAction.ADD_PERMISSION_TO_SEE_HAND_CARDS);
|
userRequestMessage.setButton1("Accept", PlayerAction.ADD_PERMISSION_TO_SEE_HAND_CARDS);
|
||||||
|
@ -188,7 +189,7 @@ public class GameSessionPlayer extends GameSessionWatcher {
|
||||||
GameView gameView = new GameView(game.getState(), game, playerId, null);
|
GameView gameView = new GameView(game.getState(), game, playerId, null);
|
||||||
gameView.setHand(new CardsView(game, player.getHand().getCards(game)));
|
gameView.setHand(new CardsView(game, player.getHand().getCards(game)));
|
||||||
if (gameView.getPriorityPlayerName().equals(player.getName())) {
|
if (gameView.getPriorityPlayerName().equals(player.getName())) {
|
||||||
gameView.setCanPlayInHand(player.getPlayableInHand(game));
|
gameView.setCanPlayObjects(player.getPlayableObjects(game, Zone.ALL));
|
||||||
}
|
}
|
||||||
|
|
||||||
processControlledPlayers(player, gameView);
|
processControlledPlayers(player, gameView);
|
||||||
|
|
|
@ -169,7 +169,7 @@ class WordOfCommandEffect extends OneShotEffect {
|
||||||
private boolean checkPlayability(Card card, Player targetPlayer, Game game, Ability source) {
|
private boolean checkPlayability(Card card, Player targetPlayer, Game game, Ability source) {
|
||||||
// check for card playability
|
// check for card playability
|
||||||
boolean canPlay = false;
|
boolean canPlay = false;
|
||||||
if (card.isLand()) { // we can't use getPlayableInHand(game) in here because it disallows playing lands outside the main step
|
if (card.isLand()) { // we can't use getPlayableObjects(game) in here because it disallows playing lands outside the main step // TODO: replace to getPlayable() checks with disable step condition?
|
||||||
if (targetPlayer.canPlayLand()
|
if (targetPlayer.canPlayLand()
|
||||||
&& game.getActivePlayerId().equals(targetPlayer.getId())) {
|
&& game.getActivePlayerId().equals(targetPlayer.getId())) {
|
||||||
canPlay = true;
|
canPlay = true;
|
||||||
|
@ -182,7 +182,7 @@ class WordOfCommandEffect extends OneShotEffect {
|
||||||
} else { // Word of Command allows the chosen card to be played "as if it had flash" so we need to invoke such effect to bypass the check
|
} else { // Word of Command allows the chosen card to be played "as if it had flash" so we need to invoke such effect to bypass the check
|
||||||
AsThoughEffectImpl effect2 = new WordOfCommandTestFlashEffect();
|
AsThoughEffectImpl effect2 = new WordOfCommandTestFlashEffect();
|
||||||
game.addEffect(effect2, source);
|
game.addEffect(effect2, source);
|
||||||
if (targetPlayer.getPlayableInHand(game).contains(card.getId())) {
|
if (targetPlayer.getPlayableObjects(game, Zone.HAND).contains(card.getId())) {
|
||||||
canPlay = true;
|
canPlay = true;
|
||||||
}
|
}
|
||||||
for (AsThoughEffect eff : game.getContinuousEffects().getApplicableAsThoughEffects(AsThoughEffectType.CAST_AS_INSTANT, game)) {
|
for (AsThoughEffect eff : game.getContinuousEffects().getApplicableAsThoughEffects(AsThoughEffectType.CAST_AS_INSTANT, game)) {
|
||||||
|
|
|
@ -2809,8 +2809,8 @@ public class TestPlayer implements Player {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<UUID> getPlayableInHand(Game game) {
|
public Set<UUID> getPlayableObjects(Game game, Zone zone) {
|
||||||
return computerPlayer.getPlayableInHand(game);
|
return computerPlayer.getPlayableObjects(game, zone);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1047,7 +1047,7 @@ public class PlayerStub implements Player {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<UUID> getPlayableInHand(Game game) {
|
public Set<UUID> getPlayableObjects(Game game, Zone zone) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -633,7 +633,7 @@ public interface Player extends MageItem, Copyable<Player> {
|
||||||
|
|
||||||
List<Ability> getPlayableOptions(Ability ability, Game game);
|
List<Ability> getPlayableOptions(Ability ability, Game game);
|
||||||
|
|
||||||
Set<UUID> getPlayableInHand(Game game);
|
Set<UUID> getPlayableObjects(Game game, Zone zone);
|
||||||
|
|
||||||
LinkedHashMap<UUID, ActivatedAbility> getUseableActivatedAbilities(MageObject object, Zone zone, Game game);
|
LinkedHashMap<UUID, ActivatedAbility> getUseableActivatedAbilities(MageObject object, Zone zone, Game game);
|
||||||
|
|
||||||
|
|
|
@ -3049,17 +3049,22 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Ability> getPlayable(Game game, boolean hidden) {
|
public List<Ability> getPlayable(Game game, boolean hidden) {
|
||||||
|
return getPlayable(game, hidden, Zone.ALL, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Ability> getPlayable(Game game, boolean hidden, Zone fromZone, boolean hideDuplicatedAbilities) {
|
||||||
List<Ability> playable = new ArrayList<>();
|
List<Ability> playable = new ArrayList<>();
|
||||||
|
|
||||||
if (!shouldSkipGettingPlayable(game)) {
|
if (!shouldSkipGettingPlayable(game)) {
|
||||||
|
|
||||||
ManaOptions availableMana = getManaAvailable(game);
|
ManaOptions availableMana = getManaAvailable(game);
|
||||||
availableMana.addMana(manaPool.getMana());
|
availableMana.addMana(manaPool.getMana());
|
||||||
for (ConditionalMana conditionalMana : manaPool.getConditionalMana()) {
|
for (ConditionalMana conditionalMana : manaPool.getConditionalMana()) {
|
||||||
availableMana.addMana(conditionalMana);
|
availableMana.addMana(conditionalMana);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hidden) {
|
boolean fromAll = fromZone.equals(Zone.ALL);
|
||||||
|
|
||||||
|
if (hidden && (fromAll || fromZone == Zone.HAND)) {
|
||||||
for (Card card : hand.getUniqueCards(game)) {
|
for (Card card : hand.getUniqueCards(game)) {
|
||||||
for (Ability ability : card.getAbilities(game)) { // gets this activated ability from hand? (Morph?)
|
for (Ability ability : card.getAbilities(game)) { // gets this activated ability from hand? (Morph?)
|
||||||
if (ability.getZone().match(Zone.HAND)) {
|
if (ability.getZone().match(Zone.HAND)) {
|
||||||
|
@ -3088,35 +3093,39 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Card card : graveyard.getUniqueCards(game)) {
|
if (fromAll || fromZone == Zone.GRAVEYARD) {
|
||||||
// Handle split cards in graveyard to support Aftermath
|
for (Card card : graveyard.getUniqueCards(game)) {
|
||||||
if (card instanceof SplitCard) {
|
// Handle split cards in graveyard to support Aftermath
|
||||||
SplitCard splitCard = (SplitCard) card;
|
if (card instanceof SplitCard) {
|
||||||
getPlayableFromGraveyardCard(game, splitCard.getLeftHalfCard(), splitCard.getLeftHalfCard().getAbilities(), availableMana, playable);
|
SplitCard splitCard = (SplitCard) card;
|
||||||
getPlayableFromGraveyardCard(game, splitCard.getRightHalfCard(), splitCard.getRightHalfCard().getAbilities(), availableMana, playable);
|
getPlayableFromGraveyardCard(game, splitCard.getLeftHalfCard(), splitCard.getLeftHalfCard().getAbilities(), availableMana, playable);
|
||||||
getPlayableFromGraveyardCard(game, splitCard, splitCard.getSharedAbilities(), availableMana, playable);
|
getPlayableFromGraveyardCard(game, splitCard.getRightHalfCard(), splitCard.getRightHalfCard().getAbilities(), availableMana, playable);
|
||||||
} else {
|
getPlayableFromGraveyardCard(game, splitCard, splitCard.getSharedAbilities(), availableMana, playable);
|
||||||
getPlayableFromGraveyardCard(game, card, card.getAbilities(), availableMana, playable);
|
} else {
|
||||||
}
|
getPlayableFromGraveyardCard(game, card, card.getAbilities(), availableMana, playable);
|
||||||
|
}
|
||||||
|
|
||||||
// Other activated abilities
|
// Other activated abilities
|
||||||
LinkedHashMap<UUID, ActivatedAbility> useable = new LinkedHashMap<>();
|
LinkedHashMap<UUID, ActivatedAbility> useable = new LinkedHashMap<>();
|
||||||
getOtherUseableActivatedAbilities(card, Zone.GRAVEYARD, game, useable);
|
getOtherUseableActivatedAbilities(card, Zone.GRAVEYARD, game, useable);
|
||||||
playable.addAll(useable.values());
|
playable.addAll(useable.values());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ExileZone exile : game.getExile().getExileZones()) {
|
if (fromAll || fromZone == Zone.EXILED) {
|
||||||
for (Card card : exile.getCards(game)) {
|
for (ExileZone exile : game.getExile().getExileZones()) {
|
||||||
if (null != game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, null, this.getId(), game)) {
|
for (Card card : exile.getCards(game)) {
|
||||||
for (Ability ability : card.getAbilities()) {
|
if (null != game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, null, this.getId(), game)) {
|
||||||
if (ability.getZone().match(Zone.HAND)) {
|
for (Ability ability : card.getAbilities()) {
|
||||||
ability.setControllerId(this.getId()); // controller must be set for case owner != caster
|
if (ability.getZone().match(Zone.HAND)) {
|
||||||
if (ability instanceof ActivatedAbility) {
|
ability.setControllerId(this.getId()); // controller must be set for case owner != caster
|
||||||
if (((ActivatedAbility) ability).canActivate(playerId, game).canActivate()) {
|
if (ability instanceof ActivatedAbility) {
|
||||||
playable.add(ability);
|
if (((ActivatedAbility) ability).canActivate(playerId, game).canActivate()) {
|
||||||
|
playable.add(ability);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
ability.setControllerId(card.getOwnerId());
|
||||||
}
|
}
|
||||||
ability.setControllerId(card.getOwnerId());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3124,25 +3133,10 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check to play revealed cards
|
// check to play revealed cards
|
||||||
for (Cards cards : game.getState().getRevealed().values()) {
|
if (fromAll) {
|
||||||
for (Card card : cards.getCards(game)) {
|
for (Cards cards : game.getState().getRevealed().values()) {
|
||||||
if (null != game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, null, this.getId(), game)) {
|
for (Card card : cards.getCards(game)) {
|
||||||
for (ActivatedAbility ability : card.getAbilities().getActivatedAbilities(Zone.HAND)) {
|
if (null != game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, null, this.getId(), game)) {
|
||||||
if (ability instanceof SpellAbility || ability instanceof PlayLandAbility) {
|
|
||||||
playable.add(ability);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if it's possible to play the top card of a library
|
|
||||||
for (UUID playerInRangeId : game.getState().getPlayersInRange(getId(), game)) {
|
|
||||||
Player player = game.getPlayer(playerInRangeId);
|
|
||||||
if (player != null) {
|
|
||||||
if (/*player.isTopCardRevealed() &&*/player.getLibrary().hasCards()) {
|
|
||||||
Card card = player.getLibrary().getFromTop(game);
|
|
||||||
if (card != null && null != game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, card.getSpellAbility(), getId(), game)) {
|
|
||||||
for (ActivatedAbility ability : card.getAbilities().getActivatedAbilities(Zone.HAND)) {
|
for (ActivatedAbility ability : card.getAbilities().getActivatedAbilities(Zone.HAND)) {
|
||||||
if (ability instanceof SpellAbility || ability instanceof PlayLandAbility) {
|
if (ability instanceof SpellAbility || ability instanceof PlayLandAbility) {
|
||||||
playable.add(ability);
|
playable.add(ability);
|
||||||
|
@ -3153,35 +3147,69 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// eliminate duplicate activated abilities
|
// check if it's possible to play the top card of a library
|
||||||
Map<String, Ability> playableActivated = new HashMap<>();
|
if (fromAll || fromZone == Zone.LIBRARY) {
|
||||||
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(playerId)) {
|
for (UUID playerInRangeId : game.getState().getPlayersInRange(getId(), game)) {
|
||||||
LinkedHashMap<UUID, ActivatedAbility> useableAbilities = getUseableActivatedAbilities(permanent, Zone.BATTLEFIELD, game);
|
Player player = game.getPlayer(playerInRangeId);
|
||||||
for (ActivatedAbility ability : useableAbilities.values()) {
|
if (player != null) {
|
||||||
playableActivated.putIfAbsent(ability.toString(), ability);
|
if (/*player.isTopCardRevealed() &&*/player.getLibrary().hasCards()) {
|
||||||
|
Card card = player.getLibrary().getFromTop(game);
|
||||||
|
if (card != null && null != game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, card.getSpellAbility(), getId(), game)) {
|
||||||
|
for (ActivatedAbility ability : card.getAbilities().getActivatedAbilities(Zone.HAND)) {
|
||||||
|
if (ability instanceof SpellAbility || ability instanceof PlayLandAbility) {
|
||||||
|
playable.add(ability);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// eliminate duplicate activated abilities (uses for AI plays)
|
||||||
|
Map<String, Ability> activatedUnique = new HashMap<>();
|
||||||
|
List<Ability> activatedAll = new ArrayList<>();
|
||||||
|
|
||||||
|
// activated abilities from battlefield objects
|
||||||
|
if (fromAll || fromZone == Zone.BATTLEFIELD) {
|
||||||
|
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(playerId)) {
|
||||||
|
LinkedHashMap<UUID, ActivatedAbility> useableAbilities = getUseableActivatedAbilities(permanent, Zone.BATTLEFIELD, game);
|
||||||
|
for (ActivatedAbility ability : useableAbilities.values()) {
|
||||||
|
activatedUnique.putIfAbsent(ability.toString(), ability);
|
||||||
|
activatedAll.add(ability);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// activated abilities from stack objects
|
// activated abilities from stack objects
|
||||||
for (StackObject stackObject : game.getState().getStack()) {
|
if (fromAll || fromZone == Zone.STACK) {
|
||||||
for (ActivatedAbility ability : stackObject.getAbilities().getActivatedAbilities(Zone.STACK)) {
|
for (StackObject stackObject : game.getState().getStack()) {
|
||||||
if (ability != null && canPlay(ability, availableMana, game.getObject(ability.getSourceId()), game)) {
|
for (ActivatedAbility ability : stackObject.getAbilities().getActivatedAbilities(Zone.STACK)) {
|
||||||
playableActivated.put(ability.toString(), ability);
|
if (ability != null && canPlay(ability, availableMana, game.getObject(ability.getSourceId()), game)) {
|
||||||
|
activatedUnique.put(ability.toString(), ability);
|
||||||
|
activatedAll.add(ability);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// activated abilities from objects in the command zone (emblems or commanders)
|
// activated abilities from objects in the command zone (emblems or commanders)
|
||||||
for (CommandObject commandObject : game.getState().getCommand()) {
|
if (fromAll || fromZone == Zone.COMMAND) {
|
||||||
for (ActivatedAbility ability : commandObject.getAbilities().getActivatedAbilities(Zone.COMMAND)) {
|
for (CommandObject commandObject : game.getState().getCommand()) {
|
||||||
if (ability.isControlledBy(getId()) && canPlay(ability, availableMana, game.getObject(ability.getSourceId()), game)) {
|
for (ActivatedAbility ability : commandObject.getAbilities().getActivatedAbilities(Zone.COMMAND)) {
|
||||||
playableActivated.put(ability.toString(), ability);
|
if (ability.isControlledBy(getId()) && canPlay(ability, availableMana, game.getObject(ability.getSourceId()), game)) {
|
||||||
|
activatedUnique.put(ability.toString(), ability);
|
||||||
|
activatedAll.add(ability);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
playable.addAll(playableActivated.values());
|
if (hideDuplicatedAbilities) {
|
||||||
|
playable.addAll(activatedUnique.values());
|
||||||
|
} else {
|
||||||
|
playable.addAll(activatedAll);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return playable;
|
return playable;
|
||||||
|
@ -3195,50 +3223,16 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
* @return A Set of cardIds that are playable
|
* @return A Set of cardIds that are playable
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Set<UUID> getPlayableInHand(Game game
|
public Set<UUID> getPlayableObjects(Game game, Zone zone) {
|
||||||
) {
|
|
||||||
Set<UUID> playable = new HashSet<>();
|
|
||||||
if (!shouldSkipGettingPlayable(game)) {
|
|
||||||
ManaOptions available = getManaAvailable(game);
|
|
||||||
available.addMana(manaPool.getMana());
|
|
||||||
|
|
||||||
for (Card card : hand.getCards(game)) {
|
List<Ability> playableAbilities = getPlayable(game, true, zone, false); // do not hide duplicated abilities
|
||||||
Abilities:
|
Set<UUID> playableObjects = new HashSet<>();
|
||||||
for (Ability ability : card.getAbilities()) {
|
for (Ability ability : playableAbilities) {
|
||||||
if (ability.getZone().match(Zone.HAND)) {
|
if (ability.getSourceId() != null) {
|
||||||
switch (ability.getAbilityType()) {
|
playableObjects.add(ability.getSourceId());
|
||||||
case PLAY_LAND:
|
|
||||||
if (game.getContinuousEffects().preventedByRuleModification(GameEvent.getEvent(GameEvent.EventType.PLAY_LAND, ability.getSourceId(), ability.getSourceId(), playerId), ability, game, true)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (canPlay((ActivatedAbility) ability, available, card, game)) {
|
|
||||||
playable.add(card.getId());
|
|
||||||
break Abilities;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ACTIVATED:
|
|
||||||
case SPELL:
|
|
||||||
if (canPlay((ActivatedAbility) ability, available, card, game)) {
|
|
||||||
playable.add(card.getId());
|
|
||||||
break Abilities;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case STATIC:
|
|
||||||
if (card.isLand() && ability instanceof AlternativeSourceCosts) {
|
|
||||||
if (canLandPlayAlternateSourceCostsAbility(card, available, ability, game)) { // e.g. Land with Morph
|
|
||||||
if (game.canPlaySorcery(getId())) {
|
|
||||||
playable.add(card.getId());
|
|
||||||
}
|
|
||||||
break Abilities;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return playableObjects;
|
||||||
return playable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue