From 99834ec024cc3a1ae3fbef4e3173fbf5a085114b Mon Sep 17 00:00:00 2001 From: Agetian Date: Wed, 27 Sep 2017 14:40:48 +0000 Subject: [PATCH] - A somewhat more fine-grained and less spoiler-y option to order graveyards, now with three states (Never / With Relevant Cards / Always). git-svn-id: http://svn.slightlymagic.net/forge/trunk@35796 269b9781-a132-4a9b-9d4e-f004f1b56b58 --- .../java/forge/ai/PlayerControllerAi.java | 2 +- forge-game/src/main/java/forge/game/Game.java | 20 ++--------------- .../src/main/java/forge/game/GameAction.java | 4 ++-- .../ability/effects/ChangeZoneAllEffect.java | 2 +- .../ability/effects/DestroyAllEffect.java | 2 +- .../game/ability/effects/DestroyEffect.java | 4 ++-- .../forge/game/ability/effects/DigEffect.java | 2 +- .../game/ability/effects/DiscardEffect.java | 14 ++++++------ .../ability/effects/SacrificeAllEffect.java | 2 +- .../game/ability/effects/SacrificeEffect.java | 2 +- .../main/java/forge/game/player/Player.java | 2 +- .../home/settings/CSubmenuPreferences.java | 12 +++++++++- .../home/settings/VSubmenuPreferences.java | 10 ++++----- .../forge/screens/settings/SettingsPage.java | 9 +++++--- forge-gui/release-files/CHANGES.txt | 4 ++-- .../forge/player/PlayerControllerHuman.java | 22 +++++++++++++++---- .../java/forge/properties/ForgeConstants.java | 5 +++++ .../forge/properties/ForgePreferences.java | 2 +- 18 files changed, 68 insertions(+), 52 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java index f0d5667e..7c47adb0 100644 --- a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java +++ b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java @@ -296,7 +296,7 @@ public class PlayerControllerAi extends PlayerController { //TODO Add more logic for AI ordering here // In presence of Volrath's Shapeshifter in deck, try to place the best creature on top of the graveyard - if (destinationZone == ZoneType.Graveyard && game.isGraveyardOrdered()) { + if (destinationZone == ZoneType.Graveyard) { if (!CardLists.filter(game.getCardsInGame(), new Predicate() { @Override public boolean apply(Card card) { diff --git a/forge-game/src/main/java/forge/game/Game.java b/forge-game/src/main/java/forge/game/Game.java index eb9327df..5fb0246f 100644 --- a/forge-game/src/main/java/forge/game/Game.java +++ b/forge-game/src/main/java/forge/game/Game.java @@ -101,8 +101,6 @@ public class Game { private final GameView view; private final Tracker tracker = new Tracker(); - private Map orderedGraveyardMap = new HashMap<>(); - public Player getMonarch() { return monarch; } @@ -873,31 +871,17 @@ public class Game { //playerCache.clear(); } - public boolean isGraveyardOrdered() { - boolean ordered = false; - for (Player p : getPlayers()) { - ordered |= isGraveyardOrdered(p); - } - return ordered; - } - + // Does the player control any cards that care about the order of cards in the graveyard? public boolean isGraveyardOrdered(final Player p) { - if (orderedGraveyardMap.containsKey(p)) { - return orderedGraveyardMap.get(p); - } for (Card c : p.getAllCards()) { if (c.hasSVar("NeedsOrderedGraveyard")) { - orderedGraveyardMap.put(p, true); return true; - } - if (c.getStates().contains(CardStateName.OriginalText)) { + } else if (c.getStates().contains(CardStateName.OriginalText)) { if (c.getState(CardStateName.OriginalText).hasSVar("NeedsOrderedGraveyard")) { - orderedGraveyardMap.put(p, true); return true; } } } - orderedGraveyardMap.put(p, false); return false; } } diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index 4f86df29..5e0c1834 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -935,7 +935,7 @@ public class GameAction { setHoldCheckingStaticAbilities(true); if (noRegCreats != null) { - if (noRegCreats.size() > 1 && game.isGraveyardOrdered() && !orderedNoRegCreats) { + if (noRegCreats.size() > 1 && !orderedNoRegCreats) { noRegCreats = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, noRegCreats, ZoneType.Graveyard); orderedNoRegCreats = true; } @@ -944,7 +944,7 @@ public class GameAction { } } if (desCreats != null) { - if (desCreats.size() > 1 && game.isGraveyardOrdered() && !orderedDesCreats) { + if (desCreats.size() > 1 && !orderedDesCreats) { desCreats = CardLists.filter(desCreats, new Predicate() { @Override public boolean apply(Card card) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneAllEffect.java index aafb08bd..72028b7a 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneAllEffect.java @@ -132,7 +132,7 @@ public class ChangeZoneAllEffect extends SpellAbilityEffect { cards = (CardCollection) p.getController().orderMoveToZoneList(cards, destination); } - if (destination == ZoneType.Graveyard && game.isGraveyardOrdered()) { + if (destination == ZoneType.Graveyard) { cards = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, cards, ZoneType.Graveyard); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/DestroyAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DestroyAllEffect.java index 149cd0f5..7c786720 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DestroyAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DestroyAllEffect.java @@ -81,7 +81,7 @@ public class DestroyAllEffect extends SpellAbilityEffect { } }); - if (list.size() > 1 && game.isGraveyardOrdered()) { + if (list.size() > 1) { list = GameActionUtil.orderCardsByTheirOwners(game, list, ZoneType.Graveyard); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/DestroyEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DestroyEffect.java index e81fe612..44a39984 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DestroyEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DestroyEffect.java @@ -86,7 +86,7 @@ public class DestroyEffect extends SpellAbilityEffect { } } - if (tgtCards.size() > 1 && game.isGraveyardOrdered()) { + if (tgtCards.size() > 1) { tgtCards = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, tgtCards, ZoneType.Graveyard); } @@ -115,7 +115,7 @@ public class DestroyEffect extends SpellAbilityEffect { } } - if (untargetedCards.size() > 1 && game.isGraveyardOrdered()) { + if (untargetedCards.size() > 1) { untargetedCards = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, untargetedCards, ZoneType.Graveyard); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/DigEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DigEffect.java index 87e0f319..ccc516c4 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DigEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DigEffect.java @@ -339,7 +339,7 @@ public class DigEffect extends SpellAbilityEffect { // now, move the rest to destZone2 if (destZone2 == ZoneType.Library || destZone2 == ZoneType.PlanarDeck || destZone2 == ZoneType.SchemeDeck - || (destZone2 == ZoneType.Graveyard && game.isGraveyardOrdered())) { + || destZone2 == ZoneType.Graveyard) { CardCollection afterOrder = rest; if (sa.hasParam("RestRandomOrder")) { CardLists.shuffle(afterOrder); diff --git a/forge-game/src/main/java/forge/game/ability/effects/DiscardEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DiscardEffect.java index 885fc291..9346f58e 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DiscardEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DiscardEffect.java @@ -135,7 +135,7 @@ public class DiscardEffect extends SpellAbilityEffect { if (runDiscard) { CardCollectionView toDiscard = AbilityUtils.getDefinedCards(source, sa.getParam("DefinedCards"), sa); - if (toDiscard.size() > 1 && p.getGame().isGraveyardOrdered()) { + if (toDiscard.size() > 1) { toDiscard = GameActionUtil.orderCardsByTheirOwners(p.getGame(), toDiscard, ZoneType.Graveyard); } @@ -159,7 +159,7 @@ public class DiscardEffect extends SpellAbilityEffect { boolean shouldRemember = sa.hasParam("RememberDiscarded"); CardCollectionView toDiscard = new CardCollection(Lists.newArrayList(p.getCardsIn(ZoneType.Hand))); - if (toDiscard.size() > 1 && p.getGame().isGraveyardOrdered()) { + if (toDiscard.size() > 1) { toDiscard = GameActionUtil.orderCardsByTheirOwners(p.getGame(), toDiscard, ZoneType.Graveyard); } @@ -173,7 +173,7 @@ public class DiscardEffect extends SpellAbilityEffect { if (mode.equals("NotRemembered")) { CardCollectionView dPHand = CardLists.getValidCards(p.getCardsIn(ZoneType.Hand), "Card.IsNotRemembered", p, source); - if (dPHand.size() > 1 && p.getGame().isGraveyardOrdered()) { + if (dPHand.size() > 1) { dPHand = GameActionUtil.orderCardsByTheirOwners(p.getGame(), dPHand, ZoneType.Graveyard); } @@ -211,7 +211,7 @@ public class DiscardEffect extends SpellAbilityEffect { } CardCollectionView toDiscardView = toDiscard; - if (toDiscard.size() > 1 && p.getGame().isGraveyardOrdered()) { + if (toDiscard.size() > 1) { toDiscardView = GameActionUtil.orderCardsByTheirOwners(p.getGame(), toDiscard, ZoneType.Graveyard); } @@ -228,7 +228,7 @@ public class DiscardEffect extends SpellAbilityEffect { hand = CardLists.filter(hand, Presets.NON_TOKEN); CardCollectionView toDiscard = p.getController().chooseCardsToDiscardUnlessType(Math.min(numCards, numCardsInHand), hand, sa.getParam("UnlessType"), sa); - if (toDiscard.size() > 1 && p.getGame().isGraveyardOrdered()) { + if (toDiscard.size() > 1) { toDiscard = GameActionUtil.orderCardsByTheirOwners(p.getGame(), toDiscard, ZoneType.Graveyard); } @@ -254,7 +254,7 @@ public class DiscardEffect extends SpellAbilityEffect { CardCollectionView dPChHand = CardLists.getValidCards(dPHand, valid.split(","), source.getController(), source, sa); dPChHand = CardLists.filter(dPChHand, Presets.NON_TOKEN); - if (dPChHand.size() > 1 && p.getGame().isGraveyardOrdered()) { + if (dPChHand.size() > 1) { dPChHand = GameActionUtil.orderCardsByTheirOwners(p.getGame(), dPChHand, ZoneType.Graveyard); } @@ -293,7 +293,7 @@ public class DiscardEffect extends SpellAbilityEffect { CardCollectionView toBeDiscarded = validCards.isEmpty() ? null : chooser.getController().chooseCardsToDiscardFrom(p, sa, validCards, min, max); - if (toBeDiscarded.size() > 1 && p.getGame().isGraveyardOrdered()) { + if (toBeDiscarded.size() > 1) { toBeDiscarded = GameActionUtil.orderCardsByTheirOwners(p.getGame(), toBeDiscarded, ZoneType.Graveyard); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/SacrificeAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/SacrificeAllEffect.java index 45fdd9cc..f4a61ba9 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/SacrificeAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/SacrificeAllEffect.java @@ -59,7 +59,7 @@ public class SacrificeAllEffect extends SpellAbilityEffect { card.clearRemembered(); } - if (list.size() > 1 && game.isGraveyardOrdered()) { + if (list.size() > 1) { list = GameActionUtil.orderCardsByTheirOwners(game, list, ZoneType.Graveyard); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/SacrificeEffect.java b/forge-game/src/main/java/forge/game/ability/effects/SacrificeEffect.java index 32af45a1..cafc302b 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/SacrificeEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/SacrificeEffect.java @@ -129,7 +129,7 @@ public class SacrificeEffect extends SpellAbilityEffect { } } - if (choosenToSacrifice.size() > 1 && game.isGraveyardOrdered()) { + if (choosenToSacrifice.size() > 1) { choosenToSacrifice = GameActionUtil.orderCardsByTheirOwners(game, choosenToSacrifice, ZoneType.Graveyard); } diff --git a/forge-game/src/main/java/forge/game/player/Player.java b/forge-game/src/main/java/forge/game/player/Player.java index 26bf8ec9..fdb4914a 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -1564,7 +1564,7 @@ public class Player extends GameEntity implements Comparable { } CardCollectionView milledView = milled; - if (destination == ZoneType.Graveyard && milled.size() > 1 && game.isGraveyardOrdered()) { + if (destination == ZoneType.Graveyard && milled.size() > 1) { milledView = GameActionUtil.orderCardsByTheirOwners(game, milled, ZoneType.Graveyard); } diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java b/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java index 92919626..c2ef65af 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java @@ -120,7 +120,6 @@ public enum CSubmenuPreferences implements ICDoc { lstControls.add(Pair.of(view.getCbEscapeEndsTurn(), FPref.UI_ALLOW_ESC_TO_END_TURN)); lstControls.add(Pair.of(view.getCbDetailedPaymentDesc(), FPref.UI_DETAILED_SPELLDESC_IN_PROMPT)); lstControls.add(Pair.of(view.getCbPreselectPrevAbOrder(), FPref.UI_PRESELECT_PREVIOUS_ABILITY_ORDER)); - lstControls.add(Pair.of(view.getCbAllowOrderingGraveyard(), FPref.UI_ALLOW_ORDER_GRAVEYARD_WHEN_NEEDED)); lstControls.add(Pair.of(view.getCbShowStormCount(), FPref.UI_SHOW_STORM_COUNT_IN_PROMPT)); lstControls.add(Pair.of(view.getCbFilterLandsByColorId(), FPref.UI_FILTER_LANDS_BY_COLOR_IDENTITY)); @@ -197,6 +196,7 @@ public enum CSubmenuPreferences implements ICDoc { initializeAutoYieldModeComboBox(); initializeCounterDisplayTypeComboBox(); initializeCounterDisplayLocationComboBox(); + initializeGraveyardOrderingComboBox(); initializePlayerNameButton(); } @@ -343,6 +343,16 @@ public enum CSubmenuPreferences implements ICDoc { panel.setComboBox(comboBox, selectedItem); } + private void initializeGraveyardOrderingComboBox() { + final String[] elems = {ForgeConstants.GRAVEYARD_ORDERING_NEVER, ForgeConstants.GRAVEYARD_ORDERING_OWN_CARDS, + ForgeConstants.GRAVEYARD_ORDERING_ALWAYS}; + final FPref userSetting = FPref.UI_ALLOW_ORDER_GRAVEYARD_WHEN_NEEDED; + final FComboBoxPanel panel = this.view.getCbpGraveyardOrdering(); + final FComboBox comboBox = createComboBox(elems, userSetting); + final String selectedItem = this.prefs.getPref(userSetting); + panel.setComboBox(comboBox, selectedItem); + } + private void initializeCounterDisplayTypeComboBox() { final String[] elements = new String[ForgeConstants.CounterDisplayType.values().length]; diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java b/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java index af63ac34..ded58572 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/settings/VSubmenuPreferences.java @@ -87,7 +87,6 @@ public enum VSubmenuPreferences implements IVSubmenu { private final JCheckBox cbCompactPrompt = new OptionsCheckBox("Compact Prompt"); private final JCheckBox cbEscapeEndsTurn = new OptionsCheckBox("Use Escape Key to End Turn"); private final JCheckBox cbPreselectPrevAbOrder = new OptionsCheckBox("Preselect Last Order of Abilities"); - private final JCheckBox cbAllowOrderingGraveyard = new OptionsCheckBox("Allow Ordering Graveyard if Needed"); private final JCheckBox cbHideReminderText = new OptionsCheckBox("Hide Reminder Text"); private final JCheckBox cbOpenPacksIndiv = new OptionsCheckBox("Open Packs Individually"); private final JCheckBox cbTokensInSeparateRow = new OptionsCheckBox("Display Tokens in a Separate Row"); @@ -105,6 +104,7 @@ public enum VSubmenuPreferences implements IVSubmenu { private final FComboBoxPanel cbpAutoYieldMode = new FComboBoxPanel<>("Auto-Yield:"); private final FComboBoxPanel cbpCounterDisplayType = new FComboBoxPanel<>("Counter Display Type:"); private final FComboBoxPanel cbpCounterDisplayLocation = new FComboBoxPanel<>("Counter Display Location:"); + private final FComboBoxPanel cbpGraveyardOrdering = new FComboBoxPanel<>("Allow Ordering Cards Put in Graveyard:"); /** * Constructor. @@ -189,8 +189,8 @@ public enum VSubmenuPreferences implements IVSubmenu { pnlPrefs.add(cbPreselectPrevAbOrder, titleConstraints); pnlPrefs.add(new NoteLabel("When enabled, preselects the last defined simultaneous ability order in the ordering dialog."), descriptionConstraints); - pnlPrefs.add(cbAllowOrderingGraveyard, titleConstraints); - pnlPrefs.add(new NoteLabel("When enabled, allows to choose the order of cards going to graveyard when playing with cards for which it matters (for example, Volrath's Shapeshifter)."), descriptionConstraints); + pnlPrefs.add(cbpGraveyardOrdering, comboBoxConstraints); + pnlPrefs.add(new NoteLabel("Determines when to let the player choose the order of cards simultaneously put in graveyard (never, always, or only when playing with cards for which it matters, for example, Volrath's Shapeshifter)."), descriptionConstraints); pnlPrefs.add(cbpAutoYieldMode, comboBoxConstraints); pnlPrefs.add(new NoteLabel("Defines the granularity level of auto-yields (per unique ability or per unique card)."), descriptionConstraints); @@ -688,8 +688,8 @@ public enum VSubmenuPreferences implements IVSubmenu { return cbPreselectPrevAbOrder; } - public final JCheckBox getCbAllowOrderingGraveyard() { - return cbAllowOrderingGraveyard; + public final FComboBoxPanel getCbpGraveyardOrdering() { + return cbpGraveyardOrdering; } /** @return {@link forge.toolbox.FLabel} */ diff --git a/forge-gui-mobile/src/forge/screens/settings/SettingsPage.java b/forge-gui-mobile/src/forge/screens/settings/SettingsPage.java index e418b703..2f7b2302 100644 --- a/forge-gui-mobile/src/forge/screens/settings/SettingsPage.java +++ b/forge-gui-mobile/src/forge/screens/settings/SettingsPage.java @@ -133,9 +133,12 @@ public class SettingsPage extends TabPage { "Preselect Last Order of Abilities", "When enabled, preselects the last defined simultaneous ability order in the ordering dialog."), 1); - lstSettings.addItem(new BooleanSetting(FPref.UI_ALLOW_ORDER_GRAVEYARD_WHEN_NEEDED, - "Allow Ordering Graveyard if Needed", - "When enabled, allows to order cards going to graveyard when playing with cards for which it matters."), + lstSettings.addItem(new CustomSelectSetting(FPref.UI_ALLOW_ORDER_GRAVEYARD_WHEN_NEEDED, + "Allow Ordering Cards Put in Graveyard", + "Determines when to allow to order cards going to graveyard (never/always/only with relevant cards).", + new String[]{ + ForgeConstants.GRAVEYARD_ORDERING_NEVER, ForgeConstants.GRAVEYARD_ORDERING_OWN_CARDS, + ForgeConstants.GRAVEYARD_ORDERING_ALWAYS}), 1); lstSettings.addItem(new CustomSelectSetting(FPref.UI_AUTO_YIELD_MODE, "Auto-Yield", diff --git a/forge-gui/release-files/CHANGES.txt b/forge-gui/release-files/CHANGES.txt index d9e28922..c8deab52 100644 --- a/forge-gui/release-files/CHANGES.txt +++ b/forge-gui/release-files/CHANGES.txt @@ -1,8 +1,8 @@ - Ixalan - All 279 cards of the newly released Ixalan set are available in Forge. We've done our best to fix the issues that you reported with the cards in the pre-release version. If you still see anything wrong with the new cards, don't hesitate to report! -- Allow Ordering Graveyard if Needed (option) - -A new option is available in Forge that makes the game offer you to order the cards as they go into graveyard if, for example, several cards are destroyed, sacrificed or milled at the same time. When enabled, this option only takes effect in case there is at least one card in at least one player's library that cares about the order of cards in graveyard (currently the following cards are marked as caring about graveyard order: Nether Shadow, Spinning Darkness, Corpse Dance, Shallow Grave, Phyrexian Furnace, Krovikan Horror, Volrath's Shapeshifter, Ashen Ghoul, Phyrexian Grimoire, Nature's Kiss, Soldevi Digger, Guiding Spirit, Barrow Ghoul, Circling Vultures, Zombie Scavengers, Necratog, Mistmoon Griffin, Bone Dancer, Bosium Strip, Alms, Death Spark). Note that this option does not affect cards that reorder the graveyard as a part of their effect (Fossil Find). If this option is disabled, then no ordering is performed for cards like Volrath's Shapeshifter and the cards go into graveyards in whatever order the game automatically determines them to do so (this is the original Forge behavior). This mechanism is not perfect yet (please report cases in which you were not allowed to order cards in the graveyard, as well as any strange behavior in corner cases, e.g. when some permanents are indestructible, etc.). This option is disabled by default. +- Allow Ordering Cards Put in Graveyard (option) - +A new option is available in Forge that makes the game determine when to offer you to order the cards as they go simultaneously into graveyard if, for example, several cards are destroyed, sacrificed or milled at the same time. There are three states: 1) "Never" (which is the default, when Forge does not let you choose the order of cards going to graveyard since in most cases it doesn't matter); 2) "With Relevant Cards" (you will be allowed to order cards in case there is at least one card in your library or on your side of the battlefield that cares about the order of cards in graveyard; currently the following cards are marked as caring about graveyard order: Nether Shadow, Spinning Darkness, Corpse Dance, Shallow Grave, Phyrexian Furnace, Krovikan Horror, Volrath's Shapeshifter, Ashen Ghoul, Phyrexian Grimoire, Nature's Kiss, Soldevi Digger, Guiding Spirit, Barrow Ghoul, Circling Vultures, Zombie Scavengers, Necratog, Mistmoon Griffin, Bone Dancer, Bosium Strip, Alms, Death Spark; 3) "Always" (you will always be prompted to order cards simultaneously put in graveyard, even if there is no immediate detected need for it judging by the contents of your library and battlefield). Note that this option does not affect cards that reorder the graveyard as a part of their effect (Fossil Find). If this option is set to "Never", which is also the default, then no ordering is performed for cards like Volrath's Shapeshifter and the cards go into graveyards in whatever order the game automatically determines them to do so (this is the original Forge behavior). This mechanism is not perfect yet (please report cases in which you were not allowed to order cards in the graveyard, as well as any strange behavior in corner cases, e.g. when some permanents are indestructible, etc.). - Desktop Forge: Personal Card Ratings in Quest Mode - In Desktop Forge, it is now possible to assign personal ratings (from 1 star to 5 stars) to cards in Quest Mode by right clicking them and choosing the relevant context menu entry. It is then possible to filter cards by rating in both the deck editor and the quest shop, which should simplify managing bigger inventories. This patch was provided by Seravy. diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index a6e84dac..94c5358d 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -689,10 +689,24 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont @Override public CardCollectionView orderMoveToZoneList(final CardCollectionView cards, final ZoneType destinationZone, final SpellAbility source) { if (source == null || source.getApi() != ApiType.ReorderZone) { - if (destinationZone == ZoneType.Graveyard - && (!FModel.getPreferences().getPrefBoolean(FPref.UI_ALLOW_ORDER_GRAVEYARD_WHEN_NEEDED) || !game.isGraveyardOrdered())) { - // Ordering not necessary - return cards; + if (destinationZone == ZoneType.Graveyard) { + switch (FModel.getPreferences().getPref(FPref.UI_ALLOW_ORDER_GRAVEYARD_WHEN_NEEDED)) { + case ForgeConstants.GRAVEYARD_ORDERING_NEVER: + // No ordering is ever performed by the player except when done by effect (AF ReorderZone) + return cards; + case ForgeConstants.GRAVEYARD_ORDERING_OWN_CARDS: + // Order only if the relevant cards controlled by the player determine the potential necessity for it + if (!game.isGraveyardOrdered(player)) { + return cards; + } + break; + case ForgeConstants.GRAVEYARD_ORDERING_ALWAYS: + // Always order cards, no matter if there is a determined case for it or not + break; + default: + // By default, assume no special ordering necessary (but should not get here unless the preference file is borked) + return cards; + } } } diff --git a/forge-gui/src/main/java/forge/properties/ForgeConstants.java b/forge-gui/src/main/java/forge/properties/ForgeConstants.java index 38defdae..2de21410 100644 --- a/forge-gui/src/main/java/forge/properties/ForgeConstants.java +++ b/forge-gui/src/main/java/forge/properties/ForgeConstants.java @@ -289,6 +289,11 @@ public final class ForgeConstants { public static final String AUTO_YIELD_PER_CARD = "Per Card (Each Game)"; public static final String AUTO_YIELD_PER_ABILITY = "Per Ability (Each Match)"; + // Constants for Graveyard Ordering + public static final String GRAVEYARD_ORDERING_NEVER = "Never"; + public static final String GRAVEYARD_ORDERING_OWN_CARDS = "With Relevant Cards"; + public static final String GRAVEYARD_ORDERING_ALWAYS = "Always"; + // Set boolean constant for landscape mode for gdx port public static final boolean isGdxPortLandscape = FileUtil.doesFileExist(ASSETS_DIR + "switch_orientation.ini") ? true : false; diff --git a/forge-gui/src/main/java/forge/properties/ForgePreferences.java b/forge-gui/src/main/java/forge/properties/ForgePreferences.java index 32484c5e..84871a67 100644 --- a/forge-gui/src/main/java/forge/properties/ForgePreferences.java +++ b/forge-gui/src/main/java/forge/properties/ForgePreferences.java @@ -97,7 +97,7 @@ public class ForgePreferences extends PreferencesStore { UI_ROTATE_PLANE_OR_PHENOMENON("false"), UI_DYNAMIC_PLANECHASE_BG("false"), UI_DISABLE_IMAGES_EFFECT_CARDS("false"), - UI_ALLOW_ORDER_GRAVEYARD_WHEN_NEEDED ("false"), + UI_ALLOW_ORDER_GRAVEYARD_WHEN_NEEDED ("never"), UI_FOR_TOUCHSCREN("false"),