diff --git a/Mage.Client/src/main/java/mage/client/MageFrame.java b/Mage.Client/src/main/java/mage/client/MageFrame.java index 8f2e807bc2e..1e39f3b9923 100644 --- a/Mage.Client/src/main/java/mage/client/MageFrame.java +++ b/Mage.Client/src/main/java/mage/client/MageFrame.java @@ -1269,7 +1269,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { hideGames(); hideTables(); } else { - logger.info("DISCONNECTED (NO Event Dispacth Thread)"); + logger.info("DISCONNECTED (NO Event Dispatch Thread)"); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { diff --git a/Mage.Sets/src/mage/sets/shardsofalara/TidehollowSculler.java b/Mage.Sets/src/mage/sets/shardsofalara/TidehollowSculler.java index 6e3ff344b1a..c290aba0449 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/TidehollowSculler.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/TidehollowSculler.java @@ -29,6 +29,7 @@ package mage.sets.shardsofalara; import java.util.UUID; import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.LeavesBattlefieldTriggeredAbility; @@ -104,15 +105,18 @@ class TidehollowScullerExileEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); Player opponent = game.getPlayer(source.getFirstTarget()); - Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); + // 6/7/2013 If Tidehollow Sculler leaves the battlefield before its first ability has resolved, + // its second ability will trigger. This ability will do nothing when it resolves. + // Then its first ability will resolve and exile the chosen card forever. + Permanent sourcePermanent = (Permanent) source.getSourceObject(game); if (controller != null && opponent != null && sourcePermanent != null) { opponent.revealCards(sourcePermanent.getName(), opponent.getHand(), game); - TargetCard target = new TargetCard(Zone.PICK, new FilterNonlandCard("nonland card to exile")); + TargetCard target = new TargetCard(Zone.HAND, new FilterNonlandCard("nonland card to exile")); if (controller.choose(Outcome.Exile, opponent.getHand(), target, game)) { Card card = opponent.getHand().get(target.getFirstTarget(), game); if (card != null) { - controller.moveCardToExileWithInfo(card, CardUtil.getCardExileZoneId(game, source), sourcePermanent.getName(), source.getSourceId(), game, Zone.HAND); + controller.moveCardToExileWithInfo(card, CardUtil.getObjectExileZoneId(game, sourcePermanent), sourcePermanent.getName(), source.getSourceId(), game, Zone.HAND); } } @@ -143,16 +147,17 @@ class TidehollowScullerLeaveEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - ExileZone exZone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source)); + MageObject sourceObject = source.getSourceObject(game); + if (controller != null && sourceObject != null) { + ExileZone exZone = game.getExile().getExileZone(CardUtil.getObjectExileZoneId(game, sourceObject)); if (exZone != null) { for (Card card : exZone.getCards(game)) { if (card != null) { controller.moveCardToHandWithInfo(card, source.getSourceId(), game, Zone.EXILED); } } - return true; } + return true; } return false; } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/TidehollowScullerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/TidehollowScullerTest.java new file mode 100644 index 00000000000..bc44c731211 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/TidehollowScullerTest.java @@ -0,0 +1,85 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package org.mage.test.cards.triggers.dies; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ + +public class TidehollowScullerTest extends CardTestPlayerBase { + + /** + * Test if the same Tidehollow Sculler is cast multiple times, the correct + * corresponding exiled cards are returned + */ + @Test + public void testCardFromHandWillBeExiled() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2); + addCard(Zone.BATTLEFIELD, playerA, "Island", 2); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 3); + // Tidehollow Sculler {W}{B} + // When Tidehollow Sculler enters the battlefield, target opponent reveals his or her hand and you choose a nonland card from it. Exile that card. + // When Tidehollow Sculler leaves the battlefield, return the exiled card to its owner's hand. + addCard(Zone.HAND, playerA, "Tidehollow Sculler", 1); + // Boomerang {U}{U} + // Return target creature card from your graveyard to your hand. + addCard(Zone.HAND, playerA, "Boomerang", 1); + // Scout's Warning {W} + // The next creature card you play this turn can be played as though it had flash. + // Draw a card. + addCard(Zone.HAND, playerA, "Scout's Warning", 1); + + addCard(Zone.HAND, playerB, "Bloodflow Connoisseur", 1); + addCard(Zone.HAND, playerB, "Silvercoat Lion", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tidehollow Sculler"); + addTarget(playerA, "Bloodflow Connoisseur"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Boomerang", "Tidehollow Sculler"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Scout's Warning", "", "Boomerang"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tidehollow Sculler", "", "", "When {this} leaves the battlefield, return the exiled card to its owner's hand."); + addTarget(playerA, "Silvercoat Lion"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA,"Boomerang", 1); + assertGraveyardCount(playerA,"Scout's Warning", 1); + assertHandCount(playerB, "Bloodflow Connoisseur", 0); // never comes back because first Tidehollow Sculler left battlefield before target was exiled + assertHandCount(playerB, "Silvercoat Lion", 0); + assertExileCount("Silvercoat Lion", 1); + + assertPermanentCount(playerA, "Tidehollow Sculler", 1); + + } +} \ No newline at end of file