diff --git a/Mage.Sets/src/mage/cards/w/WordOfCommand.java b/Mage.Sets/src/mage/cards/w/WordOfCommand.java index e2a349ffa76..d03d0332667 100644 --- a/Mage.Sets/src/mage/cards/w/WordOfCommand.java +++ b/Mage.Sets/src/mage/cards/w/WordOfCommand.java @@ -1,3 +1,4 @@ + package mage.cards.w; import java.util.UUID; @@ -71,11 +72,23 @@ class WordOfCommandEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); + Player sourceController = game.getPlayer(source.getControllerId()); Player targetPlayer = game.getPlayer(source.getFirstTarget()); MageObject sourceObject = game.getObject(source.getSourceId()); Card card = null; - if (controller != null && targetPlayer != null && sourceObject != null) { + if (sourceController != null && targetPlayer != null && sourceObject != null) { + Player controller = null; + Spell wordOfCommand = game.getSpell(source.getSourceId()); + if (wordOfCommand != null) { + if (wordOfCommand.getCommandedBy() != null) { + controller = game.getPlayer(wordOfCommand.getCommandedBy()); + } else { + controller = game.getPlayer(sourceController.getTurnControlledBy()); + } + } + if (controller == null) { + controller = sourceController; // reset the controller to avoid NPE + } // Look at target opponent's hand and choose a card from it TargetCard targetCard = new TargetCard(Zone.HAND, new FilterCard()); @@ -140,13 +153,15 @@ class WordOfCommandEffect extends OneShotEffect { spell.setCommandedBy(controller.getId()); // If the chosen card is cast as a spell, you control the player while that spell is resolving } } - - Spell wordOfCommand = game.getSpell(source.getSourceId()); + + wordOfCommand = game.getSpell(source.getSourceId()); if (wordOfCommand != null) { wordOfCommand.setCommandedBy(controller.getId()); // You control the player until Word of Command finishes resolving } else { - controller.resetOtherTurnsControlled(); - targetPlayer.setGameUnderYourControl(true); + targetPlayer.setGameUnderYourControl(true, false); + if (!targetPlayer.getTurnControlledBy().equals(controller.getId())) { + controller.getPlayersUnderYourControl().remove(targetPlayer.getId()); + } } return true; } diff --git a/Mage/src/main/java/mage/game/Game.java b/Mage/src/main/java/mage/game/Game.java index 2f7af72d292..cdb2fae408d 100644 --- a/Mage/src/main/java/mage/game/Game.java +++ b/Mage/src/main/java/mage/game/Game.java @@ -393,7 +393,7 @@ public interface Game extends MageItem, Serializable { boolean checkStateAndTriggered(); void playPriority(UUID activePlayerId, boolean resuming); - + void resetControlAfterSpellResolve(UUID topId); boolean endTurn(Ability source); diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 55c1872ab19..5127ed4af37 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -1429,12 +1429,15 @@ public abstract class GameImpl implements Game, Serializable { if (turnController != null) { Player targetPlayer = getPlayer(spellControllerId); if (targetPlayer != null) { + targetPlayer.setGameUnderYourControl(true, false); informPlayers(turnController.getLogName() + " lost control over " + targetPlayer.getLogName()); - turnController.resetOtherTurnsControlled(); - targetPlayer.setGameUnderYourControl(true); + if (targetPlayer.getTurnControlledBy().equals(turnController.getId())) { + turnController.getPlayersUnderYourControl().remove(targetPlayer.getId()); + } } } } + spell.setCommandedBy(null); } } } diff --git a/Mage/src/main/java/mage/players/Player.java b/Mage/src/main/java/mage/players/Player.java index 6a51f097456..0bcb72fb3bb 100644 --- a/Mage/src/main/java/mage/players/Player.java +++ b/Mage/src/main/java/mage/players/Player.java @@ -279,6 +279,8 @@ public interface Player extends MageItem, Copyable { */ void setTurnControlledBy(UUID playerId); + List getTurnControllers(); + UUID getTurnControlledBy(); /** @@ -306,6 +308,8 @@ public interface Player extends MageItem, Copyable { */ void setGameUnderYourControl(boolean value); + void setGameUnderYourControl(boolean value, boolean fullRestore); + boolean isTestMode(); void setTestMode(boolean value); @@ -852,6 +856,8 @@ public interface Player extends MageItem, Copyable { Set getUsersAllowedToSeeHandCards(); + void setPayManaMode(boolean payManaMode); + boolean isInPayManaMode(); void setMatchPlayer(MatchPlayer matchPlayer); diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index a21a497df72..b5f0f40ddc4 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -156,6 +156,7 @@ public abstract class PlayerImpl implements Player, Serializable { protected boolean isGameUnderControl = true; protected UUID turnController; + protected List turnControllers = new ArrayList<>(); protected Set playersUnderYourControl = new HashSet<>(); protected Set usersAllowedToSeeHandCards = new HashSet<>(); @@ -263,6 +264,8 @@ public abstract class PlayerImpl implements Player, Serializable { this.isGameUnderControl = player.isGameUnderControl; this.turnController = player.turnController; + this.turnControllers.clear(); + this.turnControllers.addAll(player.turnControllers); this.passed = player.passed; this.passedTurn = player.passedTurn; @@ -343,6 +346,8 @@ public abstract class PlayerImpl implements Player, Serializable { this.isGameUnderControl = player.isGameUnderControl(); this.turnController = player.getTurnControlledBy(); + this.turnControllers.clear(); + this.turnControllers.addAll(player.getTurnControllers()); this.reachedNextTurnAfterLeaving = player.hasReachedNextTurnAfterLeaving(); this.castSourceIdWithAlternateMana = player.getCastSourceIdWithAlternateMana(); this.castSourceIdManaCosts = player.getCastSourceIdManaCosts(); @@ -398,6 +403,7 @@ public abstract class PlayerImpl implements Player, Serializable { this.turns = 0; this.isGameUnderControl = true; this.turnController = this.getId(); + this.turnControllers.clear(); this.playersUnderYourControl.clear(); this.passed = false; @@ -520,13 +526,13 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public void controlPlayersTurn(Game game, UUID playerId) { + Player player = game.getPlayer(playerId); + player.setTurnControlledBy(this.getId()); + game.informPlayers(getLogName() + " controls the turn of " + player.getLogName()); if (!playerId.equals(this.getId())) { this.playersUnderYourControl.add(playerId); - Player player = game.getPlayer(playerId); if (!player.hasLeft() && !player.hasLost()) { player.setGameUnderYourControl(false); - player.setTurnControlledBy(this.getId()); - game.informPlayers(getLogName() + " controls the turn of " + player.getLogName()); } DelayedTriggeredAbility ability = new AtTheEndOfTurnStepPostDelayedTriggeredAbility(new LoseControlOnOtherPlayersControllerEffect(this.getLogName(), player.getLogName())); ability.setSourceId(getId()); @@ -538,6 +544,12 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public void setTurnControlledBy(UUID playerId) { this.turnController = playerId; + this.turnControllers.add(playerId); + } + + @Override + public List getTurnControllers() { + return this.turnControllers; } @Override @@ -563,9 +575,27 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public void setGameUnderYourControl(boolean value) { + setGameUnderYourControl(value, true); + } + + @Override + public void setGameUnderYourControl(boolean value, boolean fullRestore) { this.isGameUnderControl = value; if (isGameUnderControl) { - this.turnController = getId(); + if (fullRestore) { + this.turnControllers.clear(); + this.turnController = getId(); + } else { + if (turnControllers.size() > 0) { + this.turnControllers.remove(turnControllers.size() - 1); + } + if (turnControllers.isEmpty()) { + this.turnController = getId(); + } else { + this.turnController = turnControllers.get(turnControllers.size() - 1); + isGameUnderControl = false; + } + } } } @@ -980,6 +1010,11 @@ public abstract class PlayerImpl implements Player, Serializable { return castSourceIdManaCosts; } + @Override + public void setPayManaMode(boolean payManaMode) { + this.payManaMode = payManaMode; + } + @Override public boolean isInPayManaMode() { return payManaMode;