diff --git a/Mage.Sets/src/mage/cards/a/AetherTradewinds.java b/Mage.Sets/src/mage/cards/a/AetherTradewinds.java index 6ca776b4186..1b684184d63 100644 --- a/Mage.Sets/src/mage/cards/a/AetherTradewinds.java +++ b/Mage.Sets/src/mage/cards/a/AetherTradewinds.java @@ -28,16 +28,13 @@ package mage.cards.a; import java.util.UUID; - -import mage.constants.*; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.*; import mage.filter.FilterPermanent; import mage.filter.predicate.permanent.ControllerPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetControlledPermanent; @@ -54,13 +51,14 @@ public class AetherTradewinds extends CardImpl { } public AetherTradewinds(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{U}"); - + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}"); // Return target permanent you control and target permanent you don't control to their owners' hands. this.getSpellAbility().addTarget(new TargetControlledPermanent()); this.getSpellAbility().addTarget(new TargetPermanent(filter)); - this.getSpellAbility().addEffect(new AetherTradewindsEffect()); + Effect effect = new ReturnToHandTargetEffect(true); + effect.setText("Return target permanent you control and target permanent you don't control to their owners' hands"); + this.getSpellAbility().addEffect(effect); } public AetherTradewinds(final AetherTradewinds card) { @@ -72,36 +70,3 @@ public class AetherTradewinds extends CardImpl { return new AetherTradewinds(this); } } - -class AetherTradewindsEffect extends OneShotEffect { - - public AetherTradewindsEffect() { - super(Outcome.ReturnToHand); - this.staticText = "Return target permanent you control and target permanent you don't control to their owners' hands"; - } - - public AetherTradewindsEffect(final AetherTradewindsEffect effect) { - super(effect); - } - - @Override - public AetherTradewindsEffect copy() { - return new AetherTradewindsEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - boolean result = false; - - Permanent permanent = game.getPermanent(source.getFirstTarget()); - if (permanent != null) { - result |= permanent.moveToZone(Zone.HAND, source.getSourceId(), game, false); - } - permanent = game.getPermanent(source.getTargets().get(1).getFirstTarget()); - if (permanent != null) { - result |= permanent.moveToZone(Zone.HAND, source.getSourceId(), game, false); - } - - return result; - } -} diff --git a/Mage.Sets/src/mage/cards/g/GontiLordOfLuxury.java b/Mage.Sets/src/mage/cards/g/GontiLordOfLuxury.java index 04330dc7e29..168307ed514 100644 --- a/Mage.Sets/src/mage/cards/g/GontiLordOfLuxury.java +++ b/Mage.Sets/src/mage/cards/g/GontiLordOfLuxury.java @@ -131,35 +131,38 @@ class GontiLordOfLuxuryEffect extends OneShotEffect { // move card to exile UUID exileZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); card.setFaceDown(true, game); - controller.moveCardsToExile(card, source, game, false, exileZoneId, sourceObject.getIdName()); - card.setFaceDown(true, game); - @SuppressWarnings("unchecked") - Set exileZones = (Set) game.getState().getValue(GontiLordOfLuxury.VALUE_PREFIX + source.getSourceId().toString()); - if (exileZones == null) { - exileZones = new HashSet<>(); - game.getState().setValue(GontiLordOfLuxury.VALUE_PREFIX + source.getSourceId().toString(), exileZones); + if (controller.moveCardsToExile(card, source, game, false, exileZoneId, sourceObject.getIdName())) { + card.setFaceDown(true, game); + @SuppressWarnings("unchecked") + Set exileZones = (Set) game.getState().getValue(GontiLordOfLuxury.VALUE_PREFIX + source.getSourceId().toString()); + if (exileZones == null) { + exileZones = new HashSet<>(); + game.getState().setValue(GontiLordOfLuxury.VALUE_PREFIX + source.getSourceId().toString(), exileZones); + } + exileZones.add(exileZoneId); + // allow to cast the card + ContinuousEffect effect = new GontiLordOfLuxuryCastFromExileEffect(); + effect.setTargetPointer(new FixedTarget(card.getId(), game)); + game.addEffect(effect, source); + // and you may spend mana as though it were mana of any color to cast it + effect = new GontiLordOfLuxurySpendAnyManaEffect(); + effect.setTargetPointer(new FixedTarget(card.getId(), game)); + game.addEffect(effect, source); } - exileZones.add(exileZoneId); - // allow to cast the card - ContinuousEffect effect = new GontiLordOfLuxuryCastFromExileEffect(); - effect.setTargetPointer(new FixedTarget(card.getId())); - game.addEffect(effect, source); - // and you may spend mana as though it were mana of any color to cast it - effect = new GontiLordOfLuxurySpendAnyManaEffect(); - effect.setTargetPointer(new FixedTarget(card.getId())); - game.addEffect(effect, source); - } - - while (!topCards.isEmpty() && controller.isInGame()) { - Card libCard = topCards.getRandom(game); - topCards.remove(libCard); - controller.moveCardToLibraryWithInfo(libCard, source.getSourceId(), game, Zone.LIBRARY, false, false); } } + // then put the rest on the bottom of that library in a random order + while (!topCards.isEmpty() && controller.isInGame()) { + Card libCard = topCards.getRandom(game); + topCards.remove(libCard); + controller.moveCardToLibraryWithInfo(libCard, source.getSourceId(), game, Zone.LIBRARY, false, false); + } return true; } + return false; } + } class GontiLordOfLuxuryCastFromExileEffect extends AsThoughEffectImpl { @@ -185,13 +188,12 @@ class GontiLordOfLuxuryCastFromExileEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - if (objectId.equals(getTargetPointer().getFirst(game, source))) { - if (affectedControllerId.equals(source.getControllerId())) { - return true; - } - } else if (((FixedTarget) getTargetPointer()).getTarget().equals(objectId)) { - // object has moved zone so effect can be discarted + UUID targetId = getTargetPointer().getFirst(game, source); + if (targetId == null) { this.discard(); + } else if (objectId.equals(targetId) + && affectedControllerId.equals(source.getControllerId())) { + return true; } return false; } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/control/GontiLordOfLuxuryEffectTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/control/GontiLordOfLuxuryEffectTest.java new file mode 100644 index 00000000000..ebc2c88a037 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/control/GontiLordOfLuxuryEffectTest.java @@ -0,0 +1,83 @@ +/* + * 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.control; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class GontiLordOfLuxuryEffectTest extends CardTestPlayerBase { + + /** + * Returning to your hand a creature you own but is controlled by an + * opponent doesn't let you replay it. Happened after I Aether Tradewinded + * my Rashmi that an opponent cast with Gonti, Lord of Luxury (the exile + * part could have something to do with this?). Then on my turn I couldn't + * replay it. + */ + @Test + public void testCanBeCastAgain() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 8); + // Deathtouch + // When Gonti, Lord of Luxury enters the battlefield, look at the top four cards of target opponent's library, exile one of them face down, + // then put the rest on the bottom of that library in a random order. For as long as that card remains exiled, + // you may look at it, you may cast it, and you may spend mana as though it were mana of any type to cast it. + addCard(Zone.HAND, playerA, "Gonti, Lord of Luxury", 1); // Creature {2}{B}{B} + + addCard(Zone.LIBRARY, playerB, "Rashmi, Eternities Crafter"); // Creature {2}{G}{U} + skipInitShuffling(); + addCard(Zone.BATTLEFIELD, playerB, "Island", 2); + addCard(Zone.BATTLEFIELD, playerB, "Forest", 2); + // Return target permanent you control and target permanent you don't control to their owners' hands. + addCard(Zone.HAND, playerB, "Aether Tradewinds", 1); // Intant {2}{U} + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Gonti, Lord of Luxury"); + addTarget(playerA, playerB); + setChoice(playerA, "Rashmi, Eternities Crafter"); + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Rashmi, Eternities Crafter"); + + castSpell(1, PhaseStep.END_TURN, playerB, "Aether Tradewinds", "Silvercoat Lion^Rashmi, Eternities Crafter"); + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Rashmi, Eternities Crafter"); + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerB, "Aether Tradewinds", 1); + assertHandCount(playerB, "Silvercoat Lion", 1); + assertHandCount(playerB, "Rashmi, Eternities Crafter", 0); + assertPermanentCount(playerB, "Rashmi, Eternities Crafter", 1); + + } + +} diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index 6db35840900..fb4d75302e8 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -2694,6 +2694,7 @@ public abstract class PlayerImpl implements Player, Serializable { playable.add(ability); } } + ability.setControllerId(card.getOwnerId()); } } }