diff --git a/Mage.Client/src/main/java/mage/client/game/FeedbackPanel.java b/Mage.Client/src/main/java/mage/client/game/FeedbackPanel.java index f246336bd6..778c6ae58c 100644 --- a/Mage.Client/src/main/java/mage/client/game/FeedbackPanel.java +++ b/Mage.Client/src/main/java/mage/client/game/FeedbackPanel.java @@ -47,6 +47,7 @@ import mage.client.components.MageTextArea; import mage.client.dialog.MageDialog; import mage.client.util.audio.AudioManager; import mage.client.util.gui.ArrowBuilder; +import mage.constants.Constants; import mage.constants.PlayerAction; import mage.remote.Session; import org.apache.log4j.Logger; @@ -140,14 +141,21 @@ public class FeedbackPanel extends javax.swing.JPanel { endWithTimeout(); break; } - this.btnSpecial.setVisible(special); - this.btnSpecial.setText("Special"); - this.helper.setSpecial("Special", special); - // Handling Phyrexian mana - if (message.contains("P}")) { + if (options != null && options.containsKey(Constants.Option.SPECIAL_BUTTON)) { + String specialText = (String) options.get(Constants.Option.SPECIAL_BUTTON); this.btnSpecial.setVisible(true); - this.btnSpecial.setText("Pay 2 life"); - this.helper.setSpecial("Pay 2 life", true); + this.btnSpecial.setText(specialText); + this.helper.setSpecial(specialText, true); + } else { + this.btnSpecial.setVisible(special); + this.btnSpecial.setText("Special"); + this.helper.setSpecial("Special", special); + // Handling Phyrexian mana + if (message.contains("P}")) { + this.btnSpecial.setVisible(true); + this.btnSpecial.setText("Pay 2 life"); + this.helper.setSpecial("Pay 2 life", true); + } } requestFocusIfPossible(); 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 fea201e9fa..85f08debe2 100644 --- a/Mage.Client/src/main/java/mage/client/game/GamePanel.java +++ b/Mage.Client/src/main/java/mage/client/game/GamePanel.java @@ -1020,6 +1020,9 @@ public final class GamePanel extends javax.swing.JPanel { } Map panelOptions = new HashMap<>(); + if (options != null) { + panelOptions.putAll(options); + } panelOptions.put("your_turn", true); String activePlayerText; if (gameView.getActivePlayerId().equals(playerId)) { diff --git a/Mage.Client/src/main/java/mage/client/game/HelperPanel.java b/Mage.Client/src/main/java/mage/client/game/HelperPanel.java index 6cba5bd8f0..829493e0e1 100644 --- a/Mage.Client/src/main/java/mage/client/game/HelperPanel.java +++ b/Mage.Client/src/main/java/mage/client/game/HelperPanel.java @@ -200,6 +200,7 @@ public class HelperPanel extends JPanel { } }); + // sets a darker background and higher simiss time fpr tooltip in the feedback / helper panel textArea.addMouseListener(new MouseAdapter() { @Override diff --git a/Mage.Common/src/mage/constants/Constants.java b/Mage.Common/src/mage/constants/Constants.java index a65e032cca..a5b586c63a 100644 --- a/Mage.Common/src/mage/constants/Constants.java +++ b/Mage.Common/src/mage/constants/Constants.java @@ -1,39 +1,38 @@ /* -* 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. -*/ - + * 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.constants; - /** * * @author BetaSteward_at_googlemail.com */ public final class Constants { + private Constants() { throw new AssertionError(); } @@ -74,13 +73,16 @@ public final class Constants { public static final int PRIORITY_TIME_SEC = 1200; public enum SessionState { + DISCONNECTED, CONNECTED, CONNECTING, DISCONNECTING, SERVER_STARTING; } public enum Option { + ; public static final String POSSIBLE_ATTACKERS = "possibleAttackers"; + public static final String SPECIAL_BUTTON = "specialButton"; } 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 9a7fd691cc..9bbd9fcb13 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 @@ -73,6 +73,7 @@ import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.combat.CombatGroup; import mage.game.draft.Draft; +import mage.game.events.GameEvent; import mage.game.match.Match; import mage.game.permanent.Permanent; import mage.game.tournament.Tournament; @@ -785,10 +786,29 @@ public class HumanPlayer extends PlayerImpl { } } options.put(Constants.Option.POSSIBLE_ATTACKERS, (Serializable) possibleAttackers); + if (possibleAttackers.size() > 0) { + options.put(Constants.Option.SPECIAL_BUTTON, (Serializable) "All attack"); + } game.fireSelectEvent(playerId, "Select attackers", options); waitForResponse(game); - if (response.getBoolean() != null) { + if (response.getString() != null && response.getString().equals("special")) { + setStoredBookmark(game.bookmarkState()); + UUID attackedDefender = null; + if (game.getCombat().getDefenders().size() > 1) { + attackedDefender = selectDefenderForAllAttack(game.getCombat().getDefenders(), game); + } else if (game.getCombat().getDefenders().size() == 1) { + attackedDefender = game.getCombat().getDefenders().iterator().next(); + } + for (Permanent attacker : game.getBattlefield().getAllActivePermanents(filterCreatureForCombat, getId(), game)) { + if (game.getContinuousEffects().checkIfThereArePayCostToAttackBlockEffects( + GameEvent.getEvent(GameEvent.EventType.DECLARE_ATTACKER, + attackedDefender, attacker.getId(), attacker.getControllerId()), game)) { + continue; + } + declareAttacker(attacker.getId(), attackedDefender, game, true); + } + } else if (response.getBoolean() != null) { // check if enough attackers are declared if (!game.getCombat().getCreaturesForcedToAttack().isEmpty()) { if (!game.getCombat().getAttackers().containsAll(game.getCombat().getCreaturesForcedToAttack().keySet())) { @@ -891,6 +911,15 @@ public class HumanPlayer extends PlayerImpl { return false; } + protected UUID selectDefenderForAllAttack(Set defenders, Game game) { + TargetDefender target = new TargetDefender(defenders, null); + target.setNotTarget(true); // player or planswalker hexproof does not prevent attacking a player + if (chooseTarget(Outcome.Damage, target, null, game)) { + response.getUUID(); + } + return null; + } + @Override public void selectBlockers(Game game, UUID defendingPlayerId) { updateGameStatePriority("selectBlockers", game);