diff --git a/Mage.Server.Plugins/Mage.Game.BrawlDuel/src/mage/game/BrawlDuelMatch.java b/Mage.Server.Plugins/Mage.Game.BrawlDuel/src/mage/game/BrawlDuelMatch.java index 4e3437879b5..a3d977a7976 100644 --- a/Mage.Server.Plugins/Mage.Game.BrawlDuel/src/mage/game/BrawlDuelMatch.java +++ b/Mage.Server.Plugins/Mage.Game.BrawlDuel/src/mage/game/BrawlDuelMatch.java @@ -1,4 +1,3 @@ - package mage.game; import mage.game.match.MatchImpl; @@ -6,7 +5,6 @@ import mage.game.match.MatchOptions; import mage.game.mulligan.Mulligan; /** - * * @author spjspj */ public class BrawlDuelMatch extends MatchImpl { @@ -22,8 +20,6 @@ public class BrawlDuelMatch extends MatchImpl { BrawlDuel game = new BrawlDuel(options.getAttackOption(), options.getRange(), mulligan, startLife); game.setCheckCommanderDamage(false); game.setStartMessage(this.createGameStartMessage()); - game.setAlsoHand(true); - game.setAlsoLibrary(true); initGame(game); games.add(game); } diff --git a/Mage.Server.Plugins/Mage.Game.BrawlFreeForAll/src/mage/game/BrawlFreeForAllMatch.java b/Mage.Server.Plugins/Mage.Game.BrawlFreeForAll/src/mage/game/BrawlFreeForAllMatch.java index 0e00a6ab9d9..dab8c4dd52a 100644 --- a/Mage.Server.Plugins/Mage.Game.BrawlFreeForAll/src/mage/game/BrawlFreeForAllMatch.java +++ b/Mage.Server.Plugins/Mage.Game.BrawlFreeForAll/src/mage/game/BrawlFreeForAllMatch.java @@ -1,4 +1,3 @@ - package mage.game; import mage.game.match.MatchImpl; @@ -6,7 +5,6 @@ import mage.game.match.MatchOptions; import mage.game.mulligan.Mulligan; /** - * * @author spjspj */ public class BrawlFreeForAllMatch extends MatchImpl { @@ -21,9 +19,7 @@ public class BrawlFreeForAllMatch extends MatchImpl { Mulligan mulligan = options.getMulliganType().getMulligan(options.getFreeMulligans()); BrawlFreeForAll game = new BrawlFreeForAll(options.getAttackOption(), options.getRange(), mulligan, startLife); game.setStartMessage(this.createGameStartMessage()); - game.setAlsoHand(true); game.setCheckCommanderDamage(false); - game.setAlsoLibrary(true); initGame(game); games.add(game); } diff --git a/Mage.Server.Plugins/Mage.Game.CommanderDuel/src/mage/game/CommanderDuelMatch.java b/Mage.Server.Plugins/Mage.Game.CommanderDuel/src/mage/game/CommanderDuelMatch.java index 654930db5b5..f03473c6e26 100644 --- a/Mage.Server.Plugins/Mage.Game.CommanderDuel/src/mage/game/CommanderDuelMatch.java +++ b/Mage.Server.Plugins/Mage.Game.CommanderDuel/src/mage/game/CommanderDuelMatch.java @@ -1,4 +1,3 @@ - package mage.game; import mage.game.match.MatchImpl; @@ -6,7 +5,6 @@ import mage.game.match.MatchOptions; import mage.game.mulligan.Mulligan; /** - * * @author BetaSteward_at_googlemail.com */ public class CommanderDuelMatch extends MatchImpl { @@ -18,24 +16,19 @@ public class CommanderDuelMatch extends MatchImpl { @Override public void startGame() throws GameException { int startLife = 40; - boolean alsoHand = true; // Don't like it to compare but seems like it's complicated to do it in another way boolean checkCommanderDamage = true; if (options.getDeckType().equals("Variant Magic - Duel Commander")) { startLife = 20; // Starting with the Commander 2016 update (on November 11th, 2016), Duel Commander will be played with 20 life points instead of 30. - alsoHand = true; // commander going to hand allowed to go to command zone effective July 17, 2015 checkCommanderDamage = false; // since nov 16 duel commander uses no longer commander damage rule } if (options.getDeckType().equals("Variant Magic - MTGO 1v1 Commander")) { startLife = 30; - alsoHand = true; // commander going to hand allowed to go to command zone effective July 17, 2015 } Mulligan mulligan = options.getMulliganType().getMulligan(options.getFreeMulligans()); CommanderDuel game = new CommanderDuel(options.getAttackOption(), options.getRange(), mulligan, startLife); game.setCheckCommanderDamage(checkCommanderDamage); game.setStartMessage(this.createGameStartMessage()); - game.setAlsoHand(alsoHand); - game.setAlsoLibrary(true); initGame(game); games.add(game); } diff --git a/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/src/mage/game/CommanderFreeForAllMatch.java b/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/src/mage/game/CommanderFreeForAllMatch.java index efdc7aa305a..fb151a8a40e 100644 --- a/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/src/mage/game/CommanderFreeForAllMatch.java +++ b/Mage.Server.Plugins/Mage.Game.CommanderFreeForAll/src/mage/game/CommanderFreeForAllMatch.java @@ -1,5 +1,3 @@ - - package mage.game; import mage.game.match.MatchImpl; @@ -7,7 +5,6 @@ import mage.game.match.MatchOptions; import mage.game.mulligan.Mulligan; /** - * * @author LevelX2 */ public class CommanderFreeForAllMatch extends MatchImpl { @@ -19,16 +16,12 @@ public class CommanderFreeForAllMatch extends MatchImpl { @Override public void startGame() throws GameException { int startLife = 40; - boolean alsoHand = true; if (options.getDeckType().equals("Variant Magic - Duel Commander")) { startLife = 30; - alsoHand = true; // commander going to hand allowed to go to command zone effective July 17, 2015 } Mulligan mulligan = options.getMulliganType().getMulligan(options.getFreeMulligans()); CommanderFreeForAll game = new CommanderFreeForAll(options.getAttackOption(), options.getRange(), mulligan, startLife); game.setStartMessage(this.createGameStartMessage()); - game.setAlsoHand(alsoHand); - game.setAlsoLibrary(true); initGame(game); games.add(game); } diff --git a/Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/src/mage/game/FreeformCommanderDuelMatch.java b/Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/src/mage/game/FreeformCommanderDuelMatch.java index 1f3e141929d..57422d41bea 100644 --- a/Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/src/mage/game/FreeformCommanderDuelMatch.java +++ b/Mage.Server.Plugins/Mage.Game.FreeformCommanderDuel/src/mage/game/FreeformCommanderDuelMatch.java @@ -16,15 +16,11 @@ public class FreeformCommanderDuelMatch extends MatchImpl { @Override public void startGame() throws GameException { int startLife = 20; - boolean alsoHand = true; - boolean checkCommanderDamage = true; Mulligan mulligan = options.getMulliganType().getMulligan(options.getFreeMulligans()); FreeformCommanderDuel game = new FreeformCommanderDuel(options.getAttackOption(), options.getRange(), mulligan, startLife); - game.setCheckCommanderDamage(checkCommanderDamage); + game.setCheckCommanderDamage(true); game.setStartMessage(this.createGameStartMessage()); - game.setAlsoHand(alsoHand); - game.setAlsoLibrary(true); initGame(game); games.add(game); } diff --git a/Mage.Server.Plugins/Mage.Game.FreeformCommanderFreeForAll/src/mage/game/FreeformCommanderFreeForAllMatch.java b/Mage.Server.Plugins/Mage.Game.FreeformCommanderFreeForAll/src/mage/game/FreeformCommanderFreeForAllMatch.java index 5c623740426..47440a3f519 100644 --- a/Mage.Server.Plugins/Mage.Game.FreeformCommanderFreeForAll/src/mage/game/FreeformCommanderFreeForAllMatch.java +++ b/Mage.Server.Plugins/Mage.Game.FreeformCommanderFreeForAll/src/mage/game/FreeformCommanderFreeForAllMatch.java @@ -1,4 +1,3 @@ - package mage.game; import mage.game.match.MatchImpl; @@ -6,7 +5,6 @@ import mage.game.match.MatchOptions; import mage.game.mulligan.Mulligan; /** - * * @author spjspj */ public class FreeformCommanderFreeForAllMatch extends MatchImpl { @@ -18,12 +16,9 @@ public class FreeformCommanderFreeForAllMatch extends MatchImpl { @Override public void startGame() throws GameException { int startLife = 40; - boolean alsoHand = true; Mulligan mulligan = options.getMulliganType().getMulligan(options.getFreeMulligans()); FreeformCommanderFreeForAll game = new FreeformCommanderFreeForAll(options.getAttackOption(), options.getRange(), mulligan, startLife); game.setStartMessage(this.createGameStartMessage()); - game.setAlsoHand(alsoHand); - game.setAlsoLibrary(true); initGame(game); games.add(game); } diff --git a/Mage.Server.Plugins/Mage.Game.OathbreakerDuel/src/mage/game/OathbreakerDuelMatch.java b/Mage.Server.Plugins/Mage.Game.OathbreakerDuel/src/mage/game/OathbreakerDuelMatch.java index 2d2491e2a14..8fc1fffa4c1 100644 --- a/Mage.Server.Plugins/Mage.Game.OathbreakerDuel/src/mage/game/OathbreakerDuelMatch.java +++ b/Mage.Server.Plugins/Mage.Game.OathbreakerDuel/src/mage/game/OathbreakerDuelMatch.java @@ -16,13 +16,10 @@ public class OathbreakerDuelMatch extends MatchImpl { @Override public void startGame() throws GameException { int startLife = 20; - boolean alsoHand = true; Mulligan mulligan = options.getMulliganType().getMulligan(options.getFreeMulligans()); OathbreakerDuel game = new OathbreakerDuel(options.getAttackOption(), options.getRange(), mulligan, startLife); game.setCheckCommanderDamage(false); game.setStartMessage(this.createGameStartMessage()); - game.setAlsoHand(alsoHand); - game.setAlsoLibrary(true); initGame(game); games.add(game); } diff --git a/Mage.Server.Plugins/Mage.Game.OathbreakerFreeForAll/src/mage/game/OathbreakerFreeForAllMatch.java b/Mage.Server.Plugins/Mage.Game.OathbreakerFreeForAll/src/mage/game/OathbreakerFreeForAllMatch.java index 2e2d239e287..6b342469b9f 100644 --- a/Mage.Server.Plugins/Mage.Game.OathbreakerFreeForAll/src/mage/game/OathbreakerFreeForAllMatch.java +++ b/Mage.Server.Plugins/Mage.Game.OathbreakerFreeForAll/src/mage/game/OathbreakerFreeForAllMatch.java @@ -16,13 +16,10 @@ public class OathbreakerFreeForAllMatch extends MatchImpl { @Override public void startGame() throws GameException { int startLife = 20; - boolean alsoHand = true; Mulligan mulligan = options.getMulliganType().getMulligan(options.getFreeMulligans()); OathbreakerFreeForAll game = new OathbreakerFreeForAll(options.getAttackOption(), options.getRange(), mulligan, startLife); game.setCheckCommanderDamage(false); game.setStartMessage(this.createGameStartMessage()); - game.setAlsoHand(alsoHand); - game.setAlsoLibrary(true); initGame(game); games.add(game); } diff --git a/Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/src/mage/game/PennyDreadfulCommanderFreeForAllMatch.java b/Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/src/mage/game/PennyDreadfulCommanderFreeForAllMatch.java index e9deed1700c..f0feac621b4 100644 --- a/Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/src/mage/game/PennyDreadfulCommanderFreeForAllMatch.java +++ b/Mage.Server.Plugins/Mage.Game.PennyDreadfulCommanderFreeForAll/src/mage/game/PennyDreadfulCommanderFreeForAllMatch.java @@ -1,5 +1,3 @@ - - package mage.game; import mage.game.match.MatchImpl; @@ -7,7 +5,6 @@ import mage.game.match.MatchOptions; import mage.game.mulligan.Mulligan; /** - * * @author spjspj */ public class PennyDreadfulCommanderFreeForAllMatch extends MatchImpl { @@ -19,16 +16,12 @@ public class PennyDreadfulCommanderFreeForAllMatch extends MatchImpl { @Override public void startGame() throws GameException { int startLife = 40; - boolean alsoHand = true; if (options.getDeckType().equals("Variant Magic - Duel Penny Dreadful Commander")) { startLife = 30; - alsoHand = true; // commander going to hand allowed to go to command zone effective July 17, 2015 } Mulligan mulligan = options.getMulliganType().getMulligan(options.getFreeMulligans()); PennyDreadfulCommanderFreeForAll game = new PennyDreadfulCommanderFreeForAll(options.getAttackOption(), options.getRange(), mulligan, startLife); game.setStartMessage(this.createGameStartMessage()); - game.setAlsoHand(alsoHand); - game.setAlsoLibrary(true); initGame(game); games.add(game); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/CommandersCastTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/CommandersCastTest.java index 77e3a7e53d0..ef7556ca1ee 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/CommandersCastTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/CommandersCastTest.java @@ -183,4 +183,45 @@ public class CommandersCastTest extends CardTestCommander4Players { execute(); assertAllCommandsUsed(); } + + @Test + public void test_CastFromHandWithoutTaxIncrease() { + // Player order: A -> D -> C -> B + + addCard(Zone.COMMAND, playerA, "Balduvian Bears", 1); // {1}{G}, 2/2, commander + addCard(Zone.BATTLEFIELD, playerA, "Forest", 4); // cast from command for {1}{G}, from hand for {1}{G}, from command for {1}{G}{2} + // + // Counter target spell. If that spell is countered this way, put it into its owner’s hand instead of into that player’s graveyard. + // Draw a card. + addCard(Zone.HAND, playerB, "Remand", 2); + addCard(Zone.BATTLEFIELD, playerB, "Island", 2); // counter 2 times + + // cast 1 and counter (increase commander tax) + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Remand", "Balduvian Bears", "Balduvian Bears"); + setChoice(playerA, "No"); // move to hand + checkCommandCardCount("cast 1", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Balduvian Bears", 0); + checkHandCardCount("cast 1", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Balduvian Bears", 1); + checkPermanentCount("cast 1", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Balduvian Bears", 0); + + ///* + // cast 2 from hand without tax + castSpell(5, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears"); + castSpell(5, PhaseStep.PRECOMBAT_MAIN, playerB, "Remand", "Balduvian Bears", "Balduvian Bears"); + setChoice(playerA, "Yes"); // move to command zone + checkCommandCardCount("cast 2", 5, PhaseStep.POSTCOMBAT_MAIN, playerA, "Balduvian Bears", 1); + checkHandCardCount("cast 2", 5, PhaseStep.POSTCOMBAT_MAIN, playerA, "Balduvian Bears", 0); + checkPermanentCount("cast 2", 5, PhaseStep.POSTCOMBAT_MAIN, playerA, "Balduvian Bears", 0); + + // cast 3 from command with tax for 1 play + castSpell(9, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears"); + checkCommandCardCount("cast 3", 9, PhaseStep.BEGIN_COMBAT, playerA, "Balduvian Bears", 0); + checkHandCardCount("cast 3", 9, PhaseStep.BEGIN_COMBAT, playerA, "Balduvian Bears", 0); + checkPermanentCount("cast 3", 9, PhaseStep.BEGIN_COMBAT, playerA, "Balduvian Bears", 1); + + setStrictChooseMode(true); + setStopAt(9, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/CommanderReplacementEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/CommanderReplacementEffect.java index 227e938df84..399cd4c72af 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/CommanderReplacementEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/CommanderReplacementEffect.java @@ -13,18 +13,20 @@ import mage.game.permanent.Permanent; import mage.game.stack.Spell; import mage.players.Player; +import java.util.Locale; import java.util.UUID; /** - * @author Plopman + * @author Plopman, JayDi85 */ -//20130711 +// 2019-07-12 /* - * 903.11. If a commander would be put into its owner's graveyard from anywhere, that player may put it into the command zone instead. - * 903.12. If a commander would be put into the exile zone from anywhere, its owner may put it into the command zone instead. - * 903.9. If a commander would be exiled from anywhere or put into its owner's hand, graveyard, or -library from anywhere, its owner may put it into the command zone instead. This replacement effect -may apply more than once to the same event. This is an exception to rule 614.5. + 903.9. If a commander would be exiled from anywhere or put into its owner’s hand, graveyard, or library from anywhere, + its owner may put it into the command zone instead. This replacement effect may apply more than once to the same event. + This is an exception to rule 614.5. + 903.9a If a commander is a melded permanent and its owner chooses to put it into the command zone this way, + that permanent and the card representing it that isn’t a commander are put into the appropriate zone, and the card + that represents it and is a commander is put into the command zone. */ // Oathbreaker mode: If your Oathbreaker changes zones, you may return it to the Command Zone. The Signature Spell must return to the Command Zone. @@ -32,8 +34,8 @@ may apply more than once to the same event. This is an exception to rule 614.5. public class CommanderReplacementEffect extends ReplacementEffectImpl { private final UUID commanderId; - private final boolean alsoHand; - private final boolean alsoLibrary; + private final boolean alsoHand; // return from hand to command zone + private final boolean alsoLibrary; // return from library to command zone private final boolean forceToMove; private final String commanderTypeName; @@ -87,56 +89,56 @@ public class CommanderReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - switch (((ZoneChangeEvent) event).getToZone()) { - case HAND: - if (!alsoHand && ((ZoneChangeEvent) event).getToZone() == Zone.HAND) { - return false; - } + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + + if (!game.isSimulation() && commanderId.equals(zEvent.getTargetId())) { + //System.out.println("applies " + game.getTurnNum() + ": " + game.getObject(event.getTargetId()).getName() + ": " + zEvent.getFromZone() + " -> " + zEvent.getToZone() + "; " + game.getObject(zEvent.getSourceId())); + } + + if (zEvent.getToZone().equals(Zone.HAND) && !alsoHand) { + return false; + } + if (zEvent.getToZone().equals(Zone.LIBRARY) && !alsoLibrary) { + return false; + } + + // return to command zone + switch (zEvent.getToZone()) { case LIBRARY: - if (!alsoLibrary && ((ZoneChangeEvent) event).getToZone() == Zone.LIBRARY) { - return false; - } + case HAND: case GRAVEYARD: case EXILED: - if (((ZoneChangeEvent) event).getFromZone() == Zone.STACK) { - Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell != null && commanderId.equals(spell.getSourceId())) { - return true; - } - } - if (commanderId.equals(event.getTargetId())) { + if (commanderId.equals(zEvent.getTargetId())) { return true; } break; - case STACK: - Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell != null) { - if (commanderId.equals(spell.getSourceId())) { - return true; - } - } - break; - } return false; } @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - if (((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) { - Permanent permanent = ((ZoneChangeEvent) event).getTarget(); + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + String originToZone = zEvent.getToZone().toString().toLowerCase(Locale.ENGLISH); + + if (!game.isSimulation()) { + //System.out.println("replace " + game.getTurnNum() + ": " + game.getObject(event.getTargetId()).getName() + ": " + zEvent.getFromZone() + " -> " + zEvent.getToZone() + "; " + game.getObject(zEvent.getSourceId())); + } + + if (zEvent.getFromZone() == Zone.BATTLEFIELD) { + Permanent permanent = zEvent.getTarget(); if (permanent != null) { Player player = game.getPlayer(permanent.getOwnerId()); - if (player != null && (forceToMove || player.chooseUse(Outcome.Benefit, "Move " + commanderTypeName + " to command zone?", source, game))) { - ((ZoneChangeEvent) event).setToZone(Zone.COMMAND); + if (player != null && (forceToMove || player.chooseUse(Outcome.Benefit, "Move " + commanderTypeName + " to command zone instead " + originToZone + "?", source, game))) { + zEvent.setToZone(Zone.COMMAND); if (!game.isSimulation()) { - game.informPlayers(player.getLogName() + " has moved their " + commanderTypeName + " to the command zone"); + game.informPlayers(player.getLogName() + " has moved their " + commanderTypeName + " to the command zone instead " + originToZone); } } } } else { Card card = null; - if (((ZoneChangeEvent) event).getFromZone() == Zone.STACK) { + if (zEvent.getFromZone() == Zone.STACK) { Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null) { card = game.getCard(spell.getSourceId()); @@ -147,10 +149,10 @@ public class CommanderReplacementEffect extends ReplacementEffectImpl { } if (card != null) { Player player = game.getPlayer(card.getOwnerId()); - if (player != null && (forceToMove || player.chooseUse(Outcome.Benefit, "Move " + commanderTypeName + " to command zone?", source, game))) { + if (player != null && (forceToMove || player.chooseUse(Outcome.Benefit, "Move " + commanderTypeName + " to command zone instead " + originToZone + "?", source, game))) { ((ZoneChangeEvent) event).setToZone(Zone.COMMAND); if (!game.isSimulation()) { - game.informPlayers(player.getLogName() + " has moved their " + commanderTypeName + " to the command zone"); + game.informPlayers(player.getLogName() + " has moved their " + commanderTypeName + " to the command zone instead " + originToZone); } } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/cost/CommanderCostModification.java b/Mage/src/main/java/mage/abilities/effects/common/cost/CommanderCostModification.java index eb7c672a06c..7e6f87daf2d 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/cost/CommanderCostModification.java +++ b/Mage/src/main/java/mage/abilities/effects/common/cost/CommanderCostModification.java @@ -20,6 +20,9 @@ import java.util.UUID; command zone costs an additional {2} for each previous time the player casting it has cast it from the command zone that game. This additional cost is informally known as the “commander tax.” */ + +// cast from hand like Remand do not increase commander tax + public class CommanderCostModification extends CostModificationEffectImpl { private final UUID commanderId; diff --git a/Mage/src/main/java/mage/game/GameCommanderImpl.java b/Mage/src/main/java/mage/game/GameCommanderImpl.java index 03d50ee66ff..68ab22c9194 100644 --- a/Mage/src/main/java/mage/game/GameCommanderImpl.java +++ b/Mage/src/main/java/mage/game/GameCommanderImpl.java @@ -23,8 +23,11 @@ public abstract class GameCommanderImpl extends GameImpl { // private final Map mulliganedCards = new HashMap<>(); protected boolean checkCommanderDamage = true; - protected boolean alsoHand; // replace commander going to hand - protected boolean alsoLibrary; // replace commander going to library + + // old commander's versions (before 2017) restrict return from hand or library to command zone + protected boolean alsoHand = true; // replace commander going to hand + protected boolean alsoLibrary = true; // replace commander going to library + protected boolean startingPlayerSkipsDraw = true; public GameCommanderImpl(MultiplayerAttackOption attackOption, RangeOfInfluence range, Mulligan mulligan, int startLife) { diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index 0057e1dbc71..50440978e73 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -1189,11 +1189,17 @@ public abstract class PlayerImpl implements Player, Serializable { //20091005 - 305.1 if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.PLAY_LAND, card.getId(), card.getId(), playerId, activationStatus.getPermittingObject()))) { // int bookmark = game.bookmarkState(); - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.PLAY_LAND, card.getId(), card.getId(), playerId, activationStatus.getPermittingObject())); + // land events must return original zone (uses for commander watcher) + Zone cardZoneBefore = game.getState().getZone(card.getId()); + GameEvent landEventBefore = GameEvent.getEvent(GameEvent.EventType.PLAY_LAND, card.getId(), card.getId(), playerId, activationStatus.getPermittingObject()); + landEventBefore.setZone(cardZoneBefore); + game.fireEvent(landEventBefore); if (moveCards(card, Zone.BATTLEFIELD, playLandAbility, game, false, false, false, null)) { landsPlayed++; - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.LAND_PLAYED, card.getId(), card.getId(), playerId, activationStatus.getPermittingObject())); + GameEvent landEventAfter = GameEvent.getEvent(GameEvent.EventType.LAND_PLAYED, card.getId(), card.getId(), playerId, activationStatus.getPermittingObject()); + landEventAfter.setZone(cardZoneBefore); + game.fireEvent(landEventAfter); game.fireInformEvent(getLogName() + " plays " + card.getLogName()); // game.removeBookmark(bookmark); resetStoredBookmark(game); // prevent undo after playing a land diff --git a/Mage/src/main/java/mage/watchers/common/CommanderPlaysCountWatcher.java b/Mage/src/main/java/mage/watchers/common/CommanderPlaysCountWatcher.java index 43c7a19b8d8..d354aadb44e 100644 --- a/Mage/src/main/java/mage/watchers/common/CommanderPlaysCountWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/CommanderPlaysCountWatcher.java @@ -1,6 +1,7 @@ package mage.watchers.common; import mage.constants.WatcherScope; +import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; @@ -12,7 +13,8 @@ import java.util.Map; import java.util.UUID; /** - * Calcs commanders play count (spell or land) + * Calcs commanders play count only from command zone (spell or land) + * Cards like Remand can put command to hand and cast it without commander tax increase * * @author JayDi85 */ @@ -49,7 +51,7 @@ public class CommanderPlaysCountWatcher extends Watcher { } } - if (isCommanderObject) { + if (isCommanderObject && event.getZone() == Zone.COMMAND) { int count = playsCount.getOrDefault(possibleCommanderId, 0); count++; playsCount.put(possibleCommanderId, count);