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 afaf19627ed..b15bbcdd6aa 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.form @@ -82,8 +82,8 @@ - - + + @@ -159,7 +159,7 @@ - + @@ -173,7 +173,7 @@ - + @@ -231,7 +231,7 @@ - + @@ -381,8 +381,8 @@ - - + + @@ -528,8 +528,8 @@ - - + + @@ -537,7 +537,7 @@ - + @@ -628,7 +628,7 @@ - + @@ -675,6 +675,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 c7cbbb722c8..d655432110c 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java @@ -135,6 +135,9 @@ public class PreferencesDialog extends javax.swing.JDialog { public static final String KEY_STOP_BLOCK = "stopDeclareBlockersStep"; public static final String KEY_STOP_ALL_MAIN_PHASES = "stopOnAllMainPhases"; public static final String KEY_STOP_ALL_END_PHASES = "stopOnAllEndPhases"; + public static final String KEY_PASS_PRIORITY_CAST = "passPriorityCast"; + public static final String KEY_PASS_PRIORITY_ACTIVATION = "passPriorityActivation"; + public static final String KEY_AUTO_ORDER_TRIGGER = "autoOrderTrigger"; // mana auto payment public static final String KEY_GAME_MANA_AUTOPAYMENT = "gameManaAutopayment"; @@ -394,6 +397,9 @@ public class PreferencesDialog extends javax.swing.JDialog { cbStopBlock = new javax.swing.JCheckBox(); cbStopOnAllMain = new javax.swing.JCheckBox(); cbStopOnAllEnd = new javax.swing.JCheckBox(); + cbPassPriorityCast = new javax.swing.JCheckBox(); + cbPassPriorityActivation = new javax.swing.JCheckBox(); + cbAutoOrderTrigger = new javax.swing.JCheckBox(); tabImages = new javax.swing.JPanel(); panelCardImages = new javax.swing.JPanel(); cbUseDefaultImageFolder = new javax.swing.JCheckBox(); @@ -629,7 +635,7 @@ public class PreferencesDialog extends javax.swing.JDialog { .addComponent(cbConfirmEmptyManaPool) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(cbAskMoveToGraveOrder) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()) ); nonLandPermanentsInOnePile.getAccessibleContext().setAccessibleName("nonLandPermanentsInOnePile"); @@ -691,8 +697,8 @@ public class PreferencesDialog extends javax.swing.JDialog { .addContainerGap() .addComponent(main_card, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(main_game, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(main_game, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(main_gamelog, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addContainerGap()) ); @@ -701,7 +707,7 @@ public class PreferencesDialog extends javax.swing.JDialog { tabsPanel.addTab("Main", tabMain); - jLabelHeadLine.setText("Choose phases your game will stop on:"); + jLabelHeadLine.setText("Choose phases your game will stop on if not skipped by a skip action (e.g. F6):"); jLabelYourTurn.setText("Your turn"); @@ -722,7 +728,7 @@ public class PreferencesDialog extends javax.swing.JDialog { jLabelEndOfTurn.setText("End of turn:"); phases_stopSettings.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Stop settings")); - phases_stopSettings.setLayout(new java.awt.GridLayout(4, 1)); + phases_stopSettings.setLayout(new java.awt.GridLayout(7, 1)); cbStopAttack.setSelected(true); cbStopAttack.setText("Stop on declare attackers step if you skip steps (F4/F5/F7) and attackers are available"); @@ -766,6 +772,39 @@ public class PreferencesDialog extends javax.swing.JDialog { }); phases_stopSettings.add(cbStopOnAllEnd); + cbPassPriorityCast.setText("Pass priority automatically after you have put a spell on the stack"); + cbPassPriorityCast.setToolTipText("If activated the system passes priority automatically for you if you have put a spell on the stack."); + cbPassPriorityCast.setActionCommand(""); + cbPassPriorityCast.setPreferredSize(new java.awt.Dimension(300, 25)); + cbPassPriorityCast.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cbPassPriorityCastActionPerformed(evt); + } + }); + phases_stopSettings.add(cbPassPriorityCast); + + cbPassPriorityActivation.setText("Pass priority automatically after you have put an activated ability on the stack"); + cbPassPriorityActivation.setToolTipText("If activated the system passes priority for you automatically after you have put an activated ability on the stack."); + cbPassPriorityActivation.setActionCommand(""); + cbPassPriorityActivation.setPreferredSize(new java.awt.Dimension(300, 25)); + cbPassPriorityActivation.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cbPassPriorityActivationActionPerformed(evt); + } + }); + phases_stopSettings.add(cbPassPriorityActivation); + + cbAutoOrderTrigger.setText("Set order for your triggers automatically if all have the same text"); + cbAutoOrderTrigger.setToolTipText("If activated the order to put on the stack your triggers that trigger at the same time
\nis set automatically if all have the same text."); + cbAutoOrderTrigger.setActionCommand(""); + cbAutoOrderTrigger.setPreferredSize(new java.awt.Dimension(300, 25)); + cbAutoOrderTrigger.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cbAutoOrderTriggerActionPerformed(evt); + } + }); + phases_stopSettings.add(cbAutoOrderTrigger); + javax.swing.GroupLayout tabPhasesLayout = new javax.swing.GroupLayout(tabPhases); tabPhases.setLayout(tabPhasesLayout); tabPhasesLayout.setHorizontalGroup( @@ -876,11 +915,11 @@ public class PreferencesDialog extends javax.swing.JDialog { .addComponent(jLabelEndOfTurn) .addComponent(checkBoxEndTurnOthers)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(phases_stopSettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(45, Short.MAX_VALUE)) + .addComponent(phases_stopSettings, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addContainerGap()) ); - tabsPanel.addTab("Phases", tabPhases); + tabsPanel.addTab("Phases & Priority", tabPhases); panelCardImages.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), "Card images:")); @@ -1699,7 +1738,7 @@ public class PreferencesDialog extends javax.swing.JDialog { save(prefs, dialog.cbGameLogAutoSave, KEY_GAME_LOG_AUTO_SAVE, "true", "false", UPDATE_CACHE_POLICY); save(prefs, dialog.cbDraftLogAutoSave, KEY_DRAFT_LOG_AUTO_SAVE, "true", "false", UPDATE_CACHE_POLICY); - // Phases + // Phases & Priority save(prefs, dialog.checkBoxUpkeepYou, UPKEEP_YOU); save(prefs, dialog.checkBoxDrawYou, DRAW_YOU); save(prefs, dialog.checkBoxMainYou, MAIN_YOU); @@ -1720,6 +1759,9 @@ public class PreferencesDialog extends javax.swing.JDialog { save(prefs, dialog.cbStopBlock, KEY_STOP_BLOCK, "true", "false", UPDATE_CACHE_POLICY); save(prefs, dialog.cbStopOnAllMain, KEY_STOP_ALL_MAIN_PHASES, "true", "false", UPDATE_CACHE_POLICY); save(prefs, dialog.cbStopOnAllEnd, KEY_STOP_ALL_END_PHASES, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbPassPriorityCast, KEY_PASS_PRIORITY_CAST, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbPassPriorityActivation, KEY_PASS_PRIORITY_ACTIVATION, "true", "false", UPDATE_CACHE_POLICY); + save(prefs, dialog.cbAutoOrderTrigger, KEY_AUTO_ORDER_TRIGGER, "true", "false", UPDATE_CACHE_POLICY); // images save(prefs, dialog.cbUseDefaultImageFolder, KEY_CARD_IMAGES_USE_DEFAULT, "true", "false", UPDATE_CACHE_POLICY); @@ -2022,6 +2064,18 @@ public class PreferencesDialog extends javax.swing.JDialog { // TODO add your handling code here: }//GEN-LAST:event_cbDraftLogAutoSaveActionPerformed + private void cbPassPriorityCastActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbPassPriorityCastActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_cbPassPriorityCastActionPerformed + + private void cbPassPriorityActivationActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbPassPriorityActivationActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_cbPassPriorityActivationActionPerformed + + private void cbAutoOrderTriggerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbAutoOrderTriggerActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_cbAutoOrderTriggerActionPerformed + private void showProxySettings() { if (cbProxyType.getSelectedItem() == Connection.ProxyType.SOCKS) { this.pnlProxy.setVisible(true); @@ -2122,6 +2176,9 @@ public class PreferencesDialog extends javax.swing.JDialog { load(prefs, dialog.cbStopBlock, KEY_STOP_BLOCK, "true", "true"); load(prefs, dialog.cbStopOnAllMain, KEY_STOP_ALL_MAIN_PHASES, "true", "false"); load(prefs, dialog.cbStopOnAllEnd, KEY_STOP_ALL_END_PHASES, "true", "false"); + load(prefs, dialog.cbPassPriorityCast, KEY_PASS_PRIORITY_CAST, "true", "false"); + load(prefs, dialog.cbPassPriorityActivation, KEY_PASS_PRIORITY_ACTIVATION, "true", "false"); + load(prefs, dialog.cbAutoOrderTrigger, KEY_AUTO_ORDER_TRIGGER, "true", "true"); } @@ -2456,7 +2513,10 @@ public class PreferencesDialog extends javax.swing.JDialog { MageFrame.getPreferences().get(KEY_CONNECT_FLAG, "world"), PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_ASK_MOVE_TO_GRAVE_ORDER, "true").equals("true"), PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_MANA_AUTOPAYMENT, "true").equals("true"), - PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, "true").equals("true") + PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_MANA_AUTOPAYMENT_ONLY_ONE, "true").equals("true"), + PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PASS_PRIORITY_CAST, "true").equals("true"), + PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PASS_PRIORITY_ACTIVATION, "true").equals("true"), + PreferencesDialog.getCachedValue(PreferencesDialog.KEY_AUTO_ORDER_TRIGGER, "true").equals("true") ); } @@ -2469,6 +2529,7 @@ public class PreferencesDialog extends javax.swing.JDialog { private javax.swing.JButton btnBrowseImageLocation; private javax.swing.JCheckBox cbAllowRequestToShowHandCards; private javax.swing.JCheckBox cbAskMoveToGraveOrder; + private javax.swing.JCheckBox cbAutoOrderTrigger; private javax.swing.JCheckBox cbCheckForNewImages; private javax.swing.JCheckBox cbConfirmEmptyManaPool; private javax.swing.JCheckBox cbDraftLogAutoSave; @@ -2478,6 +2539,8 @@ public class PreferencesDialog extends javax.swing.JDialog { private javax.swing.JCheckBox cbEnableOtherSounds; private javax.swing.JCheckBox cbEnableSkipButtonsSounds; private javax.swing.JCheckBox cbGameLogAutoSave; + private javax.swing.JCheckBox cbPassPriorityActivation; + private javax.swing.JCheckBox cbPassPriorityCast; private javax.swing.JComboBox cbPreferedImageLanguage; private javax.swing.JComboBox cbProxyType; private javax.swing.JCheckBox cbSaveToZipFiles; 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 b628991865e..73fba0f4eae 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 @@ -562,6 +562,18 @@ public class HumanPlayer extends PlayerImpl { public boolean priority(Game game) { passed = false; if (!abort) { + if (getJustActivatedType() != null) { + if (userData.isPassPriorityCast() && getJustActivatedType().equals(AbilityType.SPELL)) { + setJustActivatedType(null); + pass(game); + return false; + } + if (userData.isPassPriorityActivation() && getJustActivatedType().equals(AbilityType.ACTIVATED)) { + setJustActivatedType(null); + pass(game); + return false; + } + } if (passedAllTurns) { if (passWithManaPoolCheck(game)) { return false; @@ -693,6 +705,8 @@ public class HumanPlayer extends PlayerImpl { @Override public TriggeredAbility chooseTriggeredAbility(List abilities, Game game) { + String autoOrderRuleText = null; + boolean autoOrderUse = getUserData().isAutoOrderTrigger(); while (!abort) { // try to set trigger auto order List abilitiesWithNoOrderSet = new ArrayList<>(); @@ -712,12 +726,19 @@ public class HumanPlayer extends PlayerImpl { abilityOrderLast = ability; continue; } + if (autoOrderUse) { + if (autoOrderRuleText == null) { + autoOrderRuleText = ability.getRule(); + } else if (!ability.getRule().equals(autoOrderRuleText)) { + autoOrderUse = false; + } + } abilitiesWithNoOrderSet.add(ability); } if (abilitiesWithNoOrderSet.isEmpty()) { return abilityOrderLast; } - if (abilitiesWithNoOrderSet.size() == 1) { + if (abilitiesWithNoOrderSet.size() == 1 || autoOrderUse) { return abilitiesWithNoOrderSet.iterator().next(); } updateGameStatePriority("chooseTriggeredAbility", game); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ManifestTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ManifestTest.java index f980b8be196..7c63a8447f1 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ManifestTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ManifestTest.java @@ -27,7 +27,6 @@ */ package org.mage.test.cards.abilities.keywords; - import mage.cards.Card; import mage.constants.PhaseStep; import mage.constants.Zone; @@ -39,7 +38,6 @@ import org.mage.test.serverside.base.CardTestPlayerBase; * * @author LevelX2 */ - public class ManifestTest extends CardTestPlayerBase { /** @@ -73,7 +71,8 @@ public class ManifestTest extends CardTestPlayerBase { } /** - * If Doomwake Giant gets manifested, it's Constellation trigger may not trigger + * If Doomwake Giant gets manifested, it's Constellation trigger may not + * trigger */ @Test public void testETBTriggeredAbilities2() { @@ -103,8 +102,10 @@ public class ManifestTest extends CardTestPlayerBase { assertPermanentCount(playerB, "Silvercoat Lion", 1); assertPowerToughness(playerB, "Silvercoat Lion", 2, 2); } + /** - * If Doomwake Giant gets manifested, it's Constellation trigger may not trigger + * If Doomwake Giant gets manifested, it's Constellation trigger may not + * trigger */ @Test public void testETBTriggeredAbilities3() { @@ -115,10 +116,10 @@ public class ManifestTest extends CardTestPlayerBase { // Constellation - When Doomwake Giant or another enchantment enters the battlefield // under your control, creatures your opponents control get -1/-1 until end of turn. addCard(Zone.LIBRARY, playerA, "Doomwake Giant"); - - addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox"); + + addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox"); addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); - + skipInitShuffling(); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Reality Shift", "Silvercoat Lion"); @@ -130,7 +131,7 @@ public class ManifestTest extends CardTestPlayerBase { assertLife(playerA, 20); assertLife(playerB, 20); assertGraveyardCount(playerB, "Reality Shift", 1); - assertExileCount("Silvercoat Lion" , 1); + assertExileCount("Silvercoat Lion", 1); // a facedown creature is on the battlefield assertPermanentCount(playerA, "", 1); assertPowerToughness(playerA, "", 2, 2); @@ -138,8 +139,10 @@ public class ManifestTest extends CardTestPlayerBase { assertPermanentCount(playerB, "Pillarfield Ox", 1); assertPowerToughness(playerB, "Pillarfield Ox", 2, 4); } + /** - * If Doomwake Giant gets manifested, it's Constellation trigger may not trigger + * If Doomwake Giant gets manifested, it's Constellation trigger may not + * trigger */ @Test public void testNylea() { @@ -150,7 +153,7 @@ public class ManifestTest extends CardTestPlayerBase { // As long as your devotion to white is less than five, Nylea isn't a creature. // (Each {G} in the mana costs of permanents you control counts towards your devotion to green.) addCard(Zone.LIBRARY, playerA, "Nylea, God of the Hunt"); - + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); skipInitShuffling(); @@ -164,17 +167,17 @@ public class ManifestTest extends CardTestPlayerBase { assertLife(playerA, 20); assertLife(playerB, 20); assertGraveyardCount(playerB, "Reality Shift", 1); - assertExileCount("Silvercoat Lion" , 1); + assertExileCount("Silvercoat Lion", 1); // a facedown creature is on the battlefield assertPermanentCount(playerA, "", 1); assertPowerToughness(playerA, "", 2, 2); } - + /* - Had a Foundry Street Denizen and another creature out. - Opponent Reality Shift'ed the other creature, manifested card was a red creature. This pumped the foundry street denizen even though it shouldn't. - */ + Had a Foundry Street Denizen and another creature out. + Opponent Reality Shift'ed the other creature, manifested card was a red creature. This pumped the foundry street denizen even though it shouldn't. + */ @Test public void testColorOfManifestedCardDoesNotCount() { addCard(Zone.BATTLEFIELD, playerB, "Island", 2); @@ -184,7 +187,7 @@ public class ManifestTest extends CardTestPlayerBase { // Gore Swine {2}{R} // 4/1 addCard(Zone.LIBRARY, playerA, "Gore Swine"); - + // Whenever another red creature enters the battlefield under your control, Foundry Street Denizen gets +1/+0 until end of turn. addCard(Zone.BATTLEFIELD, playerA, "Foundry Street Denizen"); addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); @@ -200,16 +203,17 @@ public class ManifestTest extends CardTestPlayerBase { assertLife(playerA, 20); assertLife(playerB, 20); assertGraveyardCount(playerB, "Reality Shift", 1); - assertExileCount("Silvercoat Lion" , 1); + assertExileCount("Silvercoat Lion", 1); // a facedown creature is on the battlefield assertPermanentCount(playerA, "", 1); assertPowerToughness(playerA, "", 2, 2); assertPowerToughness(playerA, "Foundry Street Denizen", 1, 1); - } + } /* - I casted a Silence the Believers on a manifested card. It moved to the exile zone face-down. - */ + I casted a Silence the Believers on a manifested card. It moved to the exile zone face-down. + */ + @Test public void testCardGetsExiledFaceUp() { addCard(Zone.BATTLEFIELD, playerB, "Island", 2); @@ -224,7 +228,7 @@ public class ManifestTest extends CardTestPlayerBase { // Gore Swine {2}{R} // 4/1 addCard(Zone.LIBRARY, playerA, "Gore Swine"); - + // Whenever another red creature enters the battlefield under your control, Foundry Street Denizen gets +1/+0 until end of turn. addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); @@ -240,12 +244,12 @@ public class ManifestTest extends CardTestPlayerBase { assertLife(playerA, 20); assertLife(playerB, 20); assertGraveyardCount(playerB, "Reality Shift", 1); - assertExileCount("Silvercoat Lion" , 1); - assertExileCount("Gore Swine" , 1); + assertExileCount("Silvercoat Lion", 1); + assertExileCount("Gore Swine", 1); // no facedown creature is on the battlefield assertPermanentCount(playerA, "", 0); - - for (Card card :currentGame.getExile().getAllCards(currentGame)){ + + for (Card card : currentGame.getExile().getAllCards(currentGame)) { if (card.getName().equals("Gore Swine")) { Assert.assertTrue("Gore Swine may not be face down in exile", !card.isFaceDown(currentGame)); } @@ -255,7 +259,6 @@ public class ManifestTest extends CardTestPlayerBase { // Qarsi High Priest went to manifest Illusory Gains, // but it made me choose a target for gains, then enchanted the card to that creature. - @Test public void testManifestAura() { @@ -282,15 +285,13 @@ public class ManifestTest extends CardTestPlayerBase { assertGraveyardCount(playerB, "Illusory Gains", 0); assertGraveyardCount(playerB, "Silvercoat Lion", 1); - // a facedown creature is on the battlefield assertPermanentCount(playerB, "", 1); } - // Check if a Megamorph card is manifested and truned by their megamorph ability + // Check if a Megamorph card is manifested and turned face up by their megamorph ability // it gets the +1/+1 counter. - @Test public void testManifestMegamorph() { @@ -300,6 +301,8 @@ public class ManifestTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerB, "Qarsi High Priest", 1); addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1); + // Reach (This creature can block creatures with flying.) + // Megamorph {5}{G} addCard(Zone.LIBRARY, playerB, "Aerie Bowmasters", 1); addCard(Zone.LIBRARY, playerB, "Mountain", 1); @@ -324,10 +327,11 @@ public class ManifestTest extends CardTestPlayerBase { assertPowerToughness(playerB, "Aerie Bowmasters", 4, 5); // 3/4 and the +1/+1 counter from Megamorph } - + /** - * When a Forest came manifested into play my Courser of Kruphix gained me a life. - * + * When a Forest came manifested into play my Courser of Kruphix gained me a + * life. + * */ @Test public void testManifestForest() { @@ -349,7 +353,6 @@ public class ManifestTest extends CardTestPlayerBase { activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{1}{B},{T}, Sacrifice another creature"); addTarget(playerB, "Silvercoat Lion"); - setStopAt(2, PhaseStep.END_TURN); execute(); @@ -361,41 +364,40 @@ public class ManifestTest extends CardTestPlayerBase { assertPermanentCount(playerB, "", 1); - } - - /** + } + + /** * Whisperwood Elemental - Its sacrifice ability doesn't work.. - * + * */ @Test public void testWhisperwoodElemental() { - addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); // Seismic Rupture deals 2 damage to each creature without flying. addCard(Zone.HAND, playerA, "Seismic Rupture", 1); - + // At the beginning of your end step, manifest the top card of your library. // Sacrifice Whisperwood Elemental: Until end of turn, face-up, nontoken creatures you control gain "When this creature dies, manifest the top card of your library." addCard(Zone.BATTLEFIELD, playerB, "Whisperwood Elemental", 1); addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 2); - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Sacrifice"); castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Seismic Rupture"); - + setStopAt(1, PhaseStep.END_TURN); execute(); // no life gain assertLife(playerA, 20); assertLife(playerB, 20); - + assertGraveyardCount(playerA, "Seismic Rupture", 1); assertGraveyardCount(playerB, "Whisperwood Elemental", 1); assertGraveyardCount(playerB, "Silvercoat Lion", 2); assertPermanentCount(playerB, "", 2); - } + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SoulbondKeywordTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SoulbondKeywordTest.java index 4a7dc293243..037de63e93d 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SoulbondKeywordTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SoulbondKeywordTest.java @@ -88,7 +88,8 @@ public class SoulbondKeywordTest extends CardTestPlayerBase { } /** - * Tests Soulbond effect disabling whenever Soulbond creature changes its controller + * Tests Soulbond effect disabling whenever Soulbond creature changes its + * controller */ @Test public void testChangeControllerForSoulbondCreature() { @@ -115,7 +116,8 @@ public class SoulbondKeywordTest extends CardTestPlayerBase { } /** - * Tests Soulbond effect disabling when paired creture changes its controller + * Tests Soulbond effect disabling when paired creture changes its + * controller */ @Test public void testChangeControllerForAnotherCreature() { @@ -141,8 +143,8 @@ public class SoulbondKeywordTest extends CardTestPlayerBase { } /** - * Tests Soulbond effect disabling when Soulbond creature changes its controller and then returns back. - * Effect should not be restored. + * Tests Soulbond effect disabling when Soulbond creature changes its + * controller and then returns back. Effect should not be restored. */ @Test public void testChangeControllerAndGettingBack() { @@ -166,7 +168,8 @@ public class SoulbondKeywordTest extends CardTestPlayerBase { } /** - * Tests that stealing creature will allow to use Soulbond ability on controller's creature + * Tests that stealing creature will allow to use Soulbond ability on + * controller's creature */ @Test public void testSoulbondWorksOnControllerSide() { @@ -243,7 +246,8 @@ public class SoulbondKeywordTest extends CardTestPlayerBase { } /** - * Tests that it is possible to animate land and pair it on next coming Soulbond creature + * Tests that it is possible to animate land and pair it on next coming + * Soulbond creature */ @Test public void testPairOnAnimatedLand() { @@ -263,7 +267,8 @@ public class SoulbondKeywordTest extends CardTestPlayerBase { } /** - * Tests no effect whether land was animated after Soulbond creature has entered the battlefield + * Tests no effect whether land was animated after Soulbond creature has + * entered the battlefield */ @Test public void testPairOnPostAnimatedLand() { @@ -302,7 +307,8 @@ public class SoulbondKeywordTest extends CardTestPlayerBase { } /** - * Tests that after loosing first pair it is possible to pair creature with another one + * Tests that after loosing first pair it is possible to pair creature with + * another one */ @Test public void testRebondOnNextCreature() { @@ -357,6 +363,8 @@ public class SoulbondKeywordTest extends CardTestPlayerBase { public void testExileAndReturnBack() { addCard(Zone.HAND, playerA, "Elite Vanguard"); addCard(Zone.HAND, playerA, "Cloudshift"); + // Soulbond (You may pair this creature with another unpaired creature when either enters the battlefield. They remain paired for as long as you control both of them.) + // As long as Trusted Forcemage is paired with another creature, each of those creatures gets +1/+1. addCard(Zone.BATTLEFIELD, playerA, "Trusted Forcemage"); addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); @@ -375,6 +383,6 @@ public class SoulbondKeywordTest extends CardTestPlayerBase { Permanent trustedForcemange = getPermanent("Trusted Forcemage", playerA.getId()); Permanent eliteVanguard = getPermanent("Elite Vanguard", playerA.getId()); Assert.assertEquals(trustedForcemange.getPairedCard(), null); - Assert.assertEquals(eliteVanguard.getPairedCard(),null); + Assert.assertEquals(eliteVanguard.getPairedCard(), null); } } diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java index c815c8f94c4..9526cb9bef0 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java @@ -53,6 +53,7 @@ import mage.cards.Card; import mage.cards.Cards; import mage.cards.decks.Deck; import mage.choices.Choice; +import mage.constants.AbilityType; import mage.constants.ManaType; import mage.constants.Outcome; import mage.constants.PhaseStep; @@ -803,6 +804,9 @@ public class TestPlayer implements Player { @Override public boolean chooseUse(Outcome outcome, MessageToClient message, Ability source, Game game) { + if (message.getMessage().equals("Scry 1?")) { + return false; + } if (!choices.isEmpty()) { if (choices.get(0).equals("No")) { choices.remove(0); @@ -813,7 +817,7 @@ public class TestPlayer implements Player { return true; } } - return true; + return computerPlayer.chooseUse(outcome, message, source, game); } @Override @@ -1822,6 +1826,16 @@ public class TestPlayer implements Player { return computerPlayer.getMatchPlayer(); } + @Override + public AbilityType getJustActivatedType() { + return computerPlayer.getJustActivatedType(); + } + + @Override + public void setJustActivatedType(AbilityType justActivatedType) { + computerPlayer.setJustActivatedType(justActivatedType); + } + @Override public void cleanUpOnMatchEnd() { computerPlayer.cleanUpOnMatchEnd(); diff --git a/Mage/src/mage/players/Player.java b/Mage/src/mage/players/Player.java index 094550b16f6..eb3d7d70b2c 100644 --- a/Mage/src/mage/players/Player.java +++ b/Mage/src/mage/players/Player.java @@ -52,6 +52,7 @@ import mage.cards.Card; import mage.cards.Cards; import mage.cards.decks.Deck; import mage.choices.Choice; +import mage.constants.AbilityType; import mage.constants.ManaType; import mage.constants.Outcome; import mage.constants.PlayerAction; @@ -192,6 +193,10 @@ public interface Player extends MageItem, Copyable { boolean getPassedAllTurns(); + AbilityType getJustActivatedType(); + + void setJustActivatedType(AbilityType abilityType); + boolean hasLost(); boolean hasWon(); diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index be796054a89..b121e9f269f 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -176,6 +176,7 @@ public abstract class PlayerImpl implements Player, Serializable { * and abilities in the stack and will pass them as well. */ protected boolean passedAllTurns; // F9 + protected AbilityType justActivatedType; // used to check if priority can be passed automatically protected int turns; protected int storedBookmark = -1; @@ -317,6 +318,7 @@ public abstract class PlayerImpl implements Player, Serializable { this.passedUntilStackResolved = player.passedUntilStackResolved; this.dateLastAddedToStack = player.dateLastAddedToStack; this.passedAllTurns = player.passedAllTurns; + this.justActivatedType = player.justActivatedType; this.priorityTimeLeft = player.getPriorityTimeLeft(); this.reachedNextTurnAfterLeaving = player.reachedNextTurnAfterLeaving; @@ -440,6 +442,7 @@ public abstract class PlayerImpl implements Player, Serializable { this.skippedAtLeastOnce = false; this.passedUntilStackResolved = false; this.passedAllTurns = false; + this.justActivatedType = null; this.canGainLife = true; this.canLoseLife = true; this.topCardRevealed = false; @@ -1130,7 +1133,11 @@ public abstract class PlayerImpl implements Player, Serializable { } //if player has taken an action then reset all player passed flags + justActivatedType = null; if (result) { + if (isHuman() && (ability.getAbilityType().equals(AbilityType.SPELL) || ability.getAbilityType().equals(AbilityType.ACTIVATED))) { + setJustActivatedType(ability.getAbilityType()); + } game.getPlayers().resetPassed(); } return result; @@ -3246,6 +3253,16 @@ public abstract class PlayerImpl implements Player, Serializable { return passedUntilStackResolved; } + @Override + public AbilityType getJustActivatedType() { + return justActivatedType; + } + + @Override + public void setJustActivatedType(AbilityType justActivatedType) { + this.justActivatedType = justActivatedType; + } + @Override public void revokePermissionToSeeHandCards() { usersAllowedToSeeHandCards.clear(); diff --git a/Mage/src/mage/players/net/UserData.java b/Mage/src/mage/players/net/UserData.java index cb405e34dff..0e6e4017334 100644 --- a/Mage/src/mage/players/net/UserData.java +++ b/Mage/src/mage/players/net/UserData.java @@ -19,10 +19,14 @@ public class UserData implements Serializable { protected boolean askMoveToGraveOrder; protected boolean manaPoolAutomatic; protected boolean manaPoolAutomaticRestricted; + protected boolean passPriorityCast; + protected boolean passPriorityActivation; + protected boolean autoOrderTrigger; public UserData(UserGroup userGroup, int avatarId, boolean showAbilityPickerForced, boolean allowRequestShowHandCards, boolean confirmEmptyManaPool, UserSkipPrioritySteps userSkipPrioritySteps, - String flagName, boolean askMoveToGraveOrder, boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted) { + String flagName, boolean askMoveToGraveOrder, boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted, + boolean passPriorityCast, boolean passPriorityActivation, boolean autoOrderTrigger) { this.groupId = userGroup.getGroupId(); this.avatarId = avatarId; this.showAbilityPickerForced = showAbilityPickerForced; @@ -33,6 +37,9 @@ public class UserData implements Serializable { this.askMoveToGraveOrder = askMoveToGraveOrder; this.manaPoolAutomatic = manaPoolAutomatic; this.manaPoolAutomaticRestricted = manaPoolAutomaticRestricted; + this.passPriorityCast = passPriorityCast; + this.passPriorityActivation = passPriorityActivation; + this.autoOrderTrigger = autoOrderTrigger; } public void update(UserData userData) { @@ -46,10 +53,13 @@ public class UserData implements Serializable { this.askMoveToGraveOrder = userData.askMoveToGraveOrder; this.manaPoolAutomatic = userData.manaPoolAutomatic; this.manaPoolAutomaticRestricted = userData.manaPoolAutomaticRestricted; + this.passPriorityCast = userData.passPriorityCast; + this.passPriorityActivation = userData.passPriorityActivation; + this.autoOrderTrigger = userData.autoOrderTrigger; } public static UserData getDefaultUserDataView() { - return new UserData(UserGroup.DEFAULT, 0, false, false, true, null, "world.png", false, true, true); + return new UserData(UserGroup.DEFAULT, 0, false, false, true, null, "world.png", false, true, true, false, false, false); } public void setGroupId(int groupId) { @@ -132,4 +142,28 @@ public class UserData implements Serializable { this.manaPoolAutomaticRestricted = manaPoolAutomaticRestricted; } + public boolean isPassPriorityCast() { + return passPriorityCast; + } + + public void setPassPriorityCast(boolean passPriorityCast) { + this.passPriorityCast = passPriorityCast; + } + + public boolean isPassPriorityActivation() { + return passPriorityActivation; + } + + public void setPassPriorityActivation(boolean passPriorityActivation) { + this.passPriorityActivation = passPriorityActivation; + } + + public boolean isAutoOrderTrigger() { + return autoOrderTrigger; + } + + public void setAutoOrderTrigger(boolean autoOrderTrigger) { + this.autoOrderTrigger = autoOrderTrigger; + } + } diff --git a/Mage/src/mage/watchers/common/SoulbondWatcher.java b/Mage/src/mage/watchers/common/SoulbondWatcher.java index 4806133c740..ffe63d93f6b 100644 --- a/Mage/src/mage/watchers/common/SoulbondWatcher.java +++ b/Mage/src/mage/watchers/common/SoulbondWatcher.java @@ -109,7 +109,7 @@ public class SoulbondWatcher extends Watcher { Cards cards = new CardsImpl(); cards.add(chosen); controller.lookAtCards("Soulbond", cards, game); - if (controller.chooseUse(Outcome.Benefit, "Use Soulbond for recent " + permanent.getLogName() + "?", null, game)) { + if (controller.chooseUse(Outcome.Benefit, "Use Soulbond for recent " + permanent.getLogName() + "?", SoulbondAbility.getInstance(), game)) { chosen.setPairedCard(permanent.getId()); permanent.setPairedCard(chosen.getId()); if (!game.isSimulation()) {