From e7e6a5bb99a3d433578eaa0e7b06925fa3c2e8a6 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 7 Nov 2014 16:13:57 +0100 Subject: [PATCH] * Copied cards - Copied cards cease to exist on check of next state based effects if they are returned to hand (#611). --- .../CounterTargetWithReplacementEffect.java | 52 ++++++++++++------- Mage/src/mage/game/Game.java | 1 + Mage/src/mage/game/GameImpl.java | 40 +++++++++++--- Mage/src/mage/game/GameState.java | 10 +++- 4 files changed, 76 insertions(+), 27 deletions(-) diff --git a/Mage/src/mage/abilities/effects/common/CounterTargetWithReplacementEffect.java b/Mage/src/mage/abilities/effects/common/CounterTargetWithReplacementEffect.java index 2931b7114b..d3ff614ffd 100644 --- a/Mage/src/mage/abilities/effects/common/CounterTargetWithReplacementEffect.java +++ b/Mage/src/mage/abilities/effects/common/CounterTargetWithReplacementEffect.java @@ -39,6 +39,7 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.stack.Spell; import mage.game.stack.StackObject; +import mage.players.Player; /** * @author nantuko, North @@ -78,25 +79,40 @@ public class CounterTargetWithReplacementEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { UUID objectId = source.getFirstTarget(); UUID sourceId = source.getSourceId(); - - StackObject stackObject = game.getStack().getStackObject(objectId); - if (stackObject != null && !game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER, objectId, sourceId, stackObject.getControllerId()))) { - boolean spell = false; - if (stackObject instanceof Spell) { - game.rememberLKI(objectId, Zone.STACK, stackObject); - spell = true; - } - game.getStack().remove(stackObject); - if (spell && !((Spell) stackObject).isCopiedSpell()) { - MageObject card = game.getObject(stackObject.getSourceId()); - if (card instanceof Card) { - ((Card) card).moveToZone(targetZone, sourceId, game, flag); - } else { - game.informPlayers("Server: Couldn't move card to zone = " + targetZone + " as it has other than Card type."); + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + StackObject stackObject = game.getStack().getStackObject(objectId); + if (stackObject != null && !game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER, objectId, sourceId, stackObject.getControllerId()))) { + boolean spell = false; + if (stackObject instanceof Spell) { + game.rememberLKI(objectId, Zone.STACK, stackObject); + spell = true; } - } - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTERED, objectId, sourceId, stackObject.getControllerId())); - return true; + game.getStack().remove(stackObject); + if (spell && !((Spell) stackObject).isCopiedSpell()) { + MageObject mageObject = game.getObject(stackObject.getSourceId()); + if (mageObject instanceof Card) { + Card card = (Card) mageObject; + switch (targetZone) { + case HAND: + controller.moveCardToHandWithInfo(card, sourceId, game, Zone.STACK); + break; + case LIBRARY: + controller.moveCardToLibraryWithInfo(card, sourceId, game, Zone.STACK, flag, true); + break; + case EXILED: + controller.moveCardToExileWithInfo(card, null, "", sourceId, game, Zone.STACK); + break; + default: + card.moveToZone(targetZone, sourceId, game, flag); + } + } else { + return false; + } + } + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTERED, objectId, sourceId, stackObject.getControllerId())); + return true; + } } return false; } diff --git a/Mage/src/mage/game/Game.java b/Mage/src/mage/game/Game.java index e17580beea..9a1bda39fe 100644 --- a/Mage/src/mage/game/Game.java +++ b/Mage/src/mage/game/Game.java @@ -80,6 +80,7 @@ public interface Game extends MageItem, Serializable { //game data methods void loadCards(Set cards, UUID ownerId); + void unloadCard(Card card); Collection getCards(); Object getCustomData(); void setCustomData(Object data); diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index cede4c13f2..c625d8c427 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -290,6 +290,20 @@ public abstract class GameImpl implements Game, Serializable { } } + @Override + public void unloadCard(Card card) { + gameCards.remove(card.getId()); + state.removeCard(card); + if (card.isSplitCard()) { + Card leftCard = ((SplitCard)card).getLeftHalfCard(); + gameCards.remove(leftCard.getId()); + state.removeCard(leftCard); + Card rightCard = ((SplitCard)card).getRightHalfCard(); + gameCards.remove(rightCard.getId()); + state.removeCard(rightCard); + } + } + @Override public Collection getCards() { return gameCards.values(); @@ -1414,6 +1428,25 @@ public abstract class GameImpl implements Game, Serializable { } } + // 704.5e + for (Player player: getPlayers().values()) { + for (Card card: player.getHand().getCards(this)) { + if (card.isCopy()) { + player.getHand().remove(card); + this.unloadCard(card); + } + } + } + // (Isochron Scepter) 12/1/2004: If you don't want to cast the copy, you can choose not to; the copy ceases to exist the next time state-based actions are checked. + for (Card card: this.getState().getExile().getAllCards(this)) { + if (card.isCopy()) { + this.getState().getExile().removeCard(card, this); + this.unloadCard(card); + } + } + // TODO Library + graveyard + + List planeswalkers = new ArrayList<>(); List legendary = new ArrayList<>(); for (Permanent perm: getBattlefield().getAllActivePermanents()) { @@ -1649,13 +1682,6 @@ public abstract class GameImpl implements Game, Serializable { } } - // (Isochron Scepter) 12/1/2004: If you don't want to cast the copy, you can choose not to; the copy ceases to exist the next time state-based actions are checked. - for(Card card: this.getState().getExile().getAllCards(this)) { - if (card.isCopy()) { - this.getState().getExile().removeCard(card, this); - this.removeCard(card.getId()); - } - } //TODO: implement the rest return somethingHappened; diff --git a/Mage/src/mage/game/GameState.java b/Mage/src/mage/game/GameState.java index 78ebdc28f9..3bbda24453 100644 --- a/Mage/src/mage/game/GameState.java +++ b/Mage/src/mage/game/GameState.java @@ -539,9 +539,15 @@ public class GameState implements Serializable, Copyable { for (Ability ability: card.getAbilities()) { addAbility(ability, card); } + } + + public void removeCard(Card card) { + zones.remove(card.getId()); + // TODO Watchers? + // TODO Abilities? if (card.isSplitCard()) { - addCard( ((SplitCard)card).getLeftHalfCard()); - addCard( ((SplitCard)card).getRightHalfCard()); + removeCard( ((SplitCard)card).getLeftHalfCard()); + removeCard( ((SplitCard)card).getRightHalfCard()); } }