mirror of
https://github.com/magefree/mage.git
synced 2026-01-26 21:29:17 -08:00
Merge origin/master
This commit is contained in:
commit
7ca60078a0
36 changed files with 740 additions and 489 deletions
|
|
@ -34,50 +34,12 @@
|
|||
|
||||
package mage.client.cards;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.ComponentListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.awt.event.MouseMotionListener;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.Popup;
|
||||
import javax.swing.PopupFactory;
|
||||
import javax.swing.text.BadLocationException;
|
||||
import javax.swing.text.Style;
|
||||
import javax.swing.text.StyleConstants;
|
||||
import javax.swing.text.StyleContext;
|
||||
import javax.swing.text.StyledDocument;
|
||||
import mage.cards.CardDimensions;
|
||||
import mage.cards.MagePermanent;
|
||||
import mage.cards.Sets;
|
||||
import mage.cards.TextPopup;
|
||||
import mage.cards.action.ActionCallback;
|
||||
import mage.client.MageFrame;
|
||||
import static mage.client.constants.Constants.CONTENT_MAX_XOFFSET;
|
||||
import static mage.client.constants.Constants.FRAME_MAX_HEIGHT;
|
||||
import static mage.client.constants.Constants.FRAME_MAX_WIDTH;
|
||||
import static mage.client.constants.Constants.NAME_FONT_MAX_SIZE;
|
||||
import static mage.client.constants.Constants.NAME_MAX_YOFFSET;
|
||||
import static mage.client.constants.Constants.POWBOX_TEXT_MAX_LEFT;
|
||||
import static mage.client.constants.Constants.POWBOX_TEXT_MAX_TOP;
|
||||
import static mage.client.constants.Constants.SYMBOL_MAX_XOFFSET;
|
||||
import static mage.client.constants.Constants.SYMBOL_MAX_YOFFSET;
|
||||
import static mage.client.constants.Constants.TYPE_MAX_YOFFSET;
|
||||
import mage.client.game.PlayAreaPanel;
|
||||
import mage.client.util.Config;
|
||||
import mage.client.util.DefaultActionCallback;
|
||||
|
|
@ -86,11 +48,18 @@ import mage.client.util.gui.ArrowBuilder;
|
|||
import mage.constants.CardType;
|
||||
import mage.constants.EnlargeMode;
|
||||
import mage.remote.Session;
|
||||
import mage.view.AbilityView;
|
||||
import mage.view.CardView;
|
||||
import mage.view.CounterView;
|
||||
import mage.view.PermanentView;
|
||||
import mage.view.StackAbilityView;
|
||||
import mage.view.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.text.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static mage.client.constants.Constants.*;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -557,4 +526,8 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis
|
|||
@Override
|
||||
public void setSelected(boolean selected) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCardAreaRef(JPanel cardArea) {
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,14 +39,14 @@ import mage.client.plugins.impl.Plugins;
|
|||
import mage.client.util.CardsViewUtil;
|
||||
import mage.client.util.Config;
|
||||
import mage.view.*;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.mage.card.arcane.CardPanel;
|
||||
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import mage.cards.action.ActionCallback;
|
||||
import mage.client.plugins.adapters.MageActionCallback;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -61,6 +61,8 @@ public class Cards extends javax.swing.JPanel {
|
|||
private static final int GAP_X = 5;
|
||||
private String zone;
|
||||
|
||||
private static final Border emptyBorder = new EmptyBorder(0,0,0,0);
|
||||
|
||||
/**
|
||||
* Defines whether component should be visible whenever there is no objects within.
|
||||
* True by default.
|
||||
|
|
@ -82,18 +84,15 @@ public class Cards extends javax.swing.JPanel {
|
|||
if (!skipAddingScrollPane) {
|
||||
jScrollPane1.setOpaque(false);
|
||||
jScrollPane1.getViewport().setOpaque(false);
|
||||
jScrollPane1.setBorder(emptyBorder);
|
||||
}
|
||||
if (Plugins.getInstance().isCardPluginLoaded()) {
|
||||
cardArea.setLayout(null);
|
||||
}
|
||||
cardArea.setBorder(emptyBorder);
|
||||
}
|
||||
|
||||
public void cleanUp() {
|
||||
// ActionCallback actionCallback = Plugins.getInstance().getActionCallback();
|
||||
// if (actionCallback instanceof MageActionCallback) {
|
||||
// ((MageActionCallback) actionCallback).setCardPreviewComponent(null);
|
||||
// }
|
||||
}
|
||||
public void cleanUp() {}
|
||||
|
||||
/**
|
||||
* Sets components background color
|
||||
|
|
@ -182,12 +181,13 @@ public class Cards extends javax.swing.JPanel {
|
|||
}
|
||||
|
||||
if (changed) {
|
||||
layoutCards(getCardDimension(), cards, order);
|
||||
layoutCards();
|
||||
}
|
||||
|
||||
if (!isVisibleIfEmpty) {
|
||||
cardArea.setVisible(cards.size() > 0);
|
||||
}
|
||||
|
||||
sizeCards(getCardDimension());
|
||||
this.revalidate();
|
||||
this.repaint();
|
||||
|
|
@ -196,13 +196,13 @@ public class Cards extends javax.swing.JPanel {
|
|||
}
|
||||
|
||||
public void sizeCards(Dimension cardDimension) {
|
||||
cardArea.setPreferredSize(new Dimension((int)(cards.size() * (cardDimension.getWidth() + GAP_X)) + 5, (int)(cardDimension.getHeight()) + 20));
|
||||
cardArea.setPreferredSize(new Dimension((int)((cards.size()) * (cardDimension.getWidth() + GAP_X)) + 20, (int)(cardDimension.getHeight()) + 20));
|
||||
cardArea.revalidate();
|
||||
cardArea.repaint();
|
||||
}
|
||||
|
||||
private Dimension getCardDimension() {
|
||||
if (cardDimension == null) {
|
||||
if (cardDimension == null) {
|
||||
cardDimension = new Dimension(Config.dimensions.frameWidth, Config.dimensions.frameHeight);
|
||||
}
|
||||
return cardDimension;
|
||||
|
|
@ -215,6 +215,19 @@ public class Cards extends javax.swing.JPanel {
|
|||
}
|
||||
cards.put(card.getId(), cardImg);
|
||||
cardArea.add(cardImg);
|
||||
definePosition(cardImg);
|
||||
cardImg.setCardAreaRef(cardArea);
|
||||
}
|
||||
|
||||
private void definePosition(MageCard card) {
|
||||
int dx = 0;
|
||||
for (Component comp: cardArea.getComponents()) {
|
||||
if (!comp.equals(card)) {
|
||||
dx = Math.max(dx, (int)comp.getLocation().getX());
|
||||
}
|
||||
}
|
||||
dx += ((CardPanel)card).getCardWidth() + GAP_X;
|
||||
card.setLocation(dx, (int)card.getLocation().getY());
|
||||
}
|
||||
|
||||
private void removeCard(UUID cardId) {
|
||||
|
|
@ -232,35 +245,7 @@ public class Cards extends javax.swing.JPanel {
|
|||
}
|
||||
|
||||
private int countCards() {
|
||||
int count = 0;
|
||||
for (Component comp: cardArea.getComponents()) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private void layoutCards(Dimension dimension, Map<UUID, MageCard> cards, java.util.List<UUID> order) {
|
||||
if (Plugins.getInstance().isCardPluginLoaded()) {
|
||||
int dx = GAP_X;
|
||||
if (order != null) {
|
||||
for (UUID cardId : order) {
|
||||
MageCard card = cards.get(cardId);
|
||||
if (card != null) {
|
||||
card.setLocation(dx, 0);
|
||||
card.setCardBounds(dx, 0, dimension.width, dimension.height);
|
||||
dx += dimension.width + GAP_X;
|
||||
} else {
|
||||
System.err.println("[ERROR] Cards.java: couldn't find a card from ordered list!");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (MageCard card: cards.values()) {
|
||||
card.setLocation(dx, 0);
|
||||
card.setCardBounds(dx, 0, dimension.width, dimension.height);
|
||||
dx += dimension.width + GAP_X;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cardArea.getComponentCount();
|
||||
}
|
||||
|
||||
/** This method is called from within the constructor to
|
||||
|
|
@ -311,7 +296,29 @@ public class Cards extends javax.swing.JPanel {
|
|||
|
||||
public void setCardDimension(Dimension dimension) {
|
||||
this.cardDimension = dimension;
|
||||
layoutCards(cardDimension, cards, null);
|
||||
layoutCards();
|
||||
}
|
||||
|
||||
private void layoutCards() {
|
||||
java.util.List<CardPanel> cards = new ArrayList();
|
||||
|
||||
for (Component component : cardArea.getComponents()) {
|
||||
if (component instanceof CardPanel) {
|
||||
cards.add((CardPanel)component);
|
||||
}
|
||||
}
|
||||
Collections.sort(cards, new Comparator<CardPanel>() {
|
||||
@Override
|
||||
public int compare(CardPanel cp1, CardPanel cp2) {
|
||||
return Integer.valueOf(cp1.getLocation().x).compareTo(cp2.getLocation().x);
|
||||
}
|
||||
});
|
||||
|
||||
int dx = 0;
|
||||
for (Component component : cards) {
|
||||
component.setLocation(dx, component.getLocation().y);
|
||||
dx += ((CardPanel) component).getCardWidth() + GAP_X;
|
||||
}
|
||||
}
|
||||
|
||||
public void setZone(String zone) {
|
||||
|
|
|
|||
|
|
@ -27,47 +27,6 @@
|
|||
*/
|
||||
package mage.client.game;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.ComponentListener;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.GroupLayout;
|
||||
import javax.swing.GroupLayout.Alignment;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLayeredPane;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.SwingWorker;
|
||||
import javax.swing.border.LineBorder;
|
||||
import javax.swing.plaf.basic.BasicSplitPaneDivider;
|
||||
import javax.swing.plaf.basic.BasicSplitPaneUI;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.action.ActionCallback;
|
||||
import mage.client.MageFrame;
|
||||
|
|
@ -78,12 +37,7 @@ import mage.client.components.HoverButton;
|
|||
import mage.client.components.MageComponents;
|
||||
import mage.client.components.ext.dlg.DialogManager;
|
||||
import mage.client.components.layout.RelativeLayout;
|
||||
import mage.client.dialog.ExileZoneDialog;
|
||||
import mage.client.dialog.PickChoiceDialog;
|
||||
import mage.client.dialog.PickNumberDialog;
|
||||
import mage.client.dialog.PickPileDialog;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.client.dialog.ShowCardsDialog;
|
||||
import mage.client.dialog.*;
|
||||
import mage.client.game.FeedbackPanel.FeedbackMode;
|
||||
import mage.client.plugins.adapters.MageActionCallback;
|
||||
import mage.client.plugins.impl.Plugins;
|
||||
|
|
@ -94,29 +48,23 @@ import mage.client.util.PhaseManager;
|
|||
import mage.client.util.gui.ArrowBuilder;
|
||||
import mage.constants.EnlargeMode;
|
||||
import mage.constants.PhaseStep;
|
||||
import static mage.constants.PhaseStep.BEGIN_COMBAT;
|
||||
import static mage.constants.PhaseStep.COMBAT_DAMAGE;
|
||||
import static mage.constants.PhaseStep.DECLARE_ATTACKERS;
|
||||
import static mage.constants.PhaseStep.DECLARE_BLOCKERS;
|
||||
import static mage.constants.PhaseStep.DRAW;
|
||||
import static mage.constants.PhaseStep.END_COMBAT;
|
||||
import static mage.constants.PhaseStep.END_TURN;
|
||||
import static mage.constants.PhaseStep.FIRST_COMBAT_DAMAGE;
|
||||
import static mage.constants.PhaseStep.UNTAP;
|
||||
import static mage.constants.PhaseStep.UPKEEP;
|
||||
import mage.remote.Session;
|
||||
import mage.view.AbilityPickerView;
|
||||
import mage.view.CardsView;
|
||||
import mage.view.ExileView;
|
||||
import mage.view.GameView;
|
||||
import mage.view.LookedAtView;
|
||||
import mage.view.MatchView;
|
||||
import mage.view.PlayerView;
|
||||
import mage.view.RevealedView;
|
||||
import mage.view.SimpleCardsView;
|
||||
import mage.view.*;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.mage.plugins.card.utils.impl.ImageManagerImpl;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.GroupLayout.Alignment;
|
||||
import javax.swing.border.LineBorder;
|
||||
import javax.swing.plaf.basic.BasicSplitPaneDivider;
|
||||
import javax.swing.plaf.basic.BasicSplitPaneUI;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com, nantuko8
|
||||
|
|
@ -503,6 +451,15 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
handCards.clear();
|
||||
handCards.put(YOUR_HAND, CardsViewUtil.convertSimple(game.getHand(), loadedCards));
|
||||
|
||||
// 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
|
||||
if (game.getOpponentHands() != null) {
|
||||
for (Map.Entry<String, SimpleCardsView> hand: game.getOpponentHands().entrySet()) {
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ import mage.client.cards.BigCard;
|
|||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.client.util.Config;
|
||||
import mage.constants.Zone;
|
||||
import mage.view.CardsView;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import java.awt.*;
|
||||
import java.util.UUID;
|
||||
import mage.view.CardsView;
|
||||
|
||||
public class HandPanel extends JPanel {
|
||||
|
||||
|
|
@ -31,12 +31,13 @@ public class HandPanel extends JPanel {
|
|||
public void initComponents() {
|
||||
hand = new mage.client.cards.Cards(true);
|
||||
hand.setCardDimension(getHandCardDimension());
|
||||
|
||||
jPanel = new JPanel();
|
||||
jScrollPane1 = new JScrollPane(jPanel);
|
||||
jScrollPane1.getViewport().setBackground(new Color(0,0,0,0));
|
||||
|
||||
jPanel.setLayout(new GridBagLayout()); // centers hand
|
||||
jPanel.setBackground(new Color(0,0,0,0));
|
||||
jPanel.setBackground(new Color(0, 0, 0, 0));
|
||||
jPanel.add(hand);
|
||||
|
||||
setOpaque(false);
|
||||
|
|
@ -47,12 +48,13 @@ public class HandPanel extends JPanel {
|
|||
jScrollPane1.setBorder(emptyBorder);
|
||||
jScrollPane1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
|
||||
jScrollPane1.getHorizontalScrollBar().setUnitIncrement(8);
|
||||
jScrollPane1.setViewportBorder(emptyBorder);
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
add(jScrollPane1, BorderLayout.CENTER);
|
||||
|
||||
hand.setHScrollSpeed(8);
|
||||
hand.setBackgroundColor(new Color(0, 0, 0, 100));
|
||||
hand.setBackgroundColor(new Color(0, 0, 0, 0));
|
||||
hand.setVisibleIfEmpty(false);
|
||||
hand.setBorder(emptyBorder);
|
||||
hand.setZone(Zone.HAND.toString());
|
||||
|
|
@ -87,7 +89,7 @@ public class HandPanel extends JPanel {
|
|||
|
||||
private JPanel jPanel;
|
||||
private JScrollPane jScrollPane1;
|
||||
private Border emptyBorder = new EmptyBorder(0,0,0,0);
|
||||
private static final Border emptyBorder = new EmptyBorder(0,0,0,0);
|
||||
private mage.client.cards.Cards hand;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,17 @@
|
|||
package mage.client.plugins.adapters;
|
||||
|
||||
import mage.cards.MageCard;
|
||||
import mage.cards.MagePermanent;
|
||||
import mage.cards.action.ActionCallback;
|
||||
import mage.cards.action.TransferData;
|
||||
import mage.client.MageFrame;
|
||||
import mage.client.cards.BigCard;
|
||||
import mage.client.components.MageComponents;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.client.game.PlayAreaPanel;
|
||||
import mage.client.game.PlayerPanelExt;
|
||||
import mage.client.plugins.impl.Plugins;
|
||||
import mage.client.util.DefaultActionCallback;
|
||||
import mage.client.util.ImageHelper;
|
||||
import mage.client.util.gui.ArrowBuilder;
|
||||
import mage.client.util.gui.ArrowUtil;
|
||||
import mage.client.util.gui.GuiDisplayUtil;
|
||||
import mage.components.CardInfoPane;
|
||||
import mage.constants.EnlargeMode;
|
||||
|
|
@ -21,10 +19,9 @@ import mage.remote.Session;
|
|||
import mage.utils.ThreadUtils;
|
||||
import mage.view.CardView;
|
||||
import mage.view.PermanentView;
|
||||
import mage.view.PlayerView;
|
||||
import mage.view.SimpleCardsView;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jdesktop.swingx.JXPanel;
|
||||
import org.mage.card.arcane.CardPanel;
|
||||
import org.mage.plugins.card.images.ImageCache;
|
||||
|
||||
import javax.swing.*;
|
||||
|
|
@ -32,8 +29,8 @@ import java.awt.*;
|
|||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
|
@ -43,11 +40,15 @@ import java.util.concurrent.TimeUnit;
|
|||
* Class that handles the callbacks from the card panels to mage to display big card
|
||||
* images from the cards the mouse hovers on. Also handles tooltip text window.
|
||||
*
|
||||
* @author Nantuko
|
||||
* @author Nantuko, noxx
|
||||
*/
|
||||
public class MageActionCallback implements ActionCallback {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ActionCallback.class);
|
||||
public static final int GAP_X = 5;
|
||||
public static final double COMPARE_GAP_X = 30;
|
||||
public static final int GO_DOWN_ON_DRAG_Y_OFFSET = 0;
|
||||
public static final int MIN_X_OFFSET_REQUIRED = 25;
|
||||
|
||||
private Popup popup;
|
||||
private JPopupMenu jPopupMenu;
|
||||
|
|
@ -69,6 +70,12 @@ public class MageActionCallback implements ActionCallback {
|
|||
private static final ScheduledExecutorService timeoutExecutor = Executors.newScheduledThreadPool(1);
|
||||
private ScheduledFuture<?> hideTimeout;
|
||||
|
||||
private CardView currentCard;
|
||||
private boolean isDragging;
|
||||
private Point initialCardPos;
|
||||
private Point initialMousePos;
|
||||
private Set<CardPanel> cardPanels = new HashSet<CardPanel>();
|
||||
|
||||
public MageActionCallback() {
|
||||
enlargeMode = EnlargeMode.NORMAL;
|
||||
}
|
||||
|
|
@ -90,21 +97,6 @@ public class MageActionCallback implements ActionCallback {
|
|||
public void mouseClicked(MouseEvent e, TransferData data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e, TransferData data) {
|
||||
data.component.requestFocusInWindow();
|
||||
// Closes popup & enlarged view if a card/Permanent is selected
|
||||
hidePopup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e, TransferData data) {
|
||||
data.component.requestFocusInWindow();
|
||||
defaultCallback.mouseClicked(e, data.gameId, session, data.card);
|
||||
// Closes popup & enlarged view if a card/Permanent is selected
|
||||
hidePopup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e, final TransferData data) {
|
||||
hidePopup();
|
||||
|
|
@ -116,109 +108,18 @@ public class MageActionCallback implements ActionCallback {
|
|||
Component parentComponent = SwingUtilities.getRoot(data.component);
|
||||
Point parentPoint = parentComponent.getLocationOnScreen();
|
||||
|
||||
drawArrowsForTargets(data, parentPoint);
|
||||
drawArrowsForSource(data, parentPoint);
|
||||
drawArrowsForPairedCards(data, parentPoint);
|
||||
drawArrowsForEnchantPlayers(data, parentPoint);
|
||||
if (data.locationOnScreen == null) {
|
||||
data.locationOnScreen = data.component.getLocationOnScreen();
|
||||
}
|
||||
|
||||
ArrowUtil.drawArrowsForTargets(data, parentPoint);
|
||||
ArrowUtil.drawArrowsForSource(data, parentPoint);
|
||||
ArrowUtil.drawArrowsForPairedCards(data, parentPoint);
|
||||
ArrowUtil.drawArrowsForEnchantPlayers(data, parentPoint);
|
||||
|
||||
showPopup(data, parentComponent, parentPoint);
|
||||
}
|
||||
|
||||
private void drawArrowsForPairedCards(TransferData data, Point parentPoint) {
|
||||
if (data.card.getPairedCard() != null) {
|
||||
Point me = new Point(data.locationOnScreen);
|
||||
me.translate(-parentPoint.x, -parentPoint.y);
|
||||
UUID uuid = data.card.getPairedCard();
|
||||
for (PlayAreaPanel pa : MageFrame.getGame(data.gameId).getPlayers().values()) {
|
||||
MagePermanent permanent = pa.getBattlefieldPanel().getPermanents().get(uuid);
|
||||
if (permanent != null) {
|
||||
Point target = permanent.getLocationOnScreen();
|
||||
target.translate(-parentPoint.x, -parentPoint.y);
|
||||
ArrowBuilder.getBuilder().addArrow(data.gameId, (int) me.getX() + 35, (int) me.getY(), (int) target.getX() + 40, (int) target.getY() + 10, Color.green, ArrowBuilder.Type.PAIRED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawArrowsForEnchantPlayers(TransferData data, Point parentPoint) {
|
||||
if (data.gameId != null && MageFrame.getGame(data.gameId) != null) {
|
||||
for (PlayAreaPanel pa : MageFrame.getGame(data.gameId).getPlayers().values()) {
|
||||
PlayerPanelExt playAreaPanel = pa.getPlayerPanel();
|
||||
if (playAreaPanel != null && playAreaPanel.getPlayer() != null && playAreaPanel.getPlayer().hasAttachments()) {
|
||||
Point me = new Point(data.locationOnScreen);
|
||||
me.translate(-parentPoint.x, -parentPoint.y);
|
||||
for (UUID attachmentId : playAreaPanel.getPlayer().getAttachments()) {
|
||||
if (attachmentId.equals(data.card.getId())) {
|
||||
Point player = pa.getLocationOnScreen();
|
||||
player.translate(-parentPoint.x, -parentPoint.y);
|
||||
ArrowBuilder.getBuilder().addArrow(data.gameId,(int) me.getX() + 35, (int) me.getY(), (int) player.getX() + 40, (int) player.getY() - 40, Color.magenta, ArrowBuilder.Type.ENCHANT_PLAYERS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawArrowsForSource(TransferData data, Point parentPoint) {
|
||||
if (data.card.isAbility()) {
|
||||
Point me = new Point(data.locationOnScreen);
|
||||
me.translate(-parentPoint.x, -parentPoint.y);
|
||||
UUID uuid = data.card.getParentId();
|
||||
for (PlayAreaPanel pa : MageFrame.getGame(data.gameId).getPlayers().values()) {
|
||||
MagePermanent permanent = pa.getBattlefieldPanel().getPermanents().get(uuid);
|
||||
if (permanent != null) {
|
||||
Point source = permanent.getLocationOnScreen();
|
||||
source.translate(-parentPoint.x, -parentPoint.y);
|
||||
ArrowBuilder.getBuilder().addArrow(data.gameId, (int) source.getX() + 40, (int) source.getY() + 10, (int) me.getX() + 35, (int) me.getY() + 20, Color.blue, ArrowBuilder.Type.SOURCE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawArrowsForTargets(TransferData data, Point parentPoint) {
|
||||
List<UUID> targets = data.card.getTargets();
|
||||
if (targets == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Point me = new Point(data.locationOnScreen);
|
||||
me.translate(-parentPoint.x, -parentPoint.y);
|
||||
for (UUID uuid : targets) {
|
||||
|
||||
PlayAreaPanel p = MageFrame.getGame(data.gameId).getPlayers().get(uuid);
|
||||
if (p != null) {
|
||||
Point target = p.getLocationOnScreen();
|
||||
target.translate(-parentPoint.x, -parentPoint.y);
|
||||
ArrowBuilder.getBuilder().addArrow(data.gameId, (int) me.getX() + 35, (int) me.getY(), (int) target.getX() + 40, (int) target.getY() - 40, Color.red, ArrowBuilder.Type.TARGET);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (PlayAreaPanel panel : MageFrame.getGame(data.gameId).getPlayers().values()) {
|
||||
MagePermanent permanent = panel.getBattlefieldPanel().getPermanents().get(uuid);
|
||||
if (permanent != null) {
|
||||
Point target = permanent.getLocationOnScreen();
|
||||
target.translate(-parentPoint.x, -parentPoint.y);
|
||||
ArrowBuilder.getBuilder().addArrow(data.gameId, (int) me.getX() + 35, (int) me.getY(), (int) target.getX() + 40, (int) target.getY() + 10, Color.red, ArrowBuilder.Type.TARGET);
|
||||
continue;
|
||||
}
|
||||
|
||||
PlayerView view = panel.getPlayerPanel().getPlayer();
|
||||
if (view != null) {
|
||||
SimpleCardsView graveyard = view.getGraveyard();
|
||||
if (graveyard.containsKey(uuid)) {
|
||||
p = MageFrame.getGame(data.gameId).getPlayers().get(view.getPlayerId());
|
||||
if (p != null) {
|
||||
Point target = p.getLocationOnScreen();
|
||||
target.translate(-parentPoint.x, -parentPoint.y);
|
||||
int yOffset = p.isSmallMode() ? (PlayAreaPanel.PANEL_HEIGHT - PlayAreaPanel.PANEL_HEIGHT_SMALL) : 0;
|
||||
ArrowBuilder.getBuilder().addArrow(data.gameId, (int) me.getX() + 35, (int) me.getY(), (int) target.getX() + 15, (int) target.getY() + 145 - yOffset, Color.red, ArrowBuilder.Type.TARGET);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showPopup(final TransferData data, final Component parentComponent, final Point parentPoint) {
|
||||
if (data.component != null) {
|
||||
String showTooltips = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SHOW_TOOLTIPS_ANY_ZONE, "true");
|
||||
|
|
@ -229,6 +130,12 @@ public class MageActionCallback implements ActionCallback {
|
|||
|
||||
if (cardInfoPane == null) {
|
||||
PopupFactory factory = PopupFactory.getSharedInstance();
|
||||
if (data.locationOnScreen == null) {
|
||||
if (data.component == null) {
|
||||
return;
|
||||
}
|
||||
data.locationOnScreen = data.component.getLocationOnScreen();
|
||||
}
|
||||
popup = factory.getPopup(data.component, data.popupText, (int) data.locationOnScreen.getX() + data.popupOffsetX, (int) data.locationOnScreen.getY() + data.popupOffsetY + 40);
|
||||
popup.show();
|
||||
// hack to get popup to resize to fit text
|
||||
|
|
@ -256,6 +163,10 @@ public class MageActionCallback implements ActionCallback {
|
|||
|
||||
((CardInfoPane) popup2).setCard(data.card, popupContainer);
|
||||
|
||||
if (data.locationOnScreen == null) {
|
||||
data.locationOnScreen = data.component.getLocationOnScreen();
|
||||
}
|
||||
|
||||
Point location = new Point((int) data.locationOnScreen.getX() + data.popupOffsetX - 40, (int) data.locationOnScreen.getY() + data.popupOffsetY - 40);
|
||||
location = GuiDisplayUtil.keepComponentInsideParent(location, parentPoint, popup2, parentComponent);
|
||||
location.translate(-parentPoint.x, -parentPoint.y);
|
||||
|
|
@ -265,15 +176,15 @@ public class MageActionCallback implements ActionCallback {
|
|||
|
||||
final Component c = MageFrame.getUI().getComponent(MageComponents.DESKTOP_PANE);
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!popupTextWindowOpen || !enlargedWindowState.equals(EnlargedWindowState.CLOSED)) {
|
||||
return;
|
||||
}
|
||||
popupContainer.setVisible(true);
|
||||
c.repaint();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
if (!popupTextWindowOpen || !enlargedWindowState.equals(EnlargedWindowState.CLOSED)) {
|
||||
return;
|
||||
}
|
||||
popupContainer.setVisible(true);
|
||||
c.repaint();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
|
|
@ -283,8 +194,127 @@ public class MageActionCallback implements ActionCallback {
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e, TransferData data) {
|
||||
data.component.requestFocusInWindow();
|
||||
currentCard = data.card;
|
||||
isDragging = false;
|
||||
cardPanels.clear();
|
||||
Point mouse = new Point(e.getX(), e.getY());
|
||||
SwingUtilities.convertPointToScreen(mouse, data.component);
|
||||
initialMousePos = new Point((int)mouse.getX(), (int)mouse.getY());
|
||||
initialCardPos = data.component.getLocation();
|
||||
// Closes popup & enlarged view if a card/Permanent is selected
|
||||
hidePopup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e, TransferData transferData) {
|
||||
int maxXOffset = 0;
|
||||
if (isDragging) {
|
||||
CardPanel card = ((CardPanel)transferData.component);
|
||||
Point mouse = new Point(e.getX(), e.getY());
|
||||
SwingUtilities.convertPointToScreen(mouse, transferData.component);
|
||||
int xOffset = card.getXOffset(card.getCardWidth());
|
||||
maxXOffset = Math.abs((int) (mouse.getX() - initialMousePos.x) - xOffset);
|
||||
|
||||
}
|
||||
if (maxXOffset > MIN_X_OFFSET_REQUIRED) { // we need this for protection from small card movements
|
||||
CardPanel card = ((CardPanel)transferData.component);
|
||||
for (Component component : card.getCardArea().getComponents()) {
|
||||
if (component instanceof CardPanel) {
|
||||
if (cardPanels.contains(component)) {
|
||||
component.setLocation(component.getLocation().x, component.getLocation().y - GO_DOWN_ON_DRAG_Y_OFFSET);
|
||||
}
|
||||
}
|
||||
}
|
||||
sort(card, card.getCardArea(), true);
|
||||
cardPanels.clear();
|
||||
} else {
|
||||
transferData.component.requestFocusInWindow();
|
||||
defaultCallback.mouseClicked(e, transferData.gameId, session, transferData.card);
|
||||
// Closes popup & enlarged view if a card/Permanent is selected
|
||||
hidePopup();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e, TransferData transferData) {
|
||||
handlePopup(transferData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e, TransferData transferData) {
|
||||
CardPanel card = ((CardPanel)transferData.component);
|
||||
if (card.getZone() == null || !card.getZone().equalsIgnoreCase("hand")) {
|
||||
// drag'n'drop is allowed for HAND zone only
|
||||
return;
|
||||
}
|
||||
currentCard = null;
|
||||
isDragging = true;
|
||||
Point p = card.getCardLocation();
|
||||
Point mouse = new Point(e.getX(), e.getY());
|
||||
SwingUtilities.convertPointToScreen(mouse, transferData.component);
|
||||
int xOffset = card.getXOffset(card.getCardWidth());
|
||||
int newX = Math.max(initialCardPos.x + (int)(mouse.getX() - initialMousePos.x) - xOffset, 0);
|
||||
card.setCardBounds(
|
||||
newX,
|
||||
p.y,
|
||||
card.getCardWidth(),
|
||||
card.getCardHeight());
|
||||
card.getCardArea().setComponentZOrder(card, 0);
|
||||
sort(card, card.getCardArea(), false);
|
||||
}
|
||||
|
||||
private void sort(CardPanel card, JPanel container, boolean sortSource) {
|
||||
java.util.List<CardPanel> cards = new ArrayList<CardPanel>();
|
||||
for (Component component : container.getComponents()) {
|
||||
if (component instanceof CardPanel) {
|
||||
if (!component.equals(card)) {
|
||||
if (!cardPanels.contains(component)) {
|
||||
component.setLocation(component.getLocation().x, component.getLocation().y + GO_DOWN_ON_DRAG_Y_OFFSET);
|
||||
}
|
||||
cardPanels.add((CardPanel)component);
|
||||
}
|
||||
cards.add((CardPanel)component);
|
||||
}
|
||||
}
|
||||
sortLayout(cards, card, sortSource);
|
||||
}
|
||||
|
||||
private void sortLayout(List<CardPanel> cards, CardPanel source, boolean includeSource) {
|
||||
source.getLocation().x -= COMPARE_GAP_X; // this creates nice effect
|
||||
|
||||
Collections.sort(cards, new Comparator<CardPanel>() {
|
||||
@Override
|
||||
public int compare(CardPanel cp1, CardPanel cp2) {
|
||||
return Integer.valueOf(cp1.getLocation().x).compareTo(cp2.getLocation().x);
|
||||
}
|
||||
});
|
||||
|
||||
int dx = 0;
|
||||
boolean createdGapForSource = false;
|
||||
for (Component component : cards) {
|
||||
if (!includeSource) {
|
||||
if (!component.equals(source)) {
|
||||
component.setLocation(dx, component.getLocation().y);
|
||||
dx += ((CardPanel) component).getCardWidth() + GAP_X;
|
||||
// once dx is bigger than source's x position
|
||||
// we need to create a gap for the source card
|
||||
// but only once
|
||||
if (!createdGapForSource && (dx + COMPARE_GAP_X) > source.getLocation().x) {
|
||||
createdGapForSource = true;
|
||||
dx += ((CardPanel) component).getCardWidth() + GAP_X;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
component.setLocation(dx, component.getLocation().y);
|
||||
dx += ((CardPanel) component).getCardWidth() + GAP_X;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handlePopup(TransferData transferData) {
|
||||
if (!Plugins.getInstance().isCardPluginLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -469,6 +499,7 @@ public class MageActionCallback implements ActionCallback {
|
|||
final Component popupContainer = MageFrame.getUI().getComponent(mageComponentCardPreviewContainer);
|
||||
Component cardPreviewPane = MageFrame.getUI().getComponent(mageComponentCardPreviewPane);
|
||||
if (cardPreviewPane != null) {
|
||||
transferData.locationOnScreen = transferData.component.getLocationOnScreen();
|
||||
Point location = new Point((int) transferData.locationOnScreen.getX() + transferData.popupOffsetX - 40, (int) transferData.locationOnScreen.getY() + transferData.popupOffsetY - 40);
|
||||
location = GuiDisplayUtil.keepComponentInsideParent(location, parentPoint, cardPreviewPane, parentComponent);
|
||||
location.translate(-parentPoint.x, -parentPoint.y);
|
||||
|
|
|
|||
|
|
@ -180,4 +180,5 @@ public class ArrowBuilder {
|
|||
arrowPanels.get(gameId).setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
116
Mage.Client/src/main/java/mage/client/util/gui/ArrowUtil.java
Normal file
116
Mage.Client/src/main/java/mage/client/util/gui/ArrowUtil.java
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
package mage.client.util.gui;
|
||||
|
||||
import mage.cards.MagePermanent;
|
||||
import mage.cards.action.TransferData;
|
||||
import mage.client.MageFrame;
|
||||
import mage.client.game.PlayAreaPanel;
|
||||
import mage.client.game.PlayerPanelExt;
|
||||
import mage.view.PlayerView;
|
||||
import mage.view.SimpleCardsView;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author noxx
|
||||
*/
|
||||
public class ArrowUtil {
|
||||
|
||||
private ArrowUtil() {}
|
||||
|
||||
public static void drawArrowsForPairedCards(TransferData data, Point parentPoint) {
|
||||
if (data.card.getPairedCard() != null) {
|
||||
Point me = new Point(data.locationOnScreen);
|
||||
me.translate(-parentPoint.x, -parentPoint.y);
|
||||
UUID uuid = data.card.getPairedCard();
|
||||
for (PlayAreaPanel pa : MageFrame.getGame(data.gameId).getPlayers().values()) {
|
||||
MagePermanent permanent = pa.getBattlefieldPanel().getPermanents().get(uuid);
|
||||
if (permanent != null) {
|
||||
Point target = permanent.getLocationOnScreen();
|
||||
target.translate(-parentPoint.x, -parentPoint.y);
|
||||
ArrowBuilder.getBuilder().addArrow(data.gameId, (int) me.getX() + 35, (int) me.getY(), (int) target.getX() + 40, (int) target.getY() + 10, Color.green, ArrowBuilder.Type.PAIRED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawArrowsForEnchantPlayers(TransferData data, Point parentPoint) {
|
||||
if (data.gameId != null && MageFrame.getGame(data.gameId) != null) {
|
||||
for (PlayAreaPanel pa : MageFrame.getGame(data.gameId).getPlayers().values()) {
|
||||
PlayerPanelExt playAreaPanel = pa.getPlayerPanel();
|
||||
if (playAreaPanel != null && playAreaPanel.getPlayer() != null && playAreaPanel.getPlayer().hasAttachments()) {
|
||||
Point me = new Point(data.locationOnScreen);
|
||||
me.translate(-parentPoint.x, -parentPoint.y);
|
||||
for (UUID attachmentId : playAreaPanel.getPlayer().getAttachments()) {
|
||||
if (attachmentId.equals(data.card.getId())) {
|
||||
Point player = pa.getLocationOnScreen();
|
||||
player.translate(-parentPoint.x, -parentPoint.y);
|
||||
ArrowBuilder.getBuilder().addArrow(data.gameId,(int) me.getX() + 35, (int) me.getY(), (int) player.getX() + 40, (int) player.getY() - 40, Color.magenta, ArrowBuilder.Type.ENCHANT_PLAYERS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawArrowsForSource(TransferData data, Point parentPoint) {
|
||||
if (data.card.isAbility()) {
|
||||
Point me = new Point(data.locationOnScreen);
|
||||
me.translate(-parentPoint.x, -parentPoint.y);
|
||||
UUID uuid = data.card.getParentId();
|
||||
for (PlayAreaPanel pa : MageFrame.getGame(data.gameId).getPlayers().values()) {
|
||||
MagePermanent permanent = pa.getBattlefieldPanel().getPermanents().get(uuid);
|
||||
if (permanent != null) {
|
||||
Point source = permanent.getLocationOnScreen();
|
||||
source.translate(-parentPoint.x, -parentPoint.y);
|
||||
ArrowBuilder.getBuilder().addArrow(data.gameId, (int) source.getX() + 40, (int) source.getY() + 10, (int) me.getX() + 35, (int) me.getY() + 20, Color.blue, ArrowBuilder.Type.SOURCE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawArrowsForTargets(TransferData data, Point parentPoint) {
|
||||
java.util.List<UUID> targets = data.card.getTargets();
|
||||
if (targets == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Point me = new Point(data.locationOnScreen);
|
||||
me.translate(-parentPoint.x, -parentPoint.y);
|
||||
for (UUID uuid : targets) {
|
||||
|
||||
PlayAreaPanel p = MageFrame.getGame(data.gameId).getPlayers().get(uuid);
|
||||
if (p != null) {
|
||||
Point target = p.getLocationOnScreen();
|
||||
target.translate(-parentPoint.x, -parentPoint.y);
|
||||
ArrowBuilder.getBuilder().addArrow(data.gameId, (int) me.getX() + 35, (int) me.getY(), (int) target.getX() + 40, (int) target.getY() - 40, Color.red, ArrowBuilder.Type.TARGET);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (PlayAreaPanel panel : MageFrame.getGame(data.gameId).getPlayers().values()) {
|
||||
MagePermanent permanent = panel.getBattlefieldPanel().getPermanents().get(uuid);
|
||||
if (permanent != null) {
|
||||
Point target = permanent.getLocationOnScreen();
|
||||
target.translate(-parentPoint.x, -parentPoint.y);
|
||||
ArrowBuilder.getBuilder().addArrow(data.gameId, (int) me.getX() + 35, (int) me.getY(), (int) target.getX() + 40, (int) target.getY() + 10, Color.red, ArrowBuilder.Type.TARGET);
|
||||
continue;
|
||||
}
|
||||
|
||||
PlayerView view = panel.getPlayerPanel().getPlayer();
|
||||
if (view != null) {
|
||||
SimpleCardsView graveyard = view.getGraveyard();
|
||||
if (graveyard.containsKey(uuid)) {
|
||||
p = MageFrame.getGame(data.gameId).getPlayers().get(view.getPlayerId());
|
||||
if (p != null) {
|
||||
Point target = p.getLocationOnScreen();
|
||||
target.translate(-parentPoint.x, -parentPoint.y);
|
||||
int yOffset = p.isSmallMode() ? (PlayAreaPanel.PANEL_HEIGHT - PlayAreaPanel.PANEL_HEIGHT_SMALL) : 0;
|
||||
ArrowBuilder.getBuilder().addArrow(data.gameId, (int) me.getX() + 35, (int) me.getY(), (int) target.getX() + 15, (int) target.getY() + 145 - yOffset, Color.red, ArrowBuilder.Type.TARGET);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -20,19 +20,31 @@ import java.util.UUID;
|
|||
*/
|
||||
public class OldCardLayoutStrategy implements CardLayoutStrategy {
|
||||
|
||||
/**
|
||||
* This offset is used once to shift all attachments
|
||||
*/
|
||||
private static final int ATTACHMENTS_DX_OFFSET = 8;
|
||||
|
||||
/**
|
||||
* This offset is used for each attachment
|
||||
*/
|
||||
private static final int ATTACHMENT_DX_OFFSET = 0;
|
||||
private static final int ATTACHMENT_DY_OFFSET = 10;
|
||||
|
||||
@Override
|
||||
public void doLayout(JLayeredPane jLayeredPane, int width) {
|
||||
Map<UUID, MagePermanent> permanents = ((BattlefieldPanel)jLayeredPane).getPermanents();
|
||||
JLayeredPane jPanel = ((BattlefieldPanel)jLayeredPane).getMainPanel();
|
||||
Map<UUID, MagePermanent> permanents = ((BattlefieldPanel) jLayeredPane).getPermanents();
|
||||
JLayeredPane jPanel = ((BattlefieldPanel) jLayeredPane).getMainPanel();
|
||||
|
||||
int height = Plugins.getInstance().sortPermanents(((BattlefieldPanel)jLayeredPane).getUiComponentsList(), permanents.values());
|
||||
int height = Plugins.getInstance().sortPermanents(((BattlefieldPanel) jLayeredPane).getUiComponentsList(), permanents.values());
|
||||
jPanel.setPreferredSize(new Dimension(width - 30, height));
|
||||
|
||||
for (PermanentView permanent: ((BattlefieldPanel)jLayeredPane).getBattlefield().values()) {
|
||||
for (PermanentView permanent : ((BattlefieldPanel) jLayeredPane).getBattlefield().values()) {
|
||||
if (permanent.getAttachments() != null) {
|
||||
groupAttachments(jLayeredPane, jPanel, permanents, permanent);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void groupAttachments(JLayeredPane jLayeredPane, JLayeredPane jPanel, Map<UUID, MagePermanent> permanents, PermanentView permanent) {
|
||||
|
|
@ -60,7 +72,11 @@ public class OldCardLayoutStrategy implements CardLayoutStrategy {
|
|||
if (link != null) {
|
||||
link.setBounds(r);
|
||||
perm.getLinks().add(link);
|
||||
r.translate(8, 10);
|
||||
if (index == 1) {
|
||||
r.translate(ATTACHMENTS_DX_OFFSET, ATTACHMENT_DY_OFFSET); // do it once
|
||||
} else {
|
||||
r.translate(ATTACHMENT_DX_OFFSET, ATTACHMENT_DY_OFFSET);
|
||||
}
|
||||
perm.setBounds(r);
|
||||
jLayeredPane.moveToFront(link);
|
||||
jLayeredPane.moveToFront(perm);
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
|
|||
public int cardXOffset, cardYOffset, cardWidth, cardHeight;
|
||||
|
||||
private boolean isSelected;
|
||||
private boolean isPlayable;
|
||||
private boolean showCastingCost;
|
||||
private boolean hasImage = false;
|
||||
private float alpha = 1.0f;
|
||||
|
|
@ -106,6 +107,8 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
|
|||
|
||||
private boolean displayTitleAnyway;
|
||||
|
||||
private JPanel cardArea;
|
||||
|
||||
public CardPanel(CardView newGameCard, UUID gameId, final boolean loadImage, ActionCallback callback, final boolean foil, Dimension dimension) {
|
||||
this.gameCard = newGameCard;
|
||||
this.callback = callback;
|
||||
|
|
@ -152,7 +155,7 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
|
|||
}
|
||||
|
||||
if (this.gameCard.isToken()) {
|
||||
// token icon
|
||||
// token icon
|
||||
iconPanel = new JPanel();
|
||||
iconPanel.setLayout(null);
|
||||
iconPanel.setOpaque(false);
|
||||
|
|
@ -354,6 +357,11 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
|
|||
repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCardAreaRef(JPanel cardArea) {
|
||||
this.cardArea = cardArea;
|
||||
}
|
||||
|
||||
public boolean getSelected() {
|
||||
return this.isSelected;
|
||||
}
|
||||
|
|
@ -413,6 +421,11 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
|
|||
g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
|
||||
}
|
||||
|
||||
if (isPlayable) {
|
||||
g2d.setColor(new Color(250, 250, 0, 200));
|
||||
g2d.fillRoundRect(cardXOffset + 1, cardYOffset + 1, cardWidth - 2, cardHeight - 2, cornerSize, cornerSize);
|
||||
}
|
||||
|
||||
//TODO:uncomment
|
||||
/*
|
||||
if (gameCard.isAttacking()) {
|
||||
|
|
@ -516,22 +529,37 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
|
|||
}
|
||||
|
||||
@Override
|
||||
public final void setCardBounds(int x, int y, int width, int height) {
|
||||
cardWidth = width;
|
||||
cardHeight = height;
|
||||
int rotCenterX = Math.round(width / 2f);
|
||||
int rotCenterY = height - rotCenterX;
|
||||
int rotCenterToTopCorner = Math.round(width * CardPanel.ROT_CENTER_TO_TOP_CORNER);
|
||||
int rotCenterToBottomCorner = Math.round(width * CardPanel.ROT_CENTER_TO_BOTTOM_CORNER);
|
||||
int xOffset = rotCenterX - rotCenterToBottomCorner;
|
||||
int yOffset = rotCenterY - rotCenterToTopCorner;
|
||||
public final void setCardBounds(int x, int y, int cardWidth, int cardHeight) {
|
||||
this.cardWidth = cardWidth;
|
||||
this.cardHeight = cardHeight;
|
||||
int rotCenterX = Math.round(cardWidth / 2f);
|
||||
int rotCenterY = cardHeight - rotCenterX;
|
||||
int rotCenterToTopCorner = Math.round(cardWidth * CardPanel.ROT_CENTER_TO_TOP_CORNER);
|
||||
int rotCenterToBottomCorner = Math.round(cardWidth * CardPanel.ROT_CENTER_TO_BOTTOM_CORNER);
|
||||
int xOffset = getXOffset(cardWidth);
|
||||
int yOffset = getYOffset(cardWidth, cardHeight);
|
||||
cardXOffset = -xOffset;
|
||||
cardYOffset = -yOffset;
|
||||
width = -xOffset + rotCenterX + rotCenterToTopCorner;
|
||||
height = -yOffset + rotCenterY + rotCenterToBottomCorner;
|
||||
int width = -xOffset + rotCenterX + rotCenterToTopCorner;
|
||||
int height = -yOffset + rotCenterY + rotCenterToBottomCorner;
|
||||
setBounds(x + xOffset, y + yOffset, width, height);
|
||||
}
|
||||
|
||||
public int getXOffset(int cardWidth) {
|
||||
int rotCenterX = Math.round(cardWidth / 2f);
|
||||
int rotCenterToBottomCorner = Math.round(cardWidth * CardPanel.ROT_CENTER_TO_BOTTOM_CORNER);
|
||||
int xOffset = rotCenterX - rotCenterToBottomCorner;
|
||||
return xOffset;
|
||||
}
|
||||
|
||||
public int getYOffset(int cardWidth, int cardHeight) {
|
||||
int rotCenterX = Math.round(cardWidth / 2f);
|
||||
int rotCenterY = cardHeight - rotCenterX;
|
||||
int rotCenterToTopCorner = Math.round(cardWidth * CardPanel.ROT_CENTER_TO_TOP_CORNER);
|
||||
int yOffset = rotCenterY - rotCenterToTopCorner;
|
||||
return yOffset;
|
||||
}
|
||||
|
||||
public int getCardX() {
|
||||
return getX() + cardXOffset;
|
||||
}
|
||||
|
|
@ -686,6 +714,8 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
|
|||
}
|
||||
setText(card);
|
||||
|
||||
this.isPlayable = card.isPlayable();
|
||||
|
||||
boolean updateImage = !gameCard.getName().equals(card.getName()) || gameCard.isFaceDown() != card.isFaceDown(); // update after e.g. turning a night/day card
|
||||
this.gameCard = card;
|
||||
|
||||
|
|
@ -777,6 +807,8 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
|
|||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
data.component = this;
|
||||
callback.mouseDragged(e, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -832,13 +864,9 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
|
|||
data.card = this.gameCard;
|
||||
data.popupText = popupText;
|
||||
data.gameId = this.gameId;
|
||||
data.locationOnScreen = data.component.getLocationOnScreen(); // we need this for popup
|
||||
data.popupOffsetX = isTapped() ? cardHeight + cardXOffset + POPUP_X_GAP : cardWidth + cardXOffset + POPUP_X_GAP;
|
||||
data.popupOffsetY = 40;
|
||||
if (this.isShowing()) {
|
||||
data.locationOnScreen = this.getLocationOnScreen();
|
||||
} else {
|
||||
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
|
|
@ -965,4 +993,7 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
|
|||
callback.mouseWheelMoved(e, data);
|
||||
}
|
||||
|
||||
public JPanel getCardArea() {
|
||||
return cardArea;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ public class CardPluginImpl implements CardPlugin {
|
|||
|
||||
private static final Logger log = Logger.getLogger(CardPluginImpl.class);
|
||||
|
||||
private static final int ATTACHMENT_DY_OFFSET = 10;
|
||||
|
||||
private static final int GUTTER_Y = 15;
|
||||
private static final int GUTTER_X = 5;
|
||||
static final float EXTRA_CARD_SPACING_X = 0.04f;
|
||||
|
|
@ -149,12 +151,18 @@ public class CardPluginImpl implements CardPlugin {
|
|||
}
|
||||
|
||||
Stack stack = new Stack();
|
||||
|
||||
if (permanent.getOriginalPermanent().getAttachments() != null) {
|
||||
stack.setMaxAttachedCount(permanent.getOriginalPermanent().getAttachments().size());
|
||||
}
|
||||
|
||||
stack.add(permanent);
|
||||
allLands.add(insertIndex == -1 ? allLands.size() : insertIndex, stack);
|
||||
}
|
||||
|
||||
Row allCreatures = new Row(permanents, RowType.creature);
|
||||
Row allOthers = new Row(permanents, RowType.other);
|
||||
Row allAttached = new Row(permanents, RowType.attached);
|
||||
|
||||
boolean othersOnTheRight = true;
|
||||
if (options != null && options.containsKey("nonLandPermanentsInOnePile")) {
|
||||
|
|
@ -266,6 +274,14 @@ public class CardPluginImpl implements CardPlugin {
|
|||
y = rowBottom;
|
||||
}
|
||||
|
||||
// we need this only for defining card size
|
||||
// attached permanents will be handled separately
|
||||
for (Stack stack : allAttached) {
|
||||
for (MagePermanent panel : stack) {
|
||||
panel.setCardBounds(0, 0, cardWidth, cardHeight);
|
||||
}
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
|
|
@ -338,7 +354,7 @@ public class CardPluginImpl implements CardPlugin {
|
|||
}
|
||||
|
||||
private static enum RowType {
|
||||
land, creature, other;
|
||||
land, creature, other, attached;
|
||||
|
||||
public boolean isType(MagePermanent card) {
|
||||
switch (this) {
|
||||
|
|
@ -348,6 +364,8 @@ public class CardPluginImpl implements CardPlugin {
|
|||
return CardUtil.isCreature(card);
|
||||
case other:
|
||||
return !CardUtil.isLand(card) && !CardUtil.isCreature(card);
|
||||
case attached:
|
||||
return card.getOriginalPermanent().isAttachedTo();
|
||||
default:
|
||||
throw new RuntimeException("Unhandled type: " + this);
|
||||
}
|
||||
|
|
@ -371,8 +389,15 @@ public class CardPluginImpl implements CardPlugin {
|
|||
if (!type.isType(panel)) {
|
||||
continue;
|
||||
}
|
||||
// all attached permanents are grouped separately later
|
||||
if (!type.equals(RowType.attached) && RowType.attached.isType(panel)) {
|
||||
continue;
|
||||
}
|
||||
Stack stack = new Stack();
|
||||
stack.add(panel);
|
||||
if (panel.getOriginalPermanent().getAttachments() != null) {
|
||||
stack.setMaxAttachedCount(panel.getOriginalPermanent().getAttachments().size());
|
||||
}
|
||||
add(stack);
|
||||
}
|
||||
}
|
||||
|
|
@ -410,6 +435,11 @@ public class CardPluginImpl implements CardPlugin {
|
|||
private class Stack extends ArrayList<MagePermanent> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Max attached object count attached to single permanent in the stack.
|
||||
*/
|
||||
private int maxAttachedCount = 0;
|
||||
|
||||
public Stack() {
|
||||
super(8);
|
||||
}
|
||||
|
|
@ -419,7 +449,15 @@ public class CardPluginImpl implements CardPlugin {
|
|||
}
|
||||
|
||||
private int getHeight() {
|
||||
return cardHeight + (size() - 1) * stackSpacingY + cardSpacingY;
|
||||
return cardHeight + (size() - 1) * stackSpacingY + cardSpacingY + ATTACHMENT_DY_OFFSET*maxAttachedCount;
|
||||
}
|
||||
|
||||
public int getMaxAttachedCount() {
|
||||
return maxAttachedCount;
|
||||
}
|
||||
|
||||
public void setMaxAttachedCount(int maxAttachedCount) {
|
||||
this.maxAttachedCount = maxAttachedCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
package mage.cards;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.util.UUID;
|
||||
import javax.swing.JPanel;
|
||||
import mage.cards.action.ActionCallback;
|
||||
import mage.view.CardView;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.UUID;
|
||||
|
||||
public abstract class MageCard extends JPanel {
|
||||
private static final long serialVersionUID = 6089945326434301879L;
|
||||
|
||||
|
|
@ -27,4 +28,5 @@ public abstract class MageCard extends JPanel {
|
|||
public abstract boolean isTransformed();
|
||||
public abstract void showCardTitle();
|
||||
public abstract void setSelected(boolean selected);
|
||||
public abstract void setCardAreaRef(JPanel cardArea);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ public interface ActionCallback {
|
|||
void mousePressed(MouseEvent e, TransferData data);
|
||||
void mouseReleased(MouseEvent e, TransferData data);
|
||||
void mouseMoved(MouseEvent e, TransferData data);
|
||||
void mouseDragged(MouseEvent e, TransferData data);
|
||||
void mouseEntered(MouseEvent e, TransferData data);
|
||||
void mouseExited(MouseEvent e, TransferData data);
|
||||
void mouseWheelMoved(MouseWheelEvent e, TransferData data);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,11 @@ public class EmptyCallback implements ActionCallback {
|
|||
public void mouseMoved(MouseEvent e, TransferData data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e, TransferData data) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e, TransferData data) {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,17 +28,11 @@
|
|||
|
||||
package mage.view;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Modes;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.common.TurnFaceUpAbility;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.keyword.MorphAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.SplitCard;
|
||||
import mage.constants.CardType;
|
||||
|
|
@ -49,7 +43,6 @@ import mage.counters.Counter;
|
|||
import mage.counters.CounterType;
|
||||
import mage.game.command.Emblem;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.PermanentCard;
|
||||
import mage.game.permanent.PermanentToken;
|
||||
import mage.game.permanent.token.Token;
|
||||
import mage.game.stack.Spell;
|
||||
|
|
@ -57,6 +50,10 @@ import mage.game.stack.StackAbility;
|
|||
import mage.target.Target;
|
||||
import mage.target.Targets;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
|
|
@ -114,6 +111,8 @@ public class CardView extends SimpleCardView {
|
|||
protected boolean rotate;
|
||||
protected boolean hideInfo; // controlls if the tooltip window is shown (eg. controlled face down morph card)
|
||||
|
||||
protected boolean isPlayable;
|
||||
|
||||
public CardView(Card card) {
|
||||
this(card, null, false);
|
||||
}
|
||||
|
|
@ -673,5 +672,12 @@ public class CardView extends SimpleCardView {
|
|||
public boolean hideInfo() {
|
||||
return hideInfo;
|
||||
}
|
||||
|
||||
|
||||
public boolean isPlayable() {
|
||||
return isPlayable;
|
||||
}
|
||||
|
||||
public void setPlayable(boolean isPlayable) {
|
||||
this.isPlayable = isPlayable;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,11 +28,6 @@
|
|||
|
||||
package mage.view;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.cards.Card;
|
||||
|
|
@ -51,6 +46,9 @@ import mage.game.stack.StackAbility;
|
|||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -62,6 +60,7 @@ public class GameView implements Serializable {
|
|||
private final int priorityTime;
|
||||
private final List<PlayerView> players = new ArrayList<>();
|
||||
private SimpleCardsView hand;
|
||||
private Set<UUID> canPlayInHand;
|
||||
private Map<String, SimpleCardsView> opponentHands;
|
||||
private final CardsView stack = new CardsView();
|
||||
private final List<ExileView> exiles = new ArrayList<>();
|
||||
|
|
@ -280,4 +279,11 @@ public class GameView implements Serializable {
|
|||
return isPlayer;
|
||||
}
|
||||
|
||||
public Set<UUID> getCanPlayInHand() {
|
||||
return canPlayInHand;
|
||||
}
|
||||
|
||||
public void setCanPlayInHand(Set<UUID> canPlayInHand) {
|
||||
this.canPlayInHand = canPlayInHand;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,9 +28,6 @@
|
|||
|
||||
package mage.view;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.TurnFaceUpAbility;
|
||||
import mage.abilities.common.TurnedFaceUpTriggeredAbility;
|
||||
|
|
@ -38,10 +35,13 @@ import mage.cards.Card;
|
|||
import mage.constants.Rarity;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.PermanentCard;
|
||||
import mage.game.permanent.PermanentToken;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
|
@ -59,6 +59,7 @@ public class PermanentView extends CardView {
|
|||
private final boolean copy;
|
||||
private final String nameOwner; // only filled if != controller
|
||||
private final boolean controlled;
|
||||
private UUID attachedTo;
|
||||
|
||||
public PermanentView(Permanent permanent, Card card, UUID createdForPlayerId, Game game) {
|
||||
super(permanent, null, permanent.getControllerId().equals(createdForPlayerId));
|
||||
|
|
@ -73,6 +74,7 @@ public class PermanentView extends CardView {
|
|||
attachments = new ArrayList<>();
|
||||
attachments.addAll(permanent.getAttachments());
|
||||
}
|
||||
this.attachedTo = permanent.getAttachedTo();
|
||||
if (isToken()) {
|
||||
original = new CardView(((PermanentToken)permanent).getToken());
|
||||
original.expansionSetCode = permanent.getExpansionSetCode();
|
||||
|
|
@ -179,5 +181,12 @@ public class PermanentView extends CardView {
|
|||
public boolean isControlled() {
|
||||
return controlled;
|
||||
}
|
||||
|
||||
|
||||
public UUID getAttachedTo() {
|
||||
return attachedTo;
|
||||
}
|
||||
|
||||
public boolean isAttachedTo() {
|
||||
return attachedTo != null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,17 +28,6 @@
|
|||
|
||||
package mage.server.game;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import mage.cards.Cards;
|
||||
import mage.constants.ManaType;
|
||||
import mage.game.Game;
|
||||
|
|
@ -50,14 +39,16 @@ import mage.server.User;
|
|||
import mage.server.UserManager;
|
||||
import mage.server.util.ConfigSettings;
|
||||
import mage.server.util.ThreadExecutor;
|
||||
import mage.view.AbilityPickerView;
|
||||
import mage.view.CardsView;
|
||||
import mage.view.GameClientMessage;
|
||||
import mage.view.GameView;
|
||||
import mage.view.LookedAtView;
|
||||
import mage.view.SimpleCardsView;
|
||||
import mage.view.*;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
|
@ -245,15 +236,9 @@ public class GameSession extends GameWatcher {
|
|||
player.setUserData(this.userData);
|
||||
GameView gameView = new GameView(game.getState(), game, playerId);
|
||||
gameView.setHand(new SimpleCardsView(player.getHand().getCards(game)));
|
||||
gameView.setCanPlayInHand(player.getPlayableInHand(game));
|
||||
|
||||
if (player.getPlayersUnderYourControl().size() > 0) {
|
||||
Map<String, SimpleCardsView> handCards = new HashMap<>();
|
||||
for (UUID controlledPlayerId : player.getPlayersUnderYourControl()) {
|
||||
Player opponent = game.getPlayer(controlledPlayerId);
|
||||
handCards.put(opponent.getName(), new SimpleCardsView(opponent.getHand().getCards(game)));
|
||||
}
|
||||
gameView.setOpponentHands(handCards);
|
||||
}
|
||||
processControlledPlayers(player, gameView);
|
||||
|
||||
//TODO: should player who controls another player's turn be able to look at all these cards?
|
||||
|
||||
|
|
@ -267,6 +252,17 @@ public class GameSession extends GameWatcher {
|
|||
return gameView;
|
||||
}
|
||||
|
||||
private void processControlledPlayers(Player player, GameView gameView) {
|
||||
if (player.getPlayersUnderYourControl().size() > 0) {
|
||||
Map<String, SimpleCardsView> handCards = new HashMap<>();
|
||||
for (UUID controlledPlayerId : player.getPlayersUnderYourControl()) {
|
||||
Player opponent = game.getPlayer(controlledPlayerId);
|
||||
handCards.put(opponent.getName(), new SimpleCardsView(opponent.getHand().getCards(game)));
|
||||
}
|
||||
gameView.setOpponentHands(handCards);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeGame() {
|
||||
User user = UserManager.getInstance().getUser(userId);
|
||||
if (user != null) {
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ public class AthreosGodOfPassage extends CardImpl {
|
|||
effect.setText("As long as your devotion to white and black is less than seven, Athreos isn't a creature");
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
|
||||
// Whenever another creature you own dies, return it to your hand unless target opponent pays 3 life.
|
||||
Ability ability = new AthreosDiesCreatureTriggeredAbility(new AthreosGodOfPassageReturnEffect(), false, filter, true);
|
||||
Ability ability = new AthreosDiesCreatureTriggeredAbility(new AthreosGodOfPassageReturnEffect(), false, filter);
|
||||
ability.addTarget(new TargetOpponent());
|
||||
this.addAbility(ability);
|
||||
|
||||
|
|
@ -152,12 +152,10 @@ class AthreosGodOfPassageReturnEffect extends OneShotEffect {
|
|||
class AthreosDiesCreatureTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
protected FilterCreaturePermanent filter;
|
||||
private boolean setTargetPointer;
|
||||
|
||||
public AthreosDiesCreatureTriggeredAbility(Effect effect, boolean optional, FilterCreaturePermanent filter, boolean setTargetPointer) {
|
||||
public AthreosDiesCreatureTriggeredAbility(Effect effect, boolean optional, FilterCreaturePermanent filter) {
|
||||
super(Zone.BATTLEFIELD, effect, optional);
|
||||
this.filter = filter;
|
||||
this.setTargetPointer = setTargetPointer;
|
||||
}
|
||||
|
||||
public AthreosDiesCreatureTriggeredAbility(AthreosDiesCreatureTriggeredAbility ability) {
|
||||
|
|
@ -177,10 +175,8 @@ class AthreosDiesCreatureTriggeredAbility extends TriggeredAbilityImpl {
|
|||
if (zEvent.getFromZone().equals(Zone.BATTLEFIELD) && zEvent.getToZone().equals(Zone.GRAVEYARD)) {
|
||||
Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD);
|
||||
if (permanent != null && filter.match(permanent, sourceId, controllerId, game)) {
|
||||
if (setTargetPointer) {
|
||||
for (Effect effect : this.getEffects()) {
|
||||
effect.setValue("creatureId", event.getTargetId());
|
||||
}
|
||||
for (Effect effect : this.getEffects()) {
|
||||
effect.setValue("creatureId", event.getTargetId());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,18 +68,19 @@ public class AvariceAmulet extends CardImpl {
|
|||
// Equipped creature gets +2/+0
|
||||
Effect effect = new BoostEquippedEffect(2, 0);
|
||||
effect.setText("Equipped creature gets +2/+0");
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
|
||||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect);
|
||||
// and has vigilance
|
||||
effect = new GainAbilityAttachedEffect(VigilanceAbility.getInstance(), AttachmentType.EQUIPMENT);
|
||||
effect.setText("and has vigilance");
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
|
||||
ability.addEffect(effect);
|
||||
//and "At the beginning of your upkeep, draw a card."
|
||||
effect = new GainAbilityAttachedEffect(new BeginningOfUpkeepTriggeredAbility(new DrawCardSourceControllerEffect(1), TargetController.YOU, false), AttachmentType.EQUIPMENT);
|
||||
effect.setText("and \"At the beginning of your upkeep, draw a card.\"");
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
|
||||
ability.addEffect(effect);
|
||||
this.addAbility(ability);
|
||||
|
||||
// When equipped creature dies, target opponent gains control of Avarice Amulet.
|
||||
Ability ability = new DiesAttachedTriggeredAbility(new AvariceAmuletChangeControlEffect(), "equipped creature", false);
|
||||
ability = new DiesAttachedTriggeredAbility(new AvariceAmuletChangeControlEffect(), "equipped creature", false);
|
||||
ability.addTarget(new TargetOpponent());
|
||||
this.addAbility(ability);
|
||||
|
||||
|
|
|
|||
|
|
@ -29,9 +29,11 @@ package mage.sets.magic2015;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.combat.CantBeBlockedByOneAllEffect;
|
||||
import mage.abilities.effects.common.combat.CantBeBlockedByOneEffect;
|
||||
import mage.abilities.effects.common.continious.GainAbilityAllEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
|
|
@ -65,7 +67,8 @@ public class BelligerentSliver extends CardImpl {
|
|||
this.toughness = new MageInt(2);
|
||||
|
||||
// Sliver creatures you control have "This creature can't be blocked except by two or more creatures."
|
||||
Effect effect = new CantBeBlockedByOneAllEffect(2, filter, Duration.WhileOnBattlefield);
|
||||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new CantBeBlockedByOneEffect(2, Duration.WhileOnBattlefield));
|
||||
Effect effect = new GainAbilityAllEffect(ability, Duration.WhileOnBattlefield, filter);
|
||||
effect.setText("Sliver creatures you control have \"This creature can't be blocked except by two or more creatures.\"");
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import mage.MageInt;
|
|||
import mage.abilities.common.AuraAttachedTriggeredAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.continious.BoostSourceEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
|
|
@ -60,7 +61,9 @@ public class BroodKeeper extends CardImpl {
|
|||
|
||||
// Whenever an Aura becomes attached to Brood Keeper, put a 2/2 red Dragon creature token with flying onto the battlefield.
|
||||
// It has "{R}: This creature gets +1/+0 until end of turn."
|
||||
this.addAbility(new AuraAttachedTriggeredAbility(new CreateTokenEffect(new BroodKeeperDragonToken()), false));
|
||||
Effect effect = new CreateTokenEffect(new BroodKeeperDragonToken());
|
||||
effect.setText("put a 2/2 red Dragon creature token with flying onto the battlefield. It has \"{R}: This creature gets +1/+0 until end of turn.\"");
|
||||
this.addAbility(new AuraAttachedTriggeredAbility(effect, false));
|
||||
}
|
||||
|
||||
public BroodKeeper(final BroodKeeper card) {
|
||||
|
|
|
|||
|
|
@ -96,6 +96,12 @@ public class SiegeDragon extends CardImpl {
|
|||
|
||||
class SiegeDragonAttacksTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("wall");
|
||||
|
||||
static {
|
||||
filter.add(new SubtypePredicate("Wall"));
|
||||
}
|
||||
|
||||
public SiegeDragonAttacksTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new SiegeDragonDamageEffect());
|
||||
}
|
||||
|
|
@ -111,14 +117,13 @@ class SiegeDragonAttacksTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED && event.getSourceId().equals(this.getSourceId())) {
|
||||
FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
||||
filter.add(new ControllerIdPredicate(event.getTargetId()));
|
||||
filter.add(new SubtypePredicate("Wall"));
|
||||
List<Permanent> permanents = game.getBattlefield().getActivePermanents(filter, this.getControllerId(), this.getSourceId(), game);
|
||||
return permanents.isEmpty();
|
||||
}
|
||||
return false;
|
||||
return GameEvent.EventType.ATTACKER_DECLARED.equals(event.getType()) && event.getSourceId().equals(this.getSourceId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkInterveningIfClause(Game game) {
|
||||
UUID defendingPlayerId = game.getCombat().getDefendingPlayerId(getSourceId(), game);
|
||||
return defendingPlayerId != null && game.getBattlefield().countAll(filter, defendingPlayerId, game) < 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -144,10 +149,10 @@ class SiegeDragonDamageEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
UUID defenderId = game.getCombat().getDefenderId(source.getSourceId());
|
||||
if (defenderId != null) {
|
||||
UUID defendingPlayerId = game.getCombat().getDefendingPlayerId(source.getSourceId(), game);
|
||||
if (defendingPlayerId != null) {
|
||||
FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
||||
filter.add(new ControllerIdPredicate(defenderId));
|
||||
filter.add(new ControllerIdPredicate(defendingPlayerId));
|
||||
filter.add(Predicates.not(new AbilityPredicate(FlyingAbility.class)));
|
||||
List<Permanent> permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game);
|
||||
for (Permanent permanent : permanents) {
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ class TangleWireEffect extends OneShotEffect {
|
|||
int counterCount = permanent.getCounters().getCount(CounterType.FADE);
|
||||
int amount = Math.min(counterCount, targetCount);
|
||||
|
||||
Target target = new TargetControlledPermanent(amount, amount, filter, false);
|
||||
Target target = new TargetControlledPermanent(amount, amount, filter, true);
|
||||
target.setNotTarget(true);
|
||||
|
||||
if (amount > 0 && player.chooseTarget(Outcome.Tap, target, source, game)) {
|
||||
|
|
|
|||
|
|
@ -62,9 +62,9 @@ public class CephalidColiseum extends CardImpl {
|
|||
// Threshold - {U}, {tap}, Sacrifice Cephalid Coliseum: Target player draws three cards, then discards three cards. Activate this ability only if seven or more cards are in your graveyard.
|
||||
Ability thresholdAbility = new ConditionalGainActivatedAbility(Zone.BATTLEFIELD,
|
||||
new DrawCardTargetEffect(3),
|
||||
new ManaCostsImpl("{G}"),
|
||||
new ManaCostsImpl("{U}"),
|
||||
new CardsInControllerGraveCondition(7),
|
||||
"<i>Threshold</i> - {G}, {T}, Sacrifice {this}: Target player draws three cards, then discards three cards. Activate this ability only if seven or more cards are in your graveyard.");
|
||||
"<i>Threshold</i> - {U}, {T}, Sacrifice {this}: Target player draws three cards, then discards three cards. Activate this ability only if seven or more cards are in your graveyard.");
|
||||
thresholdAbility.addEffect(new DiscardTargetEffect(3));
|
||||
thresholdAbility.addCost(new TapSourceCost());
|
||||
thresholdAbility.addCost(new SacrificeSourceCost());
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
package mage.sets.onslaught;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.CycleAllTriggeredAbility;
|
||||
import mage.abilities.common.delayed.AtEndOfTurnDelayedTriggeredAbility;
|
||||
|
|
@ -86,12 +87,14 @@ class AstralSlideEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
MageObject sourceObject = game.getObject(source.getSourceId());
|
||||
if (controller != null && sourceObject != null) {
|
||||
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
||||
if (permanent != null) {
|
||||
if (controller.moveCardToExileWithInfo(permanent, null, "", source.getSourceId(), game, Zone.BATTLEFIELD)) {
|
||||
UUID exileId = UUID.randomUUID();
|
||||
if (controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getLogName(), source.getSourceId(), game, Zone.BATTLEFIELD)) {
|
||||
//create delayed triggered ability
|
||||
AtEndOfTurnDelayedTriggeredAbility delayedAbility = new AtEndOfTurnDelayedTriggeredAbility(new ReturnFromExileEffect(source.getSourceId(), Zone.BATTLEFIELD, false));
|
||||
AtEndOfTurnDelayedTriggeredAbility delayedAbility = new AtEndOfTurnDelayedTriggeredAbility(new ReturnFromExileEffect(exileId, Zone.BATTLEFIELD, false));
|
||||
delayedAbility.setSourceId(source.getSourceId());
|
||||
delayedAbility.setControllerId(source.getControllerId());
|
||||
game.addDelayedTriggeredAbility(delayedAbility);
|
||||
|
|
|
|||
|
|
@ -89,31 +89,34 @@ class ChainOfVaporEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
||||
if (permanent != null) {
|
||||
if(!permanent.moveToZone(Zone.HAND, source.getId(), game, false)){
|
||||
if (!controller.moveCardToHandWithInfo(permanent, source.getSourceId(), game, Zone.BATTLEFIELD)){
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
Player player = game.getPlayer(permanent.getControllerId());
|
||||
if(player.chooseUse(Outcome.ReturnToHand, "Sacrifice a land to copy this spell?", game)){
|
||||
if (player.chooseUse(Outcome.ReturnToHand, "Sacrifice a land to copy this spell?", game)){
|
||||
TargetControlledPermanent target = new TargetControlledPermanent(new FilterControlledLandPermanent());
|
||||
if(player.chooseTarget(Outcome.Sacrifice, target, source, game)){
|
||||
if (player.chooseTarget(Outcome.Sacrifice, target, source, game)){
|
||||
Permanent land = game.getPermanent(target.getFirstTarget());
|
||||
if(land != null){
|
||||
if(land.sacrifice(source.getId(), game)){
|
||||
Spell spell = game.getStack().getSpell(source.getId());
|
||||
Spell spell = game.getStack().getSpell(source.getSourceId());
|
||||
if (spell != null) {
|
||||
Spell copy = spell.copySpell();
|
||||
copy.setControllerId(player.getId());
|
||||
copy.setCopiedSpell(true);
|
||||
game.getStack().push(copy);
|
||||
copy.chooseNewTargets(game, source.getControllerId());
|
||||
copy.chooseNewTargets(game, player.getId());
|
||||
String activateMessage = copy.getActivatedMessage(game);
|
||||
if (activateMessage.startsWith(" casts ")) {
|
||||
activateMessage = activateMessage.substring(6);
|
||||
}
|
||||
game.informPlayers(player.getName() + " copies " + activateMessage);;
|
||||
game.informPlayers(player.getName() + " copies " + activateMessage);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -34,9 +34,13 @@ import mage.constants.Rarity;
|
|||
import mage.MageInt;
|
||||
import mage.Mana;
|
||||
import mage.abilities.costs.common.SacrificeSourceCost;
|
||||
import mage.abilities.costs.common.SacrificeTargetCost;
|
||||
import mage.abilities.mana.SimpleManaAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.SubtypePredicate;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -44,6 +48,12 @@ import mage.constants.Zone;
|
|||
*/
|
||||
public class SkirkProspector extends CardImpl {
|
||||
|
||||
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("a Goblin");
|
||||
|
||||
static {
|
||||
filter.add(new SubtypePredicate(("Goblin")));
|
||||
}
|
||||
|
||||
public SkirkProspector(UUID ownerId) {
|
||||
super(ownerId, 230, "Skirk Prospector", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{R}");
|
||||
this.expansionSetCode = "ONS";
|
||||
|
|
@ -54,7 +64,7 @@ public class SkirkProspector extends CardImpl {
|
|||
this.toughness = new MageInt(1);
|
||||
|
||||
// Sacrifice a Goblin: Add {R} to your mana pool.
|
||||
this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, Mana.RedMana, new SacrificeSourceCost()));
|
||||
this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, Mana.RedMana, new SacrificeTargetCost(new TargetControlledCreaturePermanent(1,1,filter,true))));
|
||||
}
|
||||
|
||||
public SkirkProspector(final SkirkProspector card) {
|
||||
|
|
|
|||
70
Mage.Sets/src/mage/sets/planeshift/EladamrisCall.java
Normal file
70
Mage.Sets/src/mage/sets/planeshift/EladamrisCall.java
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.sets.planeshift;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.mageobject.CardTypePredicate;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class EladamrisCall extends CardImpl {
|
||||
|
||||
private static final FilterCard filter = new FilterCard("creature card");
|
||||
|
||||
static {
|
||||
filter.add(new CardTypePredicate(CardType.CREATURE));
|
||||
}
|
||||
|
||||
public EladamrisCall(UUID ownerId) {
|
||||
super(ownerId, 106, "Eladamri's Call", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{G}{W}");
|
||||
this.expansionSetCode = "PLS";
|
||||
|
||||
this.color.setGreen(true);
|
||||
this.color.setWhite(true);
|
||||
|
||||
// Search your library for a creature card, reveal that card, and put it into your hand. Then shuffle your library.
|
||||
this.getSpellAbility().addEffect(new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter), true, true));
|
||||
}
|
||||
|
||||
public EladamrisCall(final EladamrisCall card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EladamrisCall copy() {
|
||||
return new EladamrisCall(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@ import mage.constants.Duration;
|
|||
import mage.constants.Rarity;
|
||||
import mage.constants.TargetController;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterLandPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.SupertypePredicate;
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ import mage.filter.predicate.mageobject.SupertypePredicate;
|
|||
*/
|
||||
public class BackToBasics extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterPermanent("Nonbasic lands");
|
||||
private static final FilterLandPermanent filter = new FilterLandPermanent("Nonbasic lands");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.not(new SupertypePredicate("Basic")));
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ public class DeftbladeElite extends CardImpl {
|
|||
// {1}{W}: Prevent all combat damage that would be dealt to and dealt by Deftblade Elite this turn.
|
||||
Effect effect = new PreventCombatDamageToSourceEffect(Duration.EndOfTurn);
|
||||
effect.setText("Prevent all combat damage that would be dealt to");
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{3}{W}"));
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{1}{W}"));
|
||||
effect = new PreventCombatDamageBySourceEffect(Duration.EndOfTurn);
|
||||
effect.setText("and dealt by {this} this turn");
|
||||
ability.addEffect(effect);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import mage.players.Player;
|
|||
import mage.target.common.TargetCardInLibrary;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.constants.TimingRule;
|
||||
|
||||
/**
|
||||
* @author Loki
|
||||
|
|
@ -25,6 +26,7 @@ import java.util.UUID;
|
|||
public class TransmuteAbility extends SimpleActivatedAbility {
|
||||
public TransmuteAbility(String manaCost) {
|
||||
super(Zone.HAND, new TransmuteEffect(), new ManaCostsImpl(manaCost));
|
||||
this.setTiming(TimingRule.SORCERY);
|
||||
this.addCost(new DiscardSourceCost());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,23 +28,6 @@
|
|||
|
||||
package mage.game;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbility;
|
||||
|
|
@ -69,13 +52,7 @@ import mage.cards.CardsImpl;
|
|||
import mage.cards.SplitCard;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.choices.Choice;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.MultiplayerAttackOption;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import mage.constants.Zone;
|
||||
import mage.constants.*;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.Filter;
|
||||
import mage.filter.FilterPermanent;
|
||||
|
|
@ -90,14 +67,8 @@ import mage.game.combat.Combat;
|
|||
import mage.game.command.CommandObject;
|
||||
import mage.game.command.Commander;
|
||||
import mage.game.command.Emblem;
|
||||
import mage.game.events.DamageEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.Listener;
|
||||
import mage.game.events.PlayerQueryEvent;
|
||||
import mage.game.events.PlayerQueryEventSource;
|
||||
import mage.game.events.TableEvent;
|
||||
import mage.game.events.*;
|
||||
import mage.game.events.TableEvent.EventType;
|
||||
import mage.game.events.TableEventSource;
|
||||
import mage.game.permanent.Battlefield;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.PermanentCard;
|
||||
|
|
@ -115,14 +86,14 @@ import mage.target.Target;
|
|||
import mage.target.TargetPermanent;
|
||||
import mage.target.TargetPlayer;
|
||||
import mage.util.functions.ApplyToPermanent;
|
||||
import mage.watchers.common.CastSpellLastTurnWatcher;
|
||||
import mage.watchers.common.MiracleWatcher;
|
||||
import mage.watchers.common.MorbidWatcher;
|
||||
import mage.watchers.common.PlayerDamagedBySourceWatcher;
|
||||
import mage.watchers.common.PlayerLostLifeWatcher;
|
||||
import mage.watchers.common.SoulbondWatcher;
|
||||
import mage.watchers.common.*;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public abstract class GameImpl implements Game, Serializable {
|
||||
|
||||
private static final transient Logger logger = Logger.getLogger(GameImpl.class);
|
||||
|
|
@ -1859,7 +1830,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
|
||||
@Override
|
||||
public boolean canPlaySorcery(UUID playerId) {
|
||||
return getActivePlayerId().equals(playerId) && getStack().isEmpty() && isMainPhase();
|
||||
return isMainPhase() && getActivePlayerId().equals(playerId) && getStack().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -28,21 +28,9 @@
|
|||
|
||||
package mage.players;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageItem;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Abilities;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbility;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.Modes;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.abilities.*;
|
||||
import mage.abilities.costs.AlternativeSourceCosts;
|
||||
import mage.abilities.costs.VariableCost;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
|
|
@ -69,6 +57,9 @@ import mage.target.TargetCard;
|
|||
import mage.target.common.TargetCardInLibrary;
|
||||
import mage.util.Copyable;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
|
@ -340,6 +331,8 @@ public interface Player extends MageItem, Copyable<Player> {
|
|||
List<Ability> getPlayable(Game game, boolean hidden);
|
||||
List<Ability> getPlayableOptions(Ability ability, Game game);
|
||||
|
||||
Set<UUID> getPlayableInHand(Game game);
|
||||
|
||||
void addCounters(Counter counter, Game game);
|
||||
List<UUID> getAttachments();
|
||||
boolean addAttachment(UUID permanentId, Game game);
|
||||
|
|
|
|||
|
|
@ -28,31 +28,9 @@
|
|||
|
||||
package mage.players;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Abilities;
|
||||
import mage.abilities.AbilitiesImpl;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbility;
|
||||
import mage.abilities.DelayedTriggeredAbility;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.PlayLandAbility;
|
||||
import mage.abilities.SpecialAction;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.abilities.*;
|
||||
import mage.abilities.common.PassAbility;
|
||||
import mage.abilities.common.delayed.AtTheEndOfTurnStepPostDelayedTriggeredAbility;
|
||||
import mage.abilities.costs.AdjustingSourceCosts;
|
||||
|
|
@ -62,12 +40,7 @@ import mage.abilities.costs.AlternativeSourceCosts;
|
|||
import mage.abilities.effects.RestrictionEffect;
|
||||
import mage.abilities.effects.RestrictionUntapNotMoreThanEffect;
|
||||
import mage.abilities.effects.common.LoseControlOnOtherPlayersControllerEffect;
|
||||
import mage.abilities.keyword.FlashbackAbility;
|
||||
import mage.abilities.keyword.HexproofAbility;
|
||||
import mage.abilities.keyword.InfectAbility;
|
||||
import mage.abilities.keyword.LifelinkAbility;
|
||||
import mage.abilities.keyword.ProtectionAbility;
|
||||
import mage.abilities.keyword.ShroudAbility;
|
||||
import mage.abilities.keyword.*;
|
||||
import mage.abilities.mana.ManaAbility;
|
||||
import mage.abilities.mana.ManaOptions;
|
||||
import mage.actions.MageDrawAction;
|
||||
|
|
@ -76,14 +49,7 @@ import mage.cards.Cards;
|
|||
import mage.cards.CardsImpl;
|
||||
import mage.cards.SplitCard;
|
||||
import mage.cards.decks.Deck;
|
||||
import mage.constants.AsThoughEffectType;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.ManaType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import mage.constants.SpellAbilityType;
|
||||
import mage.constants.TimingRule;
|
||||
import mage.constants.Zone;
|
||||
import mage.constants.*;
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.CounterType;
|
||||
import mage.counters.Counters;
|
||||
|
|
@ -116,6 +82,10 @@ import mage.target.common.TargetDiscard;
|
|||
import mage.watchers.common.BloodthirstWatcher;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public abstract class PlayerImpl implements Player, Serializable {
|
||||
|
||||
private static final transient Logger log = Logger.getLogger(PlayerImpl.class);
|
||||
|
|
@ -1544,7 +1514,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
|
||||
@Override
|
||||
public void idleTimeout(Game game) {
|
||||
game.informPlayers(new StringBuilder(getName()).append(" has run out of time. Loosing the Match.").toString());
|
||||
game.informPlayers(new StringBuilder(getName()).append(" was idle for too long. Loosing the Match.").toString());
|
||||
quit = true;
|
||||
idleTimeout = true;
|
||||
this.concede(game);
|
||||
|
|
@ -1973,6 +1943,25 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
return playable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getPlayableInHand(Game game) {
|
||||
Set<UUID> playable = new HashSet<>();
|
||||
|
||||
ManaOptions available = getManaAvailable(game);
|
||||
available.addMana(manaPool.getMana());
|
||||
|
||||
for (Card card: hand.getCards(game)) {
|
||||
for (ActivatedAbility ability: card.getAbilities().getPlayableAbilities(Zone.HAND)) {
|
||||
if (canPlay(ability, available, game)) {
|
||||
playable.add(card.getId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return playable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only used for AIs
|
||||
*
|
||||
|
|
|
|||
|
|
@ -327,7 +327,7 @@ public abstract class TargetImpl implements Target {
|
|||
@Override
|
||||
public boolean isLegal(Ability source, Game game) {
|
||||
//20101001 - 608.2b
|
||||
Set <UUID> illegalTargets = new HashSet<UUID>();
|
||||
Set <UUID> illegalTargets = new HashSet<>();
|
||||
int replacedTargets = 0;
|
||||
for (UUID targetId: targets.keySet()) {
|
||||
Card card = game.getCard(targetId);
|
||||
|
|
|
|||
|
|
@ -53,7 +53,12 @@ public class TargetCreatureOrPlayerAmount extends TargetAmount {
|
|||
protected FilterCreatureOrPlayer filter;
|
||||
|
||||
public TargetCreatureOrPlayerAmount(int amount) {
|
||||
// 107.1c If a rule or ability instructs a player to choose “any number,” that player may choose
|
||||
// any positive number or zero, unless something (such as damage or counters) is being divided
|
||||
// or distributed among “any number” of players and/or objects. In that case, a nonzero number
|
||||
// of players and/or objects must be chosen if possible.
|
||||
this(new StaticValue(amount));
|
||||
this.minNumberOfTargets = 1;
|
||||
}
|
||||
|
||||
public TargetCreatureOrPlayerAmount(DynamicValue amount) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue