From a7409f3d0824b18ae15a74842c515bc01bf19032 Mon Sep 17 00:00:00 2001 From: draxdyn Date: Fri, 24 Jun 2016 17:46:46 +0200 Subject: [PATCH 1/7] Hold priority on Ctrl+click In most cases, it is not useful to hold priority after doing something, since the spell or ability added to the stack can just be performed beforehand. Hence, automatically passing priority is the only comfortable setting. However, in some cases it is useful (chiefly for Infernal Tutor + Lion's Eye Diamond and similar interaction), and currently players have to open Preferences, change the option and then change it back whenever they need to hold priority, which is very annoying. This change allows to temporarily hold priority by simply holding Control while performing an action, which solves the issue in a manner similar to other clients. A "Hold" indicator next to the spells cast indicator is displayed so that the user knows his Control key holding was registered. The code works by adding a new HOLD_PRIORITY player action that causes the automatic priority pass options to be ignored until the player is given priority again. The client sends the message whenever it's not already holding priority and Ctrl+click/space/enter happens anywhere. This is somewhat "loose" as it means that Ctrl+click on the background also holds priority, but this might actually be desirable and it greatly simplifies the code, since only a global AWT event listener is required, and there is no need to change every place in the code that could add something to the stack. It is also possible to hold priority and stop holding priority using the context menu. --- .../src/main/java/mage/client/MageFrame.java | 31 ++++++++ .../src/main/java/mage/client/MagePane.java | 4 + .../main/java/mage/client/game/GamePane.java | 7 +- .../main/java/mage/client/game/GamePanel.java | 76 +++++++++++++++++-- .../java/mage/client/game/PlayAreaPanel.java | 25 +++++- .../client/remote/CallbackClientImpl.java | 3 +- .../src/mage/player/human/HumanPlayer.java | 11 ++- .../java/mage/constants/PlayerAction.java | 3 +- 8 files changed, 147 insertions(+), 13 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/MageFrame.java b/Mage.Client/src/main/java/mage/client/MageFrame.java index c9d69ca85f0..9752b1cd8a8 100644 --- a/Mage.Client/src/main/java/mage/client/MageFrame.java +++ b/Mage.Client/src/main/java/mage/client/MageFrame.java @@ -27,16 +27,20 @@ */ package mage.client; +import java.awt.AWTEvent; import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; +import java.awt.EventQueue; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Rectangle; import java.awt.SplashScreen; +import java.awt.Toolkit; +import java.awt.event.AWTEventListener; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; @@ -225,6 +229,26 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { return instance; } + private void handleEvent(AWTEvent event) { + MagePane frame = activeFrame; + + // support multiple mage panes + Object source = event.getSource(); + if(source instanceof Component) { + Component component = (Component)source; + while(component != null) { + if(component instanceof MagePane) { + frame = (MagePane)component; + break; + } + component = component.getParent(); + } + } + + if(frame != null) + frame.handleEvent(event); + } + /** * Creates new form MageFrame */ @@ -240,6 +264,13 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { } }); + Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { + @Override + public void eventDispatched(AWTEvent event) { + handleEvent(event); + } + }, AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK); + TConfig config = TConfig.current(); config.setArchiveDetector(new TArchiveDetector("zip")); config.setAccessPreference(FsAccessOption.STORE, true); diff --git a/Mage.Client/src/main/java/mage/client/MagePane.java b/Mage.Client/src/main/java/mage/client/MagePane.java index 8ddadc66953..b4a4d474d6e 100644 --- a/Mage.Client/src/main/java/mage/client/MagePane.java +++ b/Mage.Client/src/main/java/mage/client/MagePane.java @@ -33,6 +33,7 @@ */ package mage.client; +import java.awt.AWTEvent; import java.awt.KeyboardFocusManager; import java.beans.PropertyVetoException; import javax.swing.plaf.basic.BasicInternalFrameUI; @@ -91,6 +92,9 @@ public abstract class MagePane extends javax.swing.JInternalFrame { } + public void handleEvent(AWTEvent event) { + } + /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always diff --git a/Mage.Client/src/main/java/mage/client/game/GamePane.java b/Mage.Client/src/main/java/mage/client/game/GamePane.java index 06e86103cf3..b0c445fdfa1 100644 --- a/Mage.Client/src/main/java/mage/client/game/GamePane.java +++ b/Mage.Client/src/main/java/mage/client/game/GamePane.java @@ -33,6 +33,7 @@ */ package mage.client.game; +import java.awt.AWTEvent; import java.util.UUID; import javax.swing.SwingUtilities; import mage.client.MagePane; @@ -132,8 +133,12 @@ public class GamePane extends MagePane { gamePanel.activated(); } + @Override + public void handleEvent(AWTEvent event) { + gamePanel.handleEvent(event); + } + private mage.client.game.GamePanel gamePanel; private javax.swing.JScrollPane jScrollPane1; private UUID gameId; - } diff --git a/Mage.Client/src/main/java/mage/client/game/GamePanel.java b/Mage.Client/src/main/java/mage/client/game/GamePanel.java index 2b424627a2e..a7ab2aad802 100644 --- a/Mage.Client/src/main/java/mage/client/game/GamePanel.java +++ b/Mage.Client/src/main/java/mage/client/game/GamePanel.java @@ -27,6 +27,7 @@ */ package mage.client.game; +import java.awt.AWTEvent; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; @@ -391,6 +392,7 @@ public final class GamePanel extends javax.swing.JPanel { stackObjects.setCardDimension(GUISizeHelper.handCardDimension); txtSpellsCast.setFont(new Font(GUISizeHelper.gameDialogAreaFont.getFontName(), Font.BOLD, GUISizeHelper.gameDialogAreaFont.getSize())); + txtHoldPriority.setFont(new Font(GUISizeHelper.gameDialogAreaFont.getFontName(), Font.BOLD, GUISizeHelper.gameDialogAreaFont.getSize())); GUISizeHelper.changePopupMenuFont(popupMenuTriggerOrder); int newStackWidth = pnlHelperHandButtonsStackArea.getWidth() * GUISizeHelper.stackWidth / 100; @@ -589,7 +591,8 @@ public final class GamePanel extends javax.swing.JPanel { setMenuStates( PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT, "true").equals("true"), PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, "true").equals("true"), - PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true") + PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"), + holdingPriority ); updateGame(game); @@ -957,9 +960,9 @@ public final class GamePanel extends javax.swing.JPanel { * @param manaPoolAutomaticRestricted * @param useFirstManaAbility */ - public void setMenuStates(boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted, boolean useFirstManaAbility) { + public void setMenuStates(boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted, boolean useFirstManaAbility, boolean holdPriority) { for (PlayAreaPanel playAreaPanel : players.values()) { - playAreaPanel.setMenuStates(manaPoolAutomatic, manaPoolAutomaticRestricted, useFirstManaAbility); + playAreaPanel.setMenuStates(manaPoolAutomatic, manaPoolAutomaticRestricted, useFirstManaAbility, holdPriority); } } @@ -1201,6 +1204,14 @@ public final class GamePanel extends javax.swing.JPanel { } public void select(String message, GameView gameView, int messageId, Map options) { + holdingPriority = false; + txtHoldPriority.setVisible(false); + setMenuStates( + PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT, "true").equals("true"), + PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, "true").equals("true"), + PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"), + false); + updateGame(gameView, options); boolean controllingPlayer = false; for (PlayerView playerView : gameView.getPlayers()) { @@ -1340,6 +1351,14 @@ public final class GamePanel extends javax.swing.JPanel { txtSpellsCast.setOpaque(true); txtSpellsCast.setToolTipText("spells cast during the current turn"); + txtHoldPriority = new javax.swing.JLabel(); + txtHoldPriority.setText("Hold"); + txtHoldPriority.setBorder(BorderFactory.createCompoundBorder(border, paddingBorder)); + txtHoldPriority.setBackground(Color.LIGHT_GRAY); + txtHoldPriority.setOpaque(true); + txtHoldPriority.setToolTipText("Holding priority after the next spell cast or ability activation"); + txtHoldPriority.setVisible(false); + btnCancelSkip = new javax.swing.JButton(); // F3 btnSkipToNextTurn = new javax.swing.JButton(); // F4 btnSkipToEndTurn = new javax.swing.JButton(); // F5 @@ -1670,7 +1689,8 @@ public final class GamePanel extends javax.swing.JPanel { setMenuStates( PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT, "true").equals("true"), PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, "true").equals("true"), - PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true")); + PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"), + holdingPriority); } }); @@ -1713,7 +1733,8 @@ public final class GamePanel extends javax.swing.JPanel { setMenuStates( PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT, "true").equals("true"), PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, "true").equals("true"), - PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true")); + PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"), + holdingPriority); } }); @@ -1829,6 +1850,7 @@ public final class GamePanel extends javax.swing.JPanel { .addComponent(btnSkipToEndStepBeforeYourTurn) ) .addGroup(gl_pnlShortCuts.createSequentialGroup() + .addComponent(txtHoldPriority) .addComponent(txtSpellsCast) .addComponent(btnSwitchHands) .addComponent(btnCancelSkip) @@ -1862,6 +1884,7 @@ public final class GamePanel extends javax.swing.JPanel { .addComponent(btnSkipToEndStepBeforeYourTurn) ) .addGroup(gl_pnlShortCuts.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(txtHoldPriority) .addComponent(txtSpellsCast) .addComponent(btnSwitchHands) .addComponent(btnCancelSkip) @@ -2343,6 +2366,48 @@ public final class GamePanel extends javax.swing.JPanel { return feedbackPanel; } + // Use Cmd on OSX since Ctrl+click is already used to simulate right click + private static int holdPriorityMask = System.getProperty("os.name").contains("Mac OS X") ? InputEvent.META_DOWN_MASK : InputEvent.CTRL_DOWN_MASK; + + public void handleEvent(AWTEvent event) { + if(event instanceof InputEvent) { + int id = event.getID(); + boolean isActionEvent = false; + if(id == MouseEvent.MOUSE_PRESSED) + isActionEvent = true; + else if(id == KeyEvent.KEY_PRESSED) + { + KeyEvent key = (KeyEvent)event; + int keyCode = key.getKeyCode(); + if(keyCode == KeyEvent.VK_ENTER || keyCode == KeyEvent.VK_SPACE) + isActionEvent = true; + } + if(isActionEvent) { + InputEvent input = (InputEvent)event; + if((input.getModifiersEx() & holdPriorityMask) != 0) { + setMenuStates( + PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT, "true").equals("true"), + PreferencesDialog.getCachedValue(KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, "true").equals("true"), + PreferencesDialog.getCachedValue(KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"), + true); + holdPriority(true); + } + } + } + } + + public void holdPriority(boolean holdPriority) { + if(holdingPriority != holdPriority) { + holdingPriority = holdPriority; + txtHoldPriority.setVisible(holdPriority); + if(holdPriority) + session.sendPlayerAction(PlayerAction.HOLD_PRIORITY, gameId, null); + else + session.sendPlayerAction(PlayerAction.UNHOLD_PRIORITY, gameId, null); + } + } + + private boolean holdingPriority; private mage.client.components.ability.AbilityPicker abilityPicker; private mage.client.cards.BigCard bigCard; @@ -2397,6 +2462,7 @@ public final class GamePanel extends javax.swing.JPanel { private JPanel jPhases; private JPanel phasesContainer; private javax.swing.JLabel txtSpellsCast; + private javax.swing.JLabel txtHoldPriority; private HoverButton currentStep; private Point prevPoint; diff --git a/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java b/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java index e7ad6fff293..9568d51b13c 100644 --- a/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java +++ b/Mage.Client/src/main/java/mage/client/game/PlayAreaPanel.java @@ -78,6 +78,7 @@ public class PlayAreaPanel extends javax.swing.JPanel { private JCheckBoxMenuItem manaPoolMenuItem2; private JCheckBoxMenuItem useFirstManaAbilityItem; private JCheckBoxMenuItem allowViewHandCardsMenuItem; + private JCheckBoxMenuItem holdPriorityMenuItem; public static final int PANEL_HEIGHT = 242; public static final int PANEL_HEIGHT_SMALL = 190; @@ -210,6 +211,19 @@ public class PlayAreaPanel extends javax.swing.JPanel { popupMenu.add(menuItem); menuItem.addActionListener(skipListener); + holdPriorityMenuItem = new JCheckBoxMenuItem("" + (System.getProperty("os.name").contains("Mac OS X") ? "Cmd" : "Ctrl") + "+click - Hold Priority"); + holdPriorityMenuItem.setMnemonic(KeyEvent.VK_P); + holdPriorityMenuItem.setToolTipText("Hold priority after casting a spell or activating an ability, instead of automatically passing priority."); + popupMenu.add(holdPriorityMenuItem); + holdPriorityMenuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + boolean holdPriority = ((JCheckBoxMenuItem)e.getSource()).getState(); + gamePanel.setMenuStates(manaPoolMenuItem1.getState(), manaPoolMenuItem2.getState(), useFirstManaAbilityItem.getState(), holdPriority); + gamePanel.holdPriority(holdPriority); + } + }); + JMenu skipMenu = new JMenu("Skip"); skipMenu.setMnemonic(KeyEvent.VK_S); popupMenu.add(skipMenu); @@ -277,7 +291,7 @@ public class PlayAreaPanel extends javax.swing.JPanel { public void actionPerformed(ActionEvent e) { boolean manaPoolAutomatic = ((JCheckBoxMenuItem) e.getSource()).getState(); PreferencesDialog.saveValue(KEY_GAME_MANA_AUTOPAYMENT, manaPoolAutomatic ? "true" : "false"); - gamePanel.setMenuStates(manaPoolAutomatic, manaPoolMenuItem2.getState(), useFirstManaAbilityItem.getState()); + gamePanel.setMenuStates(manaPoolAutomatic, manaPoolMenuItem2.getState(), useFirstManaAbilityItem.getState(), holdPriorityMenuItem.getState()); gamePanel.getSession().sendPlayerAction(manaPoolAutomatic ? PlayerAction.MANA_AUTO_PAYMENT_ON : PlayerAction.MANA_AUTO_PAYMENT_OFF, gameId, null); } }); @@ -295,7 +309,7 @@ public class PlayAreaPanel extends javax.swing.JPanel { public void actionPerformed(ActionEvent e) { boolean manaPoolAutomaticRestricted = ((JCheckBoxMenuItem) e.getSource()).getState(); PreferencesDialog.saveValue(KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, manaPoolAutomaticRestricted ? "true" : "false"); - gamePanel.setMenuStates(manaPoolMenuItem1.getState(), manaPoolAutomaticRestricted, useFirstManaAbilityItem.getState()); + gamePanel.setMenuStates(manaPoolMenuItem1.getState(), manaPoolAutomaticRestricted, useFirstManaAbilityItem.getState(), holdPriorityMenuItem.getState()); gamePanel.getSession().sendPlayerAction(manaPoolAutomaticRestricted ? PlayerAction.MANA_AUTO_PAYMENT_RESTRICTED_ON : PlayerAction.MANA_AUTO_PAYMENT_RESTRICTED_OFF, gameId, null); } }); @@ -313,7 +327,7 @@ public class PlayAreaPanel extends javax.swing.JPanel { public void actionPerformed(ActionEvent e) { boolean useFirstManaAbility = ((JCheckBoxMenuItem) e.getSource()).getState(); PreferencesDialog.saveValue(KEY_USE_FIRST_MANA_ABILITY, useFirstManaAbility ? "true" : "false"); - gamePanel.setMenuStates(manaPoolMenuItem1.getState(), manaPoolMenuItem2.getState(), useFirstManaAbility); + gamePanel.setMenuStates(manaPoolMenuItem1.getState(), manaPoolMenuItem2.getState(), useFirstManaAbility, holdPriorityMenuItem.getState()); gamePanel.getSession().sendPlayerAction(useFirstManaAbility ? PlayerAction.USE_FIRST_MANA_ABILITY_ON: PlayerAction.USE_FIRST_MANA_ABILITY_OFF, gameId, null); } }); @@ -642,7 +656,7 @@ public class PlayAreaPanel extends javax.swing.JPanel { this.playingMode = playingMode; } - public void setMenuStates(boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted, boolean useFirstManaAbility) { + public void setMenuStates(boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted, boolean useFirstManaAbility, boolean holdPriority) { if (manaPoolMenuItem1 != null) { manaPoolMenuItem1.setSelected(manaPoolAutomatic); } @@ -652,6 +666,9 @@ public class PlayAreaPanel extends javax.swing.JPanel { if (useFirstManaAbilityItem != null) { useFirstManaAbilityItem.setSelected(useFirstManaAbility); } + if (holdPriorityMenuItem != null) { + holdPriorityMenuItem.setSelected(holdPriority); + } } private mage.client.game.BattlefieldPanel battlefieldPanel; diff --git a/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java b/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java index 326d3a3d59b..18bdfa651e7 100644 --- a/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java +++ b/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java @@ -395,7 +395,8 @@ public class CallbackClientImpl implements CallbackClient { .append("
F7 - Skip to next main phase but stop on declare attackers/blockers and something on the stack") .append("
F9 - Skip everything until your next turn") .append("
F11 - Skip everything until the end step just prior to your turn") - .append("
F3 - Undo F4/F5/F7/F9/F11").toString(), + .append("
F3 - Undo F4/F5/F7/F9/F11") + .append("
").append(System.getProperty("os.name").contains("Mac OS X") ? "Cmd" : "Ctrl").append(" + click - Hold priority while casting a spell or activating an ability").toString(), null, MessageType.USER_INFO, ChatMessage.MessageColor.BLUE); break; case TOURNAMENT: diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index a2a48fb1d61..203e5d45481 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -123,6 +123,8 @@ public class HumanPlayer extends PlayerImpl { protected Map requestAutoAnswerId = new HashMap<>(); protected Map requestAutoAnswerText = new HashMap<>(); + protected boolean holdingPriority; + public HumanPlayer(String name, RangeOfInfluence range, int skill) { super(name, range); replacementEffectChoice = new ChoiceImpl(true); @@ -565,7 +567,7 @@ public class HumanPlayer extends PlayerImpl { public boolean priority(Game game) { passed = false; if (!abort) { - if (getJustActivatedType() != null) { + if (getJustActivatedType() != null && !holdingPriority) { if (userData.isPassPriorityCast() && getJustActivatedType().equals(AbilityType.SPELL)) { setJustActivatedType(null); pass(game); @@ -661,6 +663,7 @@ public class HumanPlayer extends PlayerImpl { } while (canRespond()) { updateGameStatePriority("priority", game); + holdingPriority = false; game.firePriorityEvent(playerId); waitForResponse(game); if (game.executingRollback()) { @@ -1465,6 +1468,12 @@ public class HumanPlayer extends PlayerImpl { case REQUEST_AUTO_ANSWER_RESET_ALL: setRequestAutoAnswer(playerAction, game, data); break; + case HOLD_PRIORITY: + holdingPriority = true; + break; + case UNHOLD_PRIORITY: + holdingPriority = false; + break; default: super.sendPlayerAction(playerAction, game, data); } diff --git a/Mage/src/main/java/mage/constants/PlayerAction.java b/Mage/src/main/java/mage/constants/PlayerAction.java index c21bf05d458..cbff2a13840 100644 --- a/Mage/src/main/java/mage/constants/PlayerAction.java +++ b/Mage/src/main/java/mage/constants/PlayerAction.java @@ -82,5 +82,6 @@ public enum PlayerAction { CLIENT_DOWNLOAD_CARD_IMAGES, CLIENT_RECONNECT, CLIENT_REPLAY_ACTION, - + HOLD_PRIORITY, + UNHOLD_PRIORITY } From 3ca28d2eb6e35e1c6d9328b85129baaf8e7e2a12 Mon Sep 17 00:00:00 2001 From: emerald000 Date: Fri, 1 Jul 2016 01:15:56 -0400 Subject: [PATCH 2/7] [EMN] Implemented Emerge. Added Elder Deep-Fiend. --- .../sets/eldritchmoon/ElderDeepFiend.java | 78 ++++++++++++ .../mage/abilities/keyword/EmergeAbility.java | 116 ++++++++++++++++++ 2 files changed, 194 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/eldritchmoon/ElderDeepFiend.java create mode 100644 Mage/src/main/java/mage/abilities/keyword/EmergeAbility.java diff --git a/Mage.Sets/src/mage/sets/eldritchmoon/ElderDeepFiend.java b/Mage.Sets/src/mage/sets/eldritchmoon/ElderDeepFiend.java new file mode 100644 index 00000000000..53c665fa8ad --- /dev/null +++ b/Mage.Sets/src/mage/sets/eldritchmoon/ElderDeepFiend.java @@ -0,0 +1,78 @@ +/* + * 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.eldritchmoon; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CastSourceTriggeredAbility; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.keyword.EmergeAbility; +import mage.abilities.keyword.FlashAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; +import mage.filter.FilterPermanent; +import mage.target.TargetPermanent; + +/** + * + * @author emerald000 + */ +public class ElderDeepFiend extends CardImpl { + + public ElderDeepFiend(UUID ownerId) { + super(ownerId, 5, "Elder Deep-Fiend", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{8}"); + this.expansionSetCode = "EMN"; + this.subtype.add("Eldrazi"); + this.subtype.add("Octopus"); + this.power = new MageInt(5); + this.toughness = new MageInt(6); + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // Emerge {5}{U}{U} + this.addAbility(new EmergeAbility(this, new ManaCostsImpl<>("{5}{U}{U}"))); + + // When you cast Elder Deep-Fiend, tap up to four target permanents. + Ability ability = new CastSourceTriggeredAbility(new TapTargetEffect()); + ability.addTarget(new TargetPermanent(0, 4, new FilterPermanent("permanents to tap"), false)); + this.addAbility(ability); + } + + public ElderDeepFiend(final ElderDeepFiend card) { + super(card); + } + + @Override + public ElderDeepFiend copy() { + return new ElderDeepFiend(this); + } +} diff --git a/Mage/src/main/java/mage/abilities/keyword/EmergeAbility.java b/Mage/src/main/java/mage/abilities/keyword/EmergeAbility.java new file mode 100644 index 00000000000..40f610c362b --- /dev/null +++ b/Mage/src/main/java/mage/abilities/keyword/EmergeAbility.java @@ -0,0 +1,116 @@ +/* + * 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.abilities.keyword; + +import java.util.UUID; +import mage.abilities.SpellAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.mana.ManaCost; +import mage.abilities.costs.mana.ManaCosts; +import mage.cards.Card; +import mage.constants.Outcome; +import mage.constants.SpellAbilityType; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.CardIdPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.util.CardUtil; + +/** + * + * @author emerald000 + */ +public class EmergeAbility extends SpellAbility { + + private final ManaCosts emergeCost; + + public EmergeAbility(Card card, ManaCosts emergeCost) { + super(emergeCost, card.getName() + " with emerge", Zone.HAND, SpellAbilityType.BASE_ALTERNATE); + this.getCosts().addAll(card.getSpellAbility().getCosts().copy()); + this.getEffects().addAll(card.getSpellAbility().getEffects().copy()); + this.getTargets().addAll(card.getSpellAbility().getTargets().copy()); + this.timing = card.getSpellAbility().getTiming(); + this.setRuleAtTheTop(true); + this.emergeCost = emergeCost.copy(); + } + + public EmergeAbility(final EmergeAbility ability) { + super(ability); + this.emergeCost = ability.emergeCost.copy(); + } + + @Override + public boolean canActivate(UUID playerId, Game game) { + Player controller = game.getPlayer(this.getControllerId()); + if (controller != null) { + for (Permanent creature : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), this.getControllerId(), this.getSourceId(), game)) { + ManaCost costToPay = CardUtil.reduceCost(emergeCost.copy(), creature.getConvertedManaCost()); + if (costToPay.canPay(this, this.getSourceId(), this.getControllerId(), game)) { + return true; + } + } + } + return false; + } + + @Override + public boolean activate(Game game, boolean noMana) { + Player controller = game.getPlayer(this.getControllerId()); + if (controller != null) { + TargetPermanent target = new TargetControlledCreaturePermanent(new FilterControlledCreaturePermanent("creature to sacrifice for emerge")); + if (controller.choose(Outcome.Sacrifice, target, this.getSourceId(), game)) { + Permanent creature = game.getPermanent(target.getFirstTarget()); + CardUtil.reduceCost(this, creature.getConvertedManaCost()); + FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(creature.getLogName()); + filter.add(new CardIdPredicate(creature.getId())); + this.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(filter))); + return super.activate(game, false); + } + } + return false; + } + + @Override + public EmergeAbility copy() { + return new EmergeAbility(this); + } + + @Override + public String getRule(boolean all) { + return getRule(); + } + + @Override + public String getRule() { + return "Emerge " + emergeCost.getText() + " (You may cast this spell by sacrificing a creature and paying the emerge cost reduced by that creature's converted mana cost.)"; + } +} From 541e6a7f9b1aac6049a25564a05b99c86f666d27 Mon Sep 17 00:00:00 2001 From: Styxo <> Date: Fri, 1 Jul 2016 14:50:18 +0200 Subject: [PATCH 3/7] Added Earth Surge --- .../src/mage/sets/guildpact/EarthSurge.java | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/guildpact/EarthSurge.java diff --git a/Mage.Sets/src/mage/sets/guildpact/EarthSurge.java b/Mage.Sets/src/mage/sets/guildpact/EarthSurge.java new file mode 100644 index 00000000000..8406d44ee8d --- /dev/null +++ b/Mage.Sets/src/mage/sets/guildpact/EarthSurge.java @@ -0,0 +1,72 @@ +/* + * 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.guildpact; + +import java.util.UUID; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; + +/** + * + * @author Styxo + */ +public class EarthSurge extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("land creatures"); + + static { + filter.add(new CardTypePredicate(CardType.LAND)); + } + + public EarthSurge(UUID ownerId) { + super(ownerId, 84, "Earth Surge", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}"); + this.expansionSetCode = "GPT"; + + //Each land gets +2/+2 as long as it's a creature. + Effect effect = new BoostControlledEffect(2, 2, Duration.WhileOnBattlefield, filter, true); + effect.setText("Each land gets +2/+2 as long as it\'s a creature"); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + } + + public EarthSurge(final EarthSurge card) { + super(card); + } + + @Override + public EarthSurge copy() { + return new EarthSurge(this); + } +} From 3b0f7b074f2aa6ecb63fbcfb9604cf6d8e59b1f1 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 1 Jul 2016 15:08:40 +0200 Subject: [PATCH 4/7] * Some changes to distance calculation of enchantments on the battlefield. Added minimal permanet size preference setting (not working correctly yet). --- .../mage/client/dialog/PreferencesDialog.form | 541 +++++++++++++----- .../mage/client/dialog/PreferencesDialog.java | 193 ++++--- .../mage/client/game/BattlefieldPanel.java | 2 +- .../java/mage/client/util/GUISizeHelper.java | 9 +- .../layout/impl/OldCardLayoutStrategy.java | 14 +- .../org/mage/plugins/card/CardPluginImpl.java | 8 +- 6 files changed, 519 insertions(+), 248 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form index 87d1b0beb74..03ed4e96b4b 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form @@ -31,7 +31,7 @@ - + @@ -122,7 +122,7 @@ - + @@ -1719,7 +1719,7 @@ - + @@ -1744,11 +1744,11 @@ - + - - + + @@ -1756,6 +1756,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1902,7 +1939,7 @@ - + @@ -2409,11 +2446,11 @@ - - + + - + @@ -2504,11 +2541,11 @@ - - + + - + @@ -2536,7 +2573,7 @@ - + @@ -2549,7 +2586,7 @@ - + @@ -2601,11 +2638,11 @@ - - + + - + @@ -2633,7 +2670,7 @@ - + @@ -2646,7 +2683,7 @@ - + @@ -2696,11 +2733,11 @@ - - + + - + @@ -2728,7 +2765,7 @@ - + @@ -2793,11 +2830,11 @@ - - + + - + @@ -2825,7 +2862,7 @@ - + @@ -2888,11 +2925,11 @@ - - + + - + @@ -2920,7 +2957,7 @@ - + @@ -2985,11 +3022,11 @@ - - + + - + @@ -3017,7 +3054,7 @@ - + @@ -3080,7 +3117,199 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3088,7 +3317,7 @@ - + @@ -3096,7 +3325,7 @@ - + @@ -3105,16 +3334,16 @@ - + - + - + @@ -3124,12 +3353,12 @@ - + - + @@ -3139,12 +3368,12 @@ - + - + @@ -3154,12 +3383,12 @@ - + - + @@ -3169,7 +3398,7 @@ - + @@ -3181,11 +3410,11 @@ - + - + @@ -3194,16 +3423,16 @@ - + - + - + @@ -3211,12 +3440,12 @@ - + - + @@ -3224,12 +3453,12 @@ - + - + @@ -3237,12 +3466,12 @@ - + - + @@ -3250,17 +3479,17 @@ - + - + - + @@ -3269,16 +3498,16 @@ - + - + - + @@ -3286,12 +3515,12 @@ - + - + @@ -3299,12 +3528,12 @@ - + - + @@ -3312,12 +3541,12 @@ - + - + @@ -3325,13 +3554,13 @@ - + - + @@ -4172,7 +4401,7 @@ - + @@ -5028,9 +5257,9 @@ - + - + @@ -5039,7 +5268,7 @@ - + @@ -5047,7 +5276,7 @@ - + @@ -5061,6 +5290,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -5230,83 +5536,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java index ccc197fc18a..a949990fc88 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java @@ -104,7 +104,8 @@ public class PreferencesDialog extends javax.swing.JDialog { public static final String KEY_GUI_DIALOG_FONT_SIZE = "guiDialogFontSize"; public static final String KEY_GUI_FEEDBACK_AREA_SIZE = "guiFeedbackAreaSize"; public static final String KEY_GUI_CARD_OTHER_ZONES_SIZE = "guiCardOtherZonesSize"; - public static final String KEY_GUI_CARD_BATTLEFIELD_SIZE = "guiCardBattlefield"; + public static final String KEY_GUI_CARD_BATTLEFIELD_MIN_SIZE = "guiCardBattlefieldMinSize"; + public static final String KEY_GUI_CARD_BATTLEFIELD_MAX_SIZE = "guiCardBattlefieldMaxSize"; public static final String KEY_GAME_LOG_AUTO_SAVE = "gameLogAutoSave"; public static final String KEY_DRAFT_LOG_AUTO_SAVE = "draftLogAutoSave"; @@ -245,7 +246,6 @@ public class PreferencesDialog extends javax.swing.JDialog { public static final String KEY_NEW_DECK_GENERATOR_LAND_PERCENTAGE = "newDeckGeneratorLandPercentage"; public static final String KEY_NEW_DECK_GENERATOR_ADVANCED_CMC = "newDeckGeneratorAdvancedCMC"; - // used to save and restore the settings for the cardArea (draft, sideboarding, deck builder) public static final String KEY_DRAFT_VIEW = "draftView"; @@ -396,8 +396,10 @@ public class PreferencesDialog extends javax.swing.JDialog { labelCardSizeHand = new javax.swing.JLabel(); sliderCardSizeOtherZones = new javax.swing.JSlider(); labelCardSizeOtherZones = new javax.swing.JLabel(); - sliderCardSizeBattlefield = new javax.swing.JSlider(); - labelCardSizeBattlefield = new javax.swing.JLabel(); + sliderCardSizeMinBattlefield = new javax.swing.JSlider(); + labelCardSizeMinBattlefield = new javax.swing.JLabel(); + sliderCardSizeMaxBattlefield = new javax.swing.JSlider(); + labelCardSizeMaxBattlefield = new javax.swing.JLabel(); sliderStackWidth = new javax.swing.JSlider(); labelStackWidth = new javax.swing.JLabel(); sliderGameFeedbackArea = new javax.swing.JSlider(); @@ -495,6 +497,10 @@ public class PreferencesDialog extends javax.swing.JDialog { jPanel32 = new javax.swing.JPanel(); jPanel33 = new javax.swing.JPanel(); tabConnection = new javax.swing.JPanel(); + connection_servers = new javax.swing.JPanel(); + lblURLServerList = new javax.swing.JLabel(); + txtURLServerList = new javax.swing.JTextField(); + jLabel17 = new javax.swing.JLabel(); lblProxyType = new javax.swing.JLabel(); cbProxyType = new javax.swing.JComboBox<>(); pnlProxySettings = new javax.swing.JPanel(); @@ -509,10 +515,6 @@ public class PreferencesDialog extends javax.swing.JDialog { txtPasswordField = new javax.swing.JPasswordField(); rememberPswd = new javax.swing.JCheckBox(); jLabel11 = new javax.swing.JLabel(); - connection_servers = new javax.swing.JPanel(); - lblURLServerList = new javax.swing.JLabel(); - txtURLServerList = new javax.swing.JTextField(); - jLabel17 = new javax.swing.JLabel(); saveButton = new javax.swing.JButton(); exitButton = new javax.swing.JButton(); @@ -557,7 +559,7 @@ public class PreferencesDialog extends javax.swing.JDialog { .add(tooltipDelayLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 308, Short.MAX_VALUE) .add(org.jdesktop.layout.GroupLayout.LEADING, showCardName) .add(tooltipDelay, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addContainerGap(183, Short.MAX_VALUE)) + .addContainerGap(233, Short.MAX_VALUE)) ); main_cardLayout.setVerticalGroup( main_cardLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) @@ -917,7 +919,7 @@ public class PreferencesDialog extends javax.swing.JDialog { guiSizeGame.setMinimumSize(new java.awt.Dimension(600, 180)); guiSizeGame.setPreferredSize(new java.awt.Dimension(600, 180)); java.awt.GridBagLayout guiSizeGameLayout = new java.awt.GridBagLayout(); - guiSizeGameLayout.columnWeights = new double[] {1.0, 1.0, 1.0}; + guiSizeGameLayout.columnWeights = new double[] {1.0, 1.0, 1.0, 1.0}; guiSizeGameLayout.rowWeights = new double[] {1.0, 0.2, 1.0, 0.2}; guiSizeGame.setLayout(guiSizeGameLayout); @@ -980,34 +982,63 @@ public class PreferencesDialog extends javax.swing.JDialog { gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH; guiSizeGame.add(labelCardSizeOtherZones, gridBagConstraints); - sliderCardSizeBattlefield.setMajorTickSpacing(5); - sliderCardSizeBattlefield.setMaximum(50); - sliderCardSizeBattlefield.setMinimum(10); - sliderCardSizeBattlefield.setMinorTickSpacing(1); - sliderCardSizeBattlefield.setPaintLabels(true); - sliderCardSizeBattlefield.setPaintTicks(true); - sliderCardSizeBattlefield.setSnapToTicks(true); - sliderCardSizeBattlefield.setToolTipText("The maximum size of permanents on the battlefield"); - sliderCardSizeBattlefield.setBorder(javax.swing.BorderFactory.createEtchedBorder()); - sliderCardSizeBattlefield.setMinimumSize(new java.awt.Dimension(150, 40)); + sliderCardSizeMinBattlefield.setMajorTickSpacing(5); + sliderCardSizeMinBattlefield.setMaximum(50); + sliderCardSizeMinBattlefield.setMinimum(10); + sliderCardSizeMinBattlefield.setMinorTickSpacing(1); + sliderCardSizeMinBattlefield.setPaintLabels(true); + sliderCardSizeMinBattlefield.setPaintTicks(true); + sliderCardSizeMinBattlefield.setSnapToTicks(true); + sliderCardSizeMinBattlefield.setToolTipText("The maximum size of permanents on the battlefield"); + sliderCardSizeMinBattlefield.setBorder(javax.swing.BorderFactory.createEtchedBorder()); + sliderCardSizeMinBattlefield.setMinimumSize(new java.awt.Dimension(150, 40)); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 2; gridBagConstraints.gridy = 0; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH; gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2); - guiSizeGame.add(sliderCardSizeBattlefield, gridBagConstraints); + guiSizeGame.add(sliderCardSizeMinBattlefield, gridBagConstraints); - labelCardSizeBattlefield.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); - labelCardSizeBattlefield.setText("Permanents"); - labelCardSizeBattlefield.setToolTipText("The maximum size of permanents on the battlefield"); + labelCardSizeMinBattlefield.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + labelCardSizeMinBattlefield.setText("Permanents min size"); + labelCardSizeMinBattlefield.setToolTipText("The minimum size of permanents on the battlefield"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 2; gridBagConstraints.gridy = 1; gridBagConstraints.ipadx = 3; gridBagConstraints.ipady = 3; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH; - guiSizeGame.add(labelCardSizeBattlefield, gridBagConstraints); + guiSizeGame.add(labelCardSizeMinBattlefield, gridBagConstraints); + + sliderCardSizeMaxBattlefield.setMajorTickSpacing(5); + sliderCardSizeMaxBattlefield.setMaximum(50); + sliderCardSizeMaxBattlefield.setMinimum(10); + sliderCardSizeMaxBattlefield.setMinorTickSpacing(1); + sliderCardSizeMaxBattlefield.setPaintLabels(true); + sliderCardSizeMaxBattlefield.setPaintTicks(true); + sliderCardSizeMaxBattlefield.setSnapToTicks(true); + sliderCardSizeMaxBattlefield.setToolTipText("The maximum size of permanents on the battlefield"); + sliderCardSizeMaxBattlefield.setBorder(javax.swing.BorderFactory.createEtchedBorder()); + sliderCardSizeMaxBattlefield.setMinimumSize(new java.awt.Dimension(150, 40)); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 3; + gridBagConstraints.gridy = 0; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH; + gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2); + guiSizeGame.add(sliderCardSizeMaxBattlefield, gridBagConstraints); + + labelCardSizeMaxBattlefield.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + labelCardSizeMaxBattlefield.setText("Permanents max size"); + labelCardSizeMaxBattlefield.setToolTipText("The maximum size of permanents on the battlefield"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 3; + gridBagConstraints.gridy = 1; + gridBagConstraints.ipadx = 3; + gridBagConstraints.ipady = 3; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH; + guiSizeGame.add(labelCardSizeMaxBattlefield, gridBagConstraints); sliderStackWidth.setMajorTickSpacing(20); sliderStackWidth.setMaximum(90); @@ -2099,7 +2130,7 @@ public class PreferencesDialog extends javax.swing.JDialog { tabAvatarsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(tabAvatarsLayout.createSequentialGroup() .add(avatarPane, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 528, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) - .add(0, 1, Short.MAX_VALUE)) + .add(0, 0, Short.MAX_VALUE)) ); tabAvatarsLayout.setVerticalGroup( tabAvatarsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) @@ -2110,6 +2141,47 @@ public class PreferencesDialog extends javax.swing.JDialog { tabsPanel.addTab("Avatars", tabAvatars); + connection_servers.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Servers")); + + lblURLServerList.setHorizontalAlignment(javax.swing.SwingConstants.LEFT); + lblURLServerList.setText("URL server list:"); + lblURLServerList.setToolTipText(""); + lblURLServerList.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING); + lblURLServerList.setPreferredSize(new java.awt.Dimension(110, 16)); + lblURLServerList.setVerticalTextPosition(javax.swing.SwingConstants.TOP); + + txtURLServerList.setToolTipText("The URL XMage tries to read a server list from."); + txtURLServerList.setPreferredSize(new java.awt.Dimension(300, 22)); + + jLabel17.setFont(new java.awt.Font("Tahoma", 2, 10)); // NOI18N + jLabel17.setText("e.g.: http://XMage.de/files/server-list.txt"); + + org.jdesktop.layout.GroupLayout connection_serversLayout = new org.jdesktop.layout.GroupLayout(connection_servers); + connection_servers.setLayout(connection_serversLayout); + connection_serversLayout.setHorizontalGroup( + connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(connection_serversLayout.createSequentialGroup() + .add(connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(connection_serversLayout.createSequentialGroup() + .addContainerGap() + .add(lblURLServerList, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 96, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(txtURLServerList, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 370, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) + .add(connection_serversLayout.createSequentialGroup() + .add(141, 141, 141) + .add(jLabel17))) + .addContainerGap(67, Short.MAX_VALUE)) + ); + connection_serversLayout.setVerticalGroup( + connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(connection_serversLayout.createSequentialGroup() + .add(connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false) + .add(lblURLServerList, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .add(txtURLServerList, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(jLabel17)) + ); + lblProxyType.setText("Proxy:"); cbProxyType.addActionListener(new java.awt.event.ActionListener() { @@ -2219,67 +2291,26 @@ public class PreferencesDialog extends javax.swing.JDialog { .addContainerGap()) ); - connection_servers.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Servers")); - - lblURLServerList.setHorizontalAlignment(javax.swing.SwingConstants.LEFT); - lblURLServerList.setText("URL server list:"); - lblURLServerList.setToolTipText(""); - lblURLServerList.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING); - lblURLServerList.setPreferredSize(new java.awt.Dimension(110, 16)); - lblURLServerList.setVerticalTextPosition(javax.swing.SwingConstants.TOP); - - txtURLServerList.setToolTipText("The URL XMage tries to read a server list from."); - txtURLServerList.setPreferredSize(new java.awt.Dimension(300, 22)); - - jLabel17.setFont(new java.awt.Font("Tahoma", 2, 10)); // NOI18N - jLabel17.setText("e.g.: http://XMage.de/files/server-list.txt"); - - org.jdesktop.layout.GroupLayout connection_serversLayout = new org.jdesktop.layout.GroupLayout(connection_servers); - connection_servers.setLayout(connection_serversLayout); - connection_serversLayout.setHorizontalGroup( - connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) - .add(connection_serversLayout.createSequentialGroup() - .add(connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) - .add(connection_serversLayout.createSequentialGroup() - .addContainerGap() - .add(lblURLServerList, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 96, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) - .add(txtURLServerList, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 370, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) - .add(connection_serversLayout.createSequentialGroup() - .add(141, 141, 141) - .add(jLabel17))) - .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - ); - connection_serversLayout.setVerticalGroup( - connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) - .add(connection_serversLayout.createSequentialGroup() - .add(connection_serversLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false) - .add(lblURLServerList, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .add(txtURLServerList, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) - .add(jLabel17)) - ); - org.jdesktop.layout.GroupLayout tabConnectionLayout = new org.jdesktop.layout.GroupLayout(tabConnection); tabConnection.setLayout(tabConnectionLayout); tabConnectionLayout.setHorizontalGroup( tabConnectionLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) - .add(tabConnectionLayout.createSequentialGroup() + .add(org.jdesktop.layout.GroupLayout.TRAILING, tabConnectionLayout.createSequentialGroup() .addContainerGap() - .add(tabConnectionLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false) + .add(tabConnectionLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING) .add(pnlProxySettings, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .add(org.jdesktop.layout.GroupLayout.LEADING, tabConnectionLayout.createSequentialGroup() .add(lblProxyType) .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED) .add(cbProxyType, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 126, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) .add(connection_servers, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()) ); tabConnectionLayout.setVerticalGroup( tabConnectionLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(tabConnectionLayout.createSequentialGroup() .addContainerGap() - .add(connection_servers, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .add(connection_servers, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(tabConnectionLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(lblProxyType) @@ -2325,7 +2356,7 @@ public class PreferencesDialog extends javax.swing.JDialog { .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(exitButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 100, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .add(6, 6, 6)) - .add(tabsPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 535, Short.MAX_VALUE) + .add(tabsPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 584, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) @@ -2399,8 +2430,12 @@ public class PreferencesDialog extends javax.swing.JDialog { save(prefs, dialog.sliderCardSizeOtherZones, KEY_GUI_CARD_OTHER_ZONES_SIZE, "true", "false", UPDATE_CACHE_POLICY); sizeGUIChanged = true; } - if (getCachedValue(KEY_GUI_CARD_BATTLEFIELD_SIZE, 14) != dialog.sliderCardSizeBattlefield.getValue()) { - save(prefs, dialog.sliderCardSizeBattlefield, KEY_GUI_CARD_BATTLEFIELD_SIZE, "true", "false", UPDATE_CACHE_POLICY); + if (getCachedValue(KEY_GUI_CARD_BATTLEFIELD_MIN_SIZE, 10) != dialog.sliderCardSizeMaxBattlefield.getValue()) { + save(prefs, dialog.sliderCardSizeMinBattlefield, KEY_GUI_CARD_BATTLEFIELD_MIN_SIZE, "true", "false", UPDATE_CACHE_POLICY); + sizeGUIChanged = true; + } + if (getCachedValue(KEY_GUI_CARD_BATTLEFIELD_MAX_SIZE, 14) != dialog.sliderCardSizeMaxBattlefield.getValue()) { + save(prefs, dialog.sliderCardSizeMaxBattlefield, KEY_GUI_CARD_BATTLEFIELD_MAX_SIZE, "true", "false", UPDATE_CACHE_POLICY); sizeGUIChanged = true; } if (sizeGUIChanged) { @@ -2892,7 +2927,8 @@ public class PreferencesDialog extends javax.swing.JDialog { load(prefs, dialog.sliderTooltipSize, KEY_GUI_TOOLTIP_SIZE, "14"); load(prefs, dialog.sliderGameFeedbackArea, KEY_GUI_FEEDBACK_AREA_SIZE, "14"); load(prefs, dialog.sliderCardSizeOtherZones, KEY_GUI_CARD_OTHER_ZONES_SIZE, "14"); - load(prefs, dialog.sliderCardSizeBattlefield, KEY_GUI_CARD_BATTLEFIELD_SIZE, "14"); + load(prefs, dialog.sliderCardSizeMinBattlefield, KEY_GUI_CARD_BATTLEFIELD_MIN_SIZE, "10"); + load(prefs, dialog.sliderCardSizeMaxBattlefield, KEY_GUI_CARD_BATTLEFIELD_MAX_SIZE, "14"); } private static void loadImagesSettings(Preferences prefs) { @@ -3278,7 +3314,6 @@ public class PreferencesDialog extends javax.swing.JDialog { PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PASS_PRIORITY_ACTIVATION, "true").equals("true"), PreferencesDialog.getCachedValue(PreferencesDialog.KEY_AUTO_ORDER_TRIGGER, "true").equals("true"), PreferencesDialog.getCachedValue(PreferencesDialog.KEY_USE_FIRST_MANA_ABILITY, "false").equals("true") - ); } @@ -3374,8 +3409,9 @@ public class PreferencesDialog extends javax.swing.JDialog { private javax.swing.JPanel jPanel31; private javax.swing.JPanel jPanel32; private javax.swing.JPanel jPanel33; - private javax.swing.JLabel labelCardSizeBattlefield; private javax.swing.JLabel labelCardSizeHand; + private javax.swing.JLabel labelCardSizeMaxBattlefield; + private javax.swing.JLabel labelCardSizeMinBattlefield; private javax.swing.JLabel labelCardSizeOtherZones; private javax.swing.JLabel labelDialogFont; private javax.swing.JLabel labelEditorCardOffset; @@ -3404,8 +3440,9 @@ public class PreferencesDialog extends javax.swing.JDialog { private javax.swing.JCheckBox showAbilityPickerForced; private javax.swing.JCheckBox showCardName; private javax.swing.JCheckBox showPlayerNamesPermanently; - private javax.swing.JSlider sliderCardSizeBattlefield; private javax.swing.JSlider sliderCardSizeHand; + private javax.swing.JSlider sliderCardSizeMaxBattlefield; + private javax.swing.JSlider sliderCardSizeMinBattlefield; private javax.swing.JSlider sliderCardSizeOtherZones; private javax.swing.JSlider sliderChatFontSize; private javax.swing.JSlider sliderDialogFont; diff --git a/Mage.Client/src/main/java/mage/client/game/BattlefieldPanel.java b/Mage.Client/src/main/java/mage/client/game/BattlefieldPanel.java index 14659169f15..e23e22887e0 100644 --- a/Mage.Client/src/main/java/mage/client/game/BattlefieldPanel.java +++ b/Mage.Client/src/main/java/mage/client/game/BattlefieldPanel.java @@ -128,7 +128,7 @@ public class BattlefieldPanel extends javax.swing.JLayeredPane { private void setGUISize() { jScrollPane.getVerticalScrollBar().setPreferredSize(new Dimension(GUISizeHelper.scrollBarSize, 0)); jScrollPane.getHorizontalScrollBar().setPreferredSize(new Dimension(0, GUISizeHelper.scrollBarSize)); - cardDimension = GUISizeHelper.battlefieldCardDimension; + cardDimension = GUISizeHelper.battlefieldCardMaxDimension; } public void update(Map battlefield) { diff --git a/Mage.Client/src/main/java/mage/client/util/GUISizeHelper.java b/Mage.Client/src/main/java/mage/client/util/GUISizeHelper.java index 688a3b5dc1a..b41a55944ab 100644 --- a/Mage.Client/src/main/java/mage/client/util/GUISizeHelper.java +++ b/Mage.Client/src/main/java/mage/client/util/GUISizeHelper.java @@ -69,7 +69,8 @@ public class GUISizeHelper { public static Dimension otherZonesCardDimension; public static int otherZonesCardVerticalOffset; - public static Dimension battlefieldCardDimension; + public static Dimension battlefieldCardMinDimension; + public static Dimension battlefieldCardMaxDimension; public static Dimension editorCardDimension; public static int editorCardOffsetSize; @@ -144,8 +145,10 @@ public class GUISizeHelper { otherZonesCardVerticalOffset = otherZonesCardDimension.height / 10; } - int battlefieldCardSize = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GUI_CARD_BATTLEFIELD_SIZE, 14); - battlefieldCardDimension = new Dimension(CARD_IMAGE_WIDTH * battlefieldCardSize / 42, CARD_IMAGE_HEIGHT * battlefieldCardSize / 42); + int battlefieldCardMinSize = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GUI_CARD_BATTLEFIELD_MIN_SIZE, 10); + battlefieldCardMinDimension = new Dimension(CARD_IMAGE_WIDTH * battlefieldCardMinSize / 42, CARD_IMAGE_HEIGHT * battlefieldCardMinSize / 42); + int battlefieldCardMaxSize = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GUI_CARD_BATTLEFIELD_MAX_SIZE, 14); + battlefieldCardMaxDimension = new Dimension(CARD_IMAGE_WIDTH * battlefieldCardMaxSize / 42, CARD_IMAGE_HEIGHT * battlefieldCardMaxSize / 42); int editorCardSize = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GUI_CARD_EDITOR_SIZE, 14); editorCardDimension = new Dimension(CARD_IMAGE_WIDTH * editorCardSize / 42, CARD_IMAGE_HEIGHT * editorCardSize / 42); diff --git a/Mage.Client/src/main/java/mage/client/util/layout/impl/OldCardLayoutStrategy.java b/Mage.Client/src/main/java/mage/client/util/layout/impl/OldCardLayoutStrategy.java index 47cd0d30e87..517bab9508c 100644 --- a/Mage.Client/src/main/java/mage/client/util/layout/impl/OldCardLayoutStrategy.java +++ b/Mage.Client/src/main/java/mage/client/util/layout/impl/OldCardLayoutStrategy.java @@ -23,13 +23,12 @@ public class OldCardLayoutStrategy implements CardLayoutStrategy { /** * This offset is used once to shift all attachments */ - private static final int ATTACHMENTS_DX_OFFSET = 11; + private static final int ATTACHMENTS_MIN_DX_OFFSET = 12; /** * This offset is used for each attachment */ - private static final int ATTACHMENT_DX_OFFSET = 0; - private static final int ATTACHMENT_DY_OFFSET = 11; + private static final int ATTACHMENT_MIN_DY_OFFSET = 12; @Override public void doLayout(JLayeredPane jLayeredPane, int width) { @@ -56,7 +55,7 @@ public class OldCardLayoutStrategy implements CardLayoutStrategy { perm.getLinks().clear(); Rectangle rectangleBaseCard = perm.getBounds(); if (!Plugins.getInstance().isCardPluginLoaded()) { - for (UUID attachmentId: permanent.getAttachments()) { + for (UUID attachmentId : permanent.getAttachments()) { MagePermanent link = permanents.get(attachmentId); if (link != null) { perm.getLinks().add(link); @@ -67,15 +66,16 @@ public class OldCardLayoutStrategy implements CardLayoutStrategy { } } else { int index = permanent.getAttachments().size(); - for (UUID attachmentId: permanent.getAttachments()) { + for (UUID attachmentId : permanent.getAttachments()) { MagePermanent link = permanents.get(attachmentId); if (link != null) { link.setBounds(rectangleBaseCard); perm.getLinks().add(link); + int dyOffset = Math.max(perm.getHeight() / 10, ATTACHMENT_MIN_DY_OFFSET); if (index == 1) { - rectangleBaseCard.translate(ATTACHMENTS_DX_OFFSET, ATTACHMENT_DY_OFFSET); // do it once + rectangleBaseCard.translate(Math.max(perm.getWidth() / 10, ATTACHMENTS_MIN_DX_OFFSET), dyOffset); // do it once } else { - rectangleBaseCard.translate(ATTACHMENT_DX_OFFSET, ATTACHMENT_DY_OFFSET); + rectangleBaseCard.translate(0, dyOffset); } perm.setBounds(rectangleBaseCard); jLayeredPane.moveToFront(link); diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java b/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java index 99d5a8acf06..7a9f4950db9 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/CardPluginImpl.java @@ -67,7 +67,8 @@ public class CardPluginImpl implements CardPlugin { private int landStackMax = 5; // private int cardWidthMin = 50, cardWidthMax = Constants.CARD_SIZE_FULL.width; - private int cardWidthMin = 50, cardWidthMax = (int) GUISizeHelper.battlefieldCardDimension.getWidth(); + private int cardWidthMin = (int) GUISizeHelper.battlefieldCardMinDimension.getWidth(); + private int cardWidthMax = (int) GUISizeHelper.battlefieldCardMaxDimension.getWidth(); private boolean stackVertical = false; @@ -101,8 +102,8 @@ public class CardPluginImpl implements CardPlugin { } private void setGUISize() { - cardWidthMin = 50; - cardWidthMax = (int) GUISizeHelper.battlefieldCardDimension.getWidth(); + cardWidthMin = (int) GUISizeHelper.battlefieldCardMinDimension.getWidth(); + cardWidthMax = (int) GUISizeHelper.battlefieldCardMaxDimension.getWidth(); } @Override @@ -261,6 +262,7 @@ public class CardPluginImpl implements CardPlugin { } //FIXME: -1 is too slow. why not binary search? cardWidth -= 3; + } // Get size of all the rows. From b91b6402dcb12e9c1eaec681589bd37e2d92930d Mon Sep 17 00:00:00 2001 From: spjspj Date: Fri, 1 Jul 2016 23:59:47 +1000 Subject: [PATCH 5/7] spjspj - Implement Stitcher's Graft [EMN] and slight change to mtg-cards-data.txt --- .../sets/eldritchmoon/StitchersGraft.java | 119 ++++++++++++++++++ Utils/mtg-cards-data.txt | 2 +- 2 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 Mage.Sets/src/mage/sets/eldritchmoon/StitchersGraft.java diff --git a/Mage.Sets/src/mage/sets/eldritchmoon/StitchersGraft.java b/Mage.Sets/src/mage/sets/eldritchmoon/StitchersGraft.java new file mode 100644 index 00000000000..7c023fafd55 --- /dev/null +++ b/Mage.Sets/src/mage/sets/eldritchmoon/StitchersGraft.java @@ -0,0 +1,119 @@ +/* + * 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.eldritchmoon; + +import java.util.UUID; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.UnattachedTriggeredAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DontUntapInControllersNextUntapStepSourceEffect; +import mage.abilities.effects.common.SacrificeEquippedEffect; +import mage.abilities.effects.common.continuous.BoostEquippedEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EquipAbility; +import mage.cards.CardImpl; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent.EventType; +import mage.game.events.GameEvent; + +/** + * + * @author spjspj + */ +public class StitchersGraft extends CardImpl { + + public StitchersGraft(UUID ownerId) { + super(ownerId, 200, "Stitcher's Graft", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{1}"); + this.expansionSetCode = "EMN"; + this.subtype.add("Equipment"); + + // Equipped creature gets +3/+3. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(3, 3))); + + // Whenever equipped creature attacks, it doesn't untap during its controller's next untap step. + Effect effect = new GainAbilityAttachedEffect(new StitchersGraftTriggeredAbility(), AttachmentType.EQUIPMENT); + effect.setText("Equipped creature has \"Whenever equipped creature attacks, it doesn't untap during its controller's next untap step.\""); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + + // Whenever Stitcher's Graft becomes unequipped from a permanent, sacrifice that permanent. + this.addAbility(new UnattachedTriggeredAbility(new SacrificeEquippedEffect(), false)); + + // Equip {2} + this.addAbility(new EquipAbility(Outcome.AddAbility, new GenericManaCost(2))); + } + + public StitchersGraft(final StitchersGraft card) { + super(card); + } + + @Override + public StitchersGraft copy() { + return new StitchersGraft(this); + } +} + +class StitchersGraftTriggeredAbility extends TriggeredAbilityImpl { + + public StitchersGraftTriggeredAbility() { + super(Zone.BATTLEFIELD, new DontUntapInControllersNextUntapStepSourceEffect()); + } + + public StitchersGraftTriggeredAbility(final StitchersGraftTriggeredAbility ability) { + super(ability); + } + + @Override + public StitchersGraftTriggeredAbility copy() { + return new StitchersGraftTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.ATTACKER_DECLARED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED && event.getSourceId().equals(this.getSourceId())) { + return true; + } + return false; + } + + @Override + public String getRule() { + return "Whenever equipped creature attacks, it doesn't untap during its controller's next untap step"; + } +} diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 4f2c351c722..762e18cf80d 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -57364,6 +57364,6 @@ Cryptolith Fragment|Eldritch Moon|193|U|{3}|Artifact|||Cryptolith Fragment enter Aurora of Emrakul|Eldritch Moon|193|U||Creature - Eldrazi Reflection|1|4|Flying, deathtouch$Whenever Aurora of Emrakul attacks, each opponent loses 3 life.| Lupine Prototype|Eldritch Moon|197|R|{2}|Artifact Creature - Wolf Construct|5|5|Lupine Prototype can't attack or block unless a player has no cards in hand.| Soul Separator|Eldritch Moon|199|R|{3}|Artifact|||{5}, {T}, Sacrifice Soul Separator: Exile target creature card from your graveyard. Put a token onto the battlefield that's a copy of that card except it's 1/1, it's a Spirit in addition to its other types, and it has flying. Put a black Zombie creature token onto the battlefield with power equal to that card's power and toughness equal that card's toughness.| -Stitcher's Graft|Eldritch Moon|200|R|{1}|Artifact - Equipment|||Equipped creature gets +3/+3.$Whenever equipped creature attacks, it doesn't untap during its controller's next untap step.$Whenever Stitcher's Graft becomes unequipped from a creature, sacrifice that creature.$Equip {2}| +Stitcher's Graft|Eldritch Moon|200|R|{1}|Artifact - Equipment|||Equipped creature gets +3/+3.$Whenever equipped creature attacks, it doesn't untap during its controller's next untap step.$Whenever Stitcher's Graft becomes unattached from a permanent, sacrifice that permanent.$Equip {2}| Geier Reach Sanitarium|Eldritch Moon|203|R||Legendary Land|||{T}: Add {C} to your mana pool.${2}, {T}: Each player draws a card, then discards a card.| Hanweir Battlements|Eldritch Moon|204|R||Land|||{T}: Add {C} to your mana pool.${R},{T}: Target creature gains haste until end of turn.${3}{R}{R},{T}: If you both own and control Hanweir Battlements and a creature named Hanweir Garrison, exile them, then meld them into Hanweir, the Writhing Township.| \ No newline at end of file From dad0b3809ffc940aaf78e8060cabfc35b4f152e4 Mon Sep 17 00:00:00 2001 From: spjspj Date: Sat, 2 Jul 2016 00:03:50 +1000 Subject: [PATCH 6/7] spjspj - Implement Stitcher's Graft [EMN] --- Mage.Sets/src/mage/sets/eldritchmoon/StitchersGraft.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/eldritchmoon/StitchersGraft.java b/Mage.Sets/src/mage/sets/eldritchmoon/StitchersGraft.java index 7c023fafd55..65876b2e08f 100644 --- a/Mage.Sets/src/mage/sets/eldritchmoon/StitchersGraft.java +++ b/Mage.Sets/src/mage/sets/eldritchmoon/StitchersGraft.java @@ -67,7 +67,7 @@ public class StitchersGraft extends CardImpl { effect.setText("Equipped creature has \"Whenever equipped creature attacks, it doesn't untap during its controller's next untap step.\""); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); - // Whenever Stitcher's Graft becomes unequipped from a permanent, sacrifice that permanent. + // Whenever Stitcher's Graft becomes unattached from a permanent, sacrifice that permanent. this.addAbility(new UnattachedTriggeredAbility(new SacrificeEquippedEffect(), false)); // Equip {2} From a6094afa406071812be92fda1c50d03f2361251f Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 1 Jul 2016 17:04:42 +0200 Subject: [PATCH 7/7] * Worldheart Phoenix - Fixed that if cast from graveyard the counters were not added. --- .../src/mage/sets/modernmasters2015/WorldheartPhoenix.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/modernmasters2015/WorldheartPhoenix.java b/Mage.Sets/src/mage/sets/modernmasters2015/WorldheartPhoenix.java index 9961f8c2b6d..bd2b489c593 100644 --- a/Mage.Sets/src/mage/sets/modernmasters2015/WorldheartPhoenix.java +++ b/Mage.Sets/src/mage/sets/modernmasters2015/WorldheartPhoenix.java @@ -134,7 +134,7 @@ public class WorldheartPhoenix extends CardImpl { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); + Permanent permanent = game.getPermanentEntering(source.getSourceId()); if (permanent != null) { SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); if (spellAbility != null