From c41c6e1fe9c4e930b8a6bddf89a3013d0d83b0a4 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 3 Oct 2018 13:44:01 +0200 Subject: [PATCH] Fixed a problem with casting split cards from non hand zone. Added some generic cast from non hand zone effects and started replacing card specific effects by the generic ones (fixes #5356 and fixes #4493). --- .../mage/cards/a/AbandonedSarcophagus.java | 54 +++--------- .../src/mage/cards/a/AbbotOfKeralKeep.java | 4 +- Mage.Sets/src/mage/cards/a/ActOnImpulse.java | 35 +------- Mage.Sets/src/mage/cards/a/AerialCaravan.java | 35 +------- Mage.Sets/src/mage/cards/a/ApexOfPower.java | 33 +------- .../src/mage/cards/c/ChandraPyromaster.java | 54 ++---------- .../src/mage/cards/c/CommuneWithLava.java | 3 +- .../src/mage/cards/c/CunningAbduction.java | 45 ++-------- Mage.Sets/src/mage/cards/d/DarkDecision.java | 39 +-------- .../src/mage/cards/d/DarkDwellerOracle.java | 38 ++------- .../src/mage/cards/d/DaxosOfMeletis.java | 14 ++-- Mage.Sets/src/mage/cards/d/DeadMansChest.java | 9 +- .../src/mage/cards/d/DireFleetDaredevil.java | 45 ++-------- Mage.Sets/src/mage/cards/d/DreamPillager.java | 45 +++------- Mage.Sets/src/mage/cards/e/ElkinLair.java | 8 +- .../src/mage/cards/m/MissionBriefing.java | 34 +------- .../mage/cards/n/NarsetEnlightenedMaster.java | 6 +- .../asthough/PlayFromNonHandZoneTest.java | 7 +- .../abilities/effects/ContinuousEffects.java | 23 ++++-- .../effects/common/AttachEffect.java | 5 +- .../PlayFromNotOwnHandZoneAllEffect.java | 74 +++++++++++++++++ .../PlayFromNotOwnHandZoneTargetEffect.java | 82 +++++++++++++++++++ .../abilities/keyword/AftermathAbility.java | 21 +++-- .../main/java/mage/players/PlayerImpl.java | 61 +++++++------- .../target/targetpointer/FixedTarget.java | 6 ++ 25 files changed, 304 insertions(+), 476 deletions(-) create mode 100644 Mage/src/main/java/mage/abilities/effects/common/asthought/PlayFromNotOwnHandZoneAllEffect.java create mode 100644 Mage/src/main/java/mage/abilities/effects/common/asthought/PlayFromNotOwnHandZoneTargetEffect.java diff --git a/Mage.Sets/src/mage/cards/a/AbandonedSarcophagus.java b/Mage.Sets/src/mage/cards/a/AbandonedSarcophagus.java index 5d44aa8dd68..81a7e42baf5 100644 --- a/Mage.Sets/src/mage/cards/a/AbandonedSarcophagus.java +++ b/Mage.Sets/src/mage/cards/a/AbandonedSarcophagus.java @@ -1,4 +1,3 @@ - package mage.cards.a; import java.util.HashMap; @@ -7,18 +6,18 @@ import java.util.Map.Entry; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneAllEffect; import mage.abilities.keyword.CyclingAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.cards.Cards; import mage.cards.CardsImpl; -import mage.constants.AsThoughEffectType; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; +import mage.constants.TargetController; import mage.constants.WatcherScope; import mage.constants.Zone; import mage.filter.FilterCard; @@ -42,7 +41,14 @@ public final class AbandonedSarcophagus extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); // You may cast nonland cards with cycling from your graveyard. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AbandonedSarcophagusCastFromGraveyardEffect())); + FilterCard filter = new FilterCard("nonland cards with cycling"); + filter.add(Predicates.not(new CardTypePredicate(CardType.LAND))); + filter.add(new AbilityPredicate(CyclingAbility.class)); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, + new PlayFromNotOwnHandZoneAllEffect(filter, + Zone.GRAVEYARD, true, TargetController.YOU, Duration.WhileOnBattlefield) + .setText("You may cast nonland cards with cycling from your graveyard")) + ); // If a card with cycling would be put into your graveyard from anywhere and it wasn't cycled, exile it instead. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new AbandonedSarcophagusReplacementEffect()), new AbandonedSarcophagusWatcher()); @@ -59,46 +65,6 @@ public final class AbandonedSarcophagus extends CardImpl { } } -class AbandonedSarcophagusCastFromGraveyardEffect extends AsThoughEffectImpl { - - private static final FilterCard filter = new FilterCard("nonland cards with cycling"); - - static { - filter.add(Predicates.not(new CardTypePredicate(CardType.LAND))); - filter.add(new AbilityPredicate(CyclingAbility.class)); - } - - AbandonedSarcophagusCastFromGraveyardEffect() { - super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.Benefit); - staticText = "You may cast nonland cards with cycling from your graveyard"; - } - - AbandonedSarcophagusCastFromGraveyardEffect(final AbandonedSarcophagusCastFromGraveyardEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public AbandonedSarcophagusCastFromGraveyardEffect copy() { - return new AbandonedSarcophagusCastFromGraveyardEffect(this); - } - - @Override - public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - Card card = game.getCard(objectId); - if (card != null) { - return (affectedControllerId.equals(source.getControllerId()) - && filter.match(card, game) - && game.getState().getZone(card.getId()) == Zone.GRAVEYARD); - } - return false; - } -} - class AbandonedSarcophagusReplacementEffect extends ReplacementEffectImpl { boolean cardHasCycling; diff --git a/Mage.Sets/src/mage/cards/a/AbbotOfKeralKeep.java b/Mage.Sets/src/mage/cards/a/AbbotOfKeralKeep.java index c8a371940d5..0d85e9cf3ce 100644 --- a/Mage.Sets/src/mage/cards/a/AbbotOfKeralKeep.java +++ b/Mage.Sets/src/mage/cards/a/AbbotOfKeralKeep.java @@ -1,4 +1,3 @@ - package mage.cards.a; import java.util.UUID; @@ -8,6 +7,7 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect; import mage.abilities.keyword.ProwessAbility; import mage.cards.Card; import mage.cards.CardImpl; @@ -75,7 +75,7 @@ class AbbotOfKeralKeepExileEffect extends OneShotEffect { if (card != null) { String exileName = sourcePermanent.getIdName() + " "; controller.moveCardsToExile(card, source, game, true, source.getSourceId(), exileName); - ContinuousEffect effect = new AbbotOfKeralKeepCastFromExileEffect(); + ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Duration.EndOfTurn); effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game))); game.addEffect(effect, source); } diff --git a/Mage.Sets/src/mage/cards/a/ActOnImpulse.java b/Mage.Sets/src/mage/cards/a/ActOnImpulse.java index 11bc0aed5b5..a2f44ab166f 100644 --- a/Mage.Sets/src/mage/cards/a/ActOnImpulse.java +++ b/Mage.Sets/src/mage/cards/a/ActOnImpulse.java @@ -1,4 +1,3 @@ - package mage.cards.a; import java.util.HashSet; @@ -6,9 +5,9 @@ import java.util.Set; import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -44,7 +43,7 @@ class ActOnImpulseExileEffect extends OneShotEffect { public ActOnImpulseExileEffect() { super(Outcome.Benefit); - this.staticText = "Exile the top three cards of your library. Until end of turn, you may play cards exiled this way."; + this.staticText = "Exile the top three cards of your library. Until end of turn, you may play cards exiled this way"; } public ActOnImpulseExileEffect(final ActOnImpulseExileEffect effect) { @@ -71,7 +70,7 @@ class ActOnImpulseExileEffect extends OneShotEffect { } } if (!cards.isEmpty()) { - ContinuousEffect effect = new ActOnImpulseMayPlayExiledEffect(); + ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn); effect.setTargetPointer(new FixedTargets(cards, game)); game.addEffect(effect, source); } @@ -82,31 +81,3 @@ class ActOnImpulseExileEffect extends OneShotEffect { } } - -class ActOnImpulseMayPlayExiledEffect extends AsThoughEffectImpl { - - public ActOnImpulseMayPlayExiledEffect() { - super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit); - } - - public ActOnImpulseMayPlayExiledEffect(final ActOnImpulseMayPlayExiledEffect effect) { - super(effect); - } - - @Override - public ActOnImpulseMayPlayExiledEffect copy() { - return new ActOnImpulseMayPlayExiledEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - return affectedControllerId.equals(source.getControllerId()) - && getTargetPointer().getTargets(game, source).contains(objectId); - } - -} diff --git a/Mage.Sets/src/mage/cards/a/AerialCaravan.java b/Mage.Sets/src/mage/cards/a/AerialCaravan.java index 933595fcd9b..27524c47b47 100644 --- a/Mage.Sets/src/mage/cards/a/AerialCaravan.java +++ b/Mage.Sets/src/mage/cards/a/AerialCaravan.java @@ -1,4 +1,3 @@ - package mage.cards.a; import java.util.UUID; @@ -6,18 +5,18 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AsThoughEffectType; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.SubType; +import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Library; @@ -81,7 +80,7 @@ class AerialCaravanExileEffect extends OneShotEffect { if (card != null) { String exileName = sourcePermanent.getIdName() + " "; controller.moveCardsToExile(card, source, game, true, source.getSourceId(), exileName); - ContinuousEffect effect = new AerialCaravanCastFromExileEffect(); + ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn); effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game))); game.addEffect(effect, source); } @@ -90,31 +89,3 @@ class AerialCaravanExileEffect extends OneShotEffect { return false; } } - -class AerialCaravanCastFromExileEffect extends AsThoughEffectImpl { - - public AerialCaravanCastFromExileEffect() { - super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit); - staticText = "You may play the card from exile"; - } - - public AerialCaravanCastFromExileEffect(final AerialCaravanCastFromExileEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public AerialCaravanCastFromExileEffect copy() { - return new AerialCaravanCastFromExileEffect(this); - } - - @Override - public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - return source.isControlledBy(affectedControllerId) - && objectId.equals(getTargetPointer().getFirst(game, source)); - } -} diff --git a/Mage.Sets/src/mage/cards/a/ApexOfPower.java b/Mage.Sets/src/mage/cards/a/ApexOfPower.java index 7cedb5425bb..edf76709889 100644 --- a/Mage.Sets/src/mage/cards/a/ApexOfPower.java +++ b/Mage.Sets/src/mage/cards/a/ApexOfPower.java @@ -4,14 +4,13 @@ import java.util.Set; import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect; import mage.abilities.effects.mana.AddManaOfAnyColorEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AsThoughEffectType; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; @@ -79,7 +78,7 @@ class ApexOfPowerSpellEffect extends OneShotEffect { if (card.isLand()) { continue; } - ContinuousEffect effect = new ApexOfPowerCastFromExileEffect(); + ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn); effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game))); game.addEffect(effect, source); } @@ -87,34 +86,6 @@ class ApexOfPowerSpellEffect extends OneShotEffect { } } -class ApexOfPowerCastFromExileEffect extends AsThoughEffectImpl { - - public ApexOfPowerCastFromExileEffect() { - super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit); - staticText = "You may play the card from exile"; - } - - public ApexOfPowerCastFromExileEffect(final ApexOfPowerCastFromExileEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public ApexOfPowerCastFromExileEffect copy() { - return new ApexOfPowerCastFromExileEffect(this); - } - - @Override - public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - return source.isControlledBy(affectedControllerId) - && objectId.equals(getTargetPointer().getFirst(game, source)); - } -} - class ApexOfPowerManaEffect extends OneShotEffect { public ApexOfPowerManaEffect() { diff --git a/Mage.Sets/src/mage/cards/c/ChandraPyromaster.java b/Mage.Sets/src/mage/cards/c/ChandraPyromaster.java index bccba205719..027213fdb3c 100644 --- a/Mage.Sets/src/mage/cards/c/ChandraPyromaster.java +++ b/Mage.Sets/src/mage/cards/c/ChandraPyromaster.java @@ -1,4 +1,3 @@ - package mage.cards.c; import java.util.HashSet; @@ -9,9 +8,9 @@ import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility; -import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect; import mage.abilities.effects.common.combat.CantBlockTargetEffect; import mage.cards.*; import mage.constants.*; @@ -20,7 +19,6 @@ import mage.filter.common.FilterInstantOrSorceryCard; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.stack.StackObject; -import mage.players.Library; import mage.players.Player; import mage.target.Target; import mage.target.TargetCard; @@ -177,12 +175,13 @@ class ChandraPyromasterEffect2 extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = source.getSourceObject(game); - if (controller != null && sourceObject != null && controller.getLibrary().hasCards()) { - Library library = controller.getLibrary(); - Card card = library.getFromTop(game); + if (controller != null && sourceObject != null) { + Card card = controller.getLibrary().getFromTop(game); if (card != null) { - controller.moveCardToExileWithInfo(card, source.getSourceId(), sourceObject.getIdName() + " ", source.getSourceId(), game, Zone.LIBRARY, true); - game.addEffect(new ChandraPyromasterPlayEffect(new MageObjectReference(card, game)), source); + controller.moveCards(card, Zone.EXILED, source, game); + ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn); + effect.setTargetPointer(new FixedTarget(card, game)); + game.addEffect(effect, source); } return true; } @@ -190,45 +189,6 @@ class ChandraPyromasterEffect2 extends OneShotEffect { } } -class ChandraPyromasterPlayEffect extends AsThoughEffectImpl { - - private final MageObjectReference objectReference; - - public ChandraPyromasterPlayEffect(MageObjectReference objectReference) { - super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit); - this.objectReference = objectReference; - staticText = "you may play that card until end of turn"; - } - - public ChandraPyromasterPlayEffect(final ChandraPyromasterPlayEffect effect) { - super(effect); - this.objectReference = effect.objectReference; - } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public ChandraPyromasterPlayEffect copy() { - return new ChandraPyromasterPlayEffect(this); - } - - @Override - public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - if (objectReference.refersTo(objectId, game) && affectedControllerId.equals(source.getControllerId())) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - return true; - } else { - discard(); - } - } - return false; - } -} - class ChandraPyromasterEffect3 extends OneShotEffect { public ChandraPyromasterEffect3() { diff --git a/Mage.Sets/src/mage/cards/c/CommuneWithLava.java b/Mage.Sets/src/mage/cards/c/CommuneWithLava.java index e38056a591d..08cf2112e74 100644 --- a/Mage.Sets/src/mage/cards/c/CommuneWithLava.java +++ b/Mage.Sets/src/mage/cards/c/CommuneWithLava.java @@ -1,4 +1,3 @@ - package mage.cards.c; import java.util.Set; @@ -23,7 +22,7 @@ import mage.util.CardUtil; public final class CommuneWithLava extends CardImpl { public CommuneWithLava(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{R}{R}"); // Exile the top X cards of your library. Until the end of your next turn, you may play those cards. this.getSpellAbility().addEffect(new CommuneWithLavaEffect()); diff --git a/Mage.Sets/src/mage/cards/c/CunningAbduction.java b/Mage.Sets/src/mage/cards/c/CunningAbduction.java index 1bbb4ac15b1..f34a14e72c5 100644 --- a/Mage.Sets/src/mage/cards/c/CunningAbduction.java +++ b/Mage.Sets/src/mage/cards/c/CunningAbduction.java @@ -1,4 +1,3 @@ - package mage.cards.c; import java.util.UUID; @@ -8,6 +7,7 @@ import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.AsThoughManaEffect; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -28,7 +28,7 @@ import mage.util.CardUtil; public final class CunningAbduction extends CardImpl { public CunningAbduction(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{U}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}{B}"); // Target opponent reveals their hand. You choose a nonland card from that player's hand and exile it. You may cast that card for as long as it remains exiled, and you may spend mana as though it were mana of any color to cast that spell. this.getSpellAbility().addTarget(new TargetOpponent()); @@ -82,10 +82,10 @@ class CunningAbductionExileEffect extends OneShotEffect { if (card != null) { // move card to exile UUID exileId = CardUtil.getCardExileZoneId(game, source); - controller.moveCardToExileWithInfo(card, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.HAND, true); + controller.moveCardsToExile(card, source, game, true, exileId, sourceObject.getIdName()); // allow to cast the card - ContinuousEffect effect = new CunningAbductionCastFromExileEffect(); - effect.setTargetPointer(new FixedTarget(card.getId())); + ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.Custom); + effect.setTargetPointer(new FixedTarget(card, game)); game.addEffect(effect, source); // and you may spend mana as though it were mana of any color to cast it effect = new CunningAbductionSpendAnyManaEffect(); @@ -99,41 +99,6 @@ class CunningAbductionExileEffect extends OneShotEffect { } } -class CunningAbductionCastFromExileEffect extends AsThoughEffectImpl { - - public CunningAbductionCastFromExileEffect() { - super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit); - staticText = "You may cast that card for as long as it remains exiled, and you may spend mana as though it were mana of any color to cast that spell"; - } - - public CunningAbductionCastFromExileEffect(final CunningAbductionCastFromExileEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public CunningAbductionCastFromExileEffect copy() { - return new CunningAbductionCastFromExileEffect(this); - } - - @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 - this.discard(); - } - return false; - } -} - class CunningAbductionSpendAnyManaEffect extends AsThoughEffectImpl implements AsThoughManaEffect { public CunningAbductionSpendAnyManaEffect() { diff --git a/Mage.Sets/src/mage/cards/d/DarkDecision.java b/Mage.Sets/src/mage/cards/d/DarkDecision.java index 880f0216af5..f89c73413ba 100644 --- a/Mage.Sets/src/mage/cards/d/DarkDecision.java +++ b/Mage.Sets/src/mage/cards/d/DarkDecision.java @@ -1,22 +1,20 @@ - package mage.cards.d; import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.costs.common.PayLifeCost; -import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AsThoughEffectType; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; +import mage.constants.Zone; import mage.filter.common.FilterNonlandCard; -import mage.game.ExileZone; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInLibrary; @@ -76,7 +74,7 @@ class DarkDecisionEffect extends OneShotEffect { Card card = game.getCard(targetId); if (card != null) { controller.moveCardsToExile(card, source, game, true, source.getSourceId(), sourceObject.getIdName()); - ContinuousEffect effect = new DarkDecisionMayPlayExiledEffect(); + ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn); effect.setTargetPointer(new FixedTarget(card.getId(), game)); game.addEffect(effect, source); } @@ -88,34 +86,3 @@ class DarkDecisionEffect extends OneShotEffect { } } - -class DarkDecisionMayPlayExiledEffect extends AsThoughEffectImpl { - - public DarkDecisionMayPlayExiledEffect() { - super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit); - } - - public DarkDecisionMayPlayExiledEffect(final DarkDecisionMayPlayExiledEffect effect) { - super(effect); - } - - @Override - public DarkDecisionMayPlayExiledEffect copy() { - return new DarkDecisionMayPlayExiledEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - if (objectId.equals(getTargetPointer().getFirst(game, source)) && affectedControllerId.equals(source.getControllerId())) { - ExileZone exileZone = game.getExile().getExileZone(source.getSourceId()); - return exileZone != null && exileZone.contains(getTargetPointer().getFirst(game, source)); - } - return false; - } - -} diff --git a/Mage.Sets/src/mage/cards/d/DarkDwellerOracle.java b/Mage.Sets/src/mage/cards/d/DarkDwellerOracle.java index bef6334009f..fc1d1a34269 100644 --- a/Mage.Sets/src/mage/cards/d/DarkDwellerOracle.java +++ b/Mage.Sets/src/mage/cards/d/DarkDwellerOracle.java @@ -6,17 +6,17 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect; import mage.cards.Card; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AsThoughEffectType; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; import static mage.filter.StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT; import mage.game.Game; import mage.game.permanent.Permanent; @@ -88,8 +88,8 @@ class DarkDwellerOracleExileEffect extends OneShotEffect { if (card != null) { String exileName = sourcePermanent.getIdName() + " "; controller.moveCardsToExile(card, source, game, true, source.getSourceId(), exileName); - ContinuousEffect effect = new DarkDwellerOracleCastFromExileEffect(); - effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game))); + ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn); + effect.setTargetPointer(new FixedTarget(card, game)); game.addEffect(effect, source); } return true; @@ -97,31 +97,3 @@ class DarkDwellerOracleExileEffect extends OneShotEffect { return false; } } - -class DarkDwellerOracleCastFromExileEffect extends AsThoughEffectImpl { - - public DarkDwellerOracleCastFromExileEffect() { - super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit); - staticText = "You may play the card from exile"; - } - - public DarkDwellerOracleCastFromExileEffect(final DarkDwellerOracleCastFromExileEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public DarkDwellerOracleCastFromExileEffect copy() { - return new DarkDwellerOracleCastFromExileEffect(this); - } - - @Override - public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - return source.isControlledBy(affectedControllerId) - && objectId.equals(getTargetPointer().getFirst(game, source)); - } -} diff --git a/Mage.Sets/src/mage/cards/d/DaxosOfMeletis.java b/Mage.Sets/src/mage/cards/d/DaxosOfMeletis.java index 0f13053b5a6..87131ba9ba9 100644 --- a/Mage.Sets/src/mage/cards/d/DaxosOfMeletis.java +++ b/Mage.Sets/src/mage/cards/d/DaxosOfMeletis.java @@ -1,4 +1,3 @@ - package mage.cards.d; import java.util.Objects; @@ -12,6 +11,7 @@ import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.AsThoughManaEffect; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect; import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; import mage.cards.Card; import mage.cards.CardImpl; @@ -39,7 +39,7 @@ public final class DaxosOfMeletis extends CardImpl { } public DaxosOfMeletis(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{W}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{U}"); this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.SOLDIER); @@ -91,7 +91,7 @@ class DaxosOfMeletisEffect extends OneShotEffect { Card card = damagedPlayer.getLibrary().getFromTop(game); if (card != null) { // move card to exile - controller.moveCardToExileWithInfo(card, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); + controller.moveCardsToExile(card, source, game, true, exileId, sourceObject.getIdName()); // player gains life int cmc = card.getConvertedManaCost(); if (cmc > 0) { @@ -100,10 +100,12 @@ class DaxosOfMeletisEffect extends OneShotEffect { // Add effects only if the card has a spellAbility (e.g. not for lands). if (card.getSpellAbility() != null) { // allow to cast the card - game.addEffect(new DaxosOfMeletisCastFromExileEffect(card.getId(), exileId), source); + ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn); + effect.setTargetPointer(new FixedTarget(card, game)); + game.addEffect(effect, source); // and you may spend mana as though it were mana of any color to cast it - ContinuousEffect effect = new DaxosOfMeletisSpendAnyManaEffect(); - effect.setTargetPointer(new FixedTarget(card.getId())); + effect = new DaxosOfMeletisSpendAnyManaEffect(); + effect.setTargetPointer(new FixedTarget(card, game)); game.addEffect(effect, source); } } diff --git a/Mage.Sets/src/mage/cards/d/DeadMansChest.java b/Mage.Sets/src/mage/cards/d/DeadMansChest.java index 24c8de7bdab..76a659af210 100644 --- a/Mage.Sets/src/mage/cards/d/DeadMansChest.java +++ b/Mage.Sets/src/mage/cards/d/DeadMansChest.java @@ -1,4 +1,3 @@ - package mage.cards.d; import java.util.Set; @@ -11,6 +10,7 @@ import mage.abilities.effects.AsThoughManaEffect; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect; import mage.abilities.keyword.EnchantAbility; import mage.cards.Card; import mage.cards.CardImpl; @@ -22,6 +22,7 @@ import mage.constants.ManaType; import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.TargetController; +import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerPredicate; import mage.game.Game; @@ -101,11 +102,11 @@ class DeadMansChestEffect extends OneShotEffect { controller.moveCardsToExile(cards, source, game, true, source.getSourceId(), sourceObject.getLogName()); for (Card card : cards) { if (!card.isLand()) { - ContinuousEffect effect = new DeadMansChestCastFromExileEffect(); - effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game))); + ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.Custom); + effect.setTargetPointer(new FixedTarget(card, game)); game.addEffect(effect, source); effect = new DeadMansChestSpendManaEffect(); - effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game))); + effect.setTargetPointer(new FixedTarget(card, game)); game.addEffect(effect, source); } } diff --git a/Mage.Sets/src/mage/cards/d/DireFleetDaredevil.java b/Mage.Sets/src/mage/cards/d/DireFleetDaredevil.java index 72fe39f0cae..f49e33e7050 100644 --- a/Mage.Sets/src/mage/cards/d/DireFleetDaredevil.java +++ b/Mage.Sets/src/mage/cards/d/DireFleetDaredevil.java @@ -1,4 +1,3 @@ - package mage.cards.d; import java.util.Objects; @@ -11,6 +10,7 @@ import mage.abilities.effects.AsThoughManaEffect; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect; import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.Card; import mage.cards.CardImpl; @@ -102,14 +102,14 @@ class DireFleetDaredevilEffect extends OneShotEffect { if (controller.moveCards(targetCard, Zone.EXILED, source, game)) { targetCard = game.getCard(targetCard.getId()); if (targetCard != null) { - ContinuousEffect effect = new DireFleetDaredevilPlayEffect(); - effect.setTargetPointer(new FixedTarget(targetCard.getId(), targetCard.getZoneChangeCounter(game))); + ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn); + effect.setTargetPointer(new FixedTarget(targetCard, game)); game.addEffect(effect, source); effect = new DireFleetDaredevilSpendAnyManaEffect(); - effect.setTargetPointer(new FixedTarget(targetCard.getId(), targetCard.getZoneChangeCounter(game))); + effect.setTargetPointer(new FixedTarget(targetCard, game)); game.addEffect(effect, source); effect = new DireFleetDaredevilReplacementEffect(); - effect.setTargetPointer(new FixedTarget(targetCard.getId(), targetCard.getZoneChangeCounter(game))); + effect.setTargetPointer(new FixedTarget(targetCard, game)); game.addEffect(effect, source); } @@ -121,41 +121,6 @@ class DireFleetDaredevilEffect extends OneShotEffect { } } -class DireFleetDaredevilPlayEffect extends AsThoughEffectImpl { - - public DireFleetDaredevilPlayEffect() { - super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit); - staticText = "You may cast that card this turn"; - } - - public DireFleetDaredevilPlayEffect(final DireFleetDaredevilPlayEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public DireFleetDaredevilPlayEffect copy() { - return new DireFleetDaredevilPlayEffect(this); - } - - @Override - public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - UUID targetId = getTargetPointer().getFirst(game, source); - if (targetId != null) { - return targetId.equals(objectId) - && source.isControlledBy(affectedControllerId); - } else { - // the target card has changed zone meanwhile, so the effect is no longer needed - discard(); - return false; - } - } -} - class DireFleetDaredevilSpendAnyManaEffect extends AsThoughEffectImpl implements AsThoughManaEffect { public DireFleetDaredevilSpendAnyManaEffect() { diff --git a/Mage.Sets/src/mage/cards/d/DreamPillager.java b/Mage.Sets/src/mage/cards/d/DreamPillager.java index e0eefc81fe7..67869fe5110 100644 --- a/Mage.Sets/src/mage/cards/d/DreamPillager.java +++ b/Mage.Sets/src/mage/cards/d/DreamPillager.java @@ -1,4 +1,3 @@ - package mage.cards.d; import java.util.Set; @@ -7,21 +6,23 @@ import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; import mage.constants.*; import mage.game.Game; import mage.game.events.DamagedPlayerEvent; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.players.Player; -import mage.target.targetpointer.FixedTarget; +import mage.target.targetpointer.FixedTargets; /** * @@ -30,7 +31,7 @@ import mage.target.targetpointer.FixedTarget; public final class DreamPillager extends CardImpl { public DreamPillager(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{R}{R}"); this.subtype.add(SubType.DRAGON); this.power = new MageInt(4); this.toughness = new MageInt(4); @@ -114,13 +115,15 @@ class DreamPillagerEffect extends OneShotEffect { Set cards = controller.getLibrary().getTopCards(game, amount); if (!cards.isEmpty()) { controller.moveCards(cards, Zone.EXILED, source, game); + Cards canBeCast = new CardsImpl(); for (Card card : cards) { if (!card.isLand()) { - ContinuousEffect effect = new DreamPillagerCastFromExileEffect(); - effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game))); - game.addEffect(effect, source); + canBeCast.add(card); } } + ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn); + effect.setTargetPointer(new FixedTargets(canBeCast, game)); + game.addEffect(effect, source); } return true; } @@ -129,31 +132,3 @@ class DreamPillagerEffect extends OneShotEffect { return false; } } - -class DreamPillagerCastFromExileEffect extends AsThoughEffectImpl { - - public DreamPillagerCastFromExileEffect() { - super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit); - staticText = "You may play the card from exile"; - } - - public DreamPillagerCastFromExileEffect(final DreamPillagerCastFromExileEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } - - @Override - public DreamPillagerCastFromExileEffect copy() { - return new DreamPillagerCastFromExileEffect(this); - } - - @Override - public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - return source.isControlledBy(affectedControllerId) - && objectId.equals(getTargetPointer().getFirst(game, source)); - } -} diff --git a/Mage.Sets/src/mage/cards/e/ElkinLair.java b/Mage.Sets/src/mage/cards/e/ElkinLair.java index 41b7287efdb..8539e15b47e 100644 --- a/Mage.Sets/src/mage/cards/e/ElkinLair.java +++ b/Mage.Sets/src/mage/cards/e/ElkinLair.java @@ -1,4 +1,3 @@ - package mage.cards.e; import java.util.Set; @@ -10,6 +9,7 @@ import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbil import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -20,9 +20,9 @@ import mage.constants.Outcome; import mage.constants.SuperType; import mage.constants.TargetController; import mage.constants.Zone; +import mage.filter.FilterCard; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.filter.FilterCard; import mage.players.Player; import mage.target.targetpointer.FixedTarget; import mage.util.RandomUtil; @@ -81,8 +81,8 @@ class ElkinLairUpkeepEffect extends OneShotEffect { String exileName = sourcePermanent.getIdName() + " asThoughEffectsList = getApplicableAsThoughEffects(type, game); - for (AsThoughEffect effect : asThoughEffectsList) { - Set abilities = asThoughEffectsMap.get(type).getAbility(effect.getId()); - for (Ability ability : abilities) { - if (affectedAbility == null) { - if (effect.applies(objectId, ability, controllerId, game)) { + if (!asThoughEffectsList.isEmpty()) { + UUID idToCheck; + if (affectedAbility != null && affectedAbility.getSourceObject(game) instanceof SplitCardHalf) { + idToCheck = ((SplitCardHalf) affectedAbility.getSourceObject(game)).getParentCard().getId(); + } else { + idToCheck = objectId; + } + for (AsThoughEffect effect : asThoughEffectsList) { + Set abilities = asThoughEffectsMap.get(type).getAbility(effect.getId()); + for (Ability ability : abilities) { + if (affectedAbility == null) { + if (effect.applies(idToCheck, ability, controllerId, game)) { + return new MageObjectReference(ability.getSourceObject(game), game); + } + } else if (effect.applies(idToCheck, affectedAbility, ability, game, controllerId)) { return new MageObjectReference(ability.getSourceObject(game), game); } - } else if (effect.applies(objectId, affectedAbility, ability, game, controllerId)) { - return new MageObjectReference(ability.getSourceObject(game), game); } } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/AttachEffect.java b/Mage/src/main/java/mage/abilities/effects/common/AttachEffect.java index 989a71b1c24..11fae020f2e 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/AttachEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/AttachEffect.java @@ -1,4 +1,3 @@ - package mage.abilities.effects.common; import mage.abilities.Ability; @@ -39,7 +38,9 @@ public class AttachEffect extends OneShotEffect { Permanent sourcePermanent = game.getPermanent(source.getSourceId()); if (sourcePermanent != null) { int zcc = game.getState().getZoneChangeCounter(sourcePermanent.getId()); - if (zcc == source.getSourceObjectZoneChangeCounter() || zcc == source.getSourceObjectZoneChangeCounter() + 1) { + if (zcc == source.getSourceObjectZoneChangeCounter() + || zcc == source.getSourceObjectZoneChangeCounter() + 1 + || zcc == source.getSourceObjectZoneChangeCounter() + 2) { Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); if (permanent != null) { return permanent.addAttachment(source.getSourceId(), game); diff --git a/Mage/src/main/java/mage/abilities/effects/common/asthought/PlayFromNotOwnHandZoneAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/asthought/PlayFromNotOwnHandZoneAllEffect.java new file mode 100644 index 00000000000..5b3927f2139 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/asthought/PlayFromNotOwnHandZoneAllEffect.java @@ -0,0 +1,74 @@ +package mage.abilities.effects.common.asthought; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.cards.Card; +import mage.constants.AsThoughEffectType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.game.Game; + +/** + * + * @author LevelX2 + */ +public class PlayFromNotOwnHandZoneAllEffect extends AsThoughEffectImpl { + + private final FilterCard filter; + private final Zone fromZone; + private final boolean onlyOwnedCards; + private final TargetController allowedCaster; + + public PlayFromNotOwnHandZoneAllEffect(FilterCard filter, Zone fromZone, boolean onlyOwnedCards, TargetController allowedCaster, Duration duration) { + super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, duration, Outcome.Benefit); + this.filter = filter; + this.fromZone = fromZone; + this.onlyOwnedCards = onlyOwnedCards; + this.allowedCaster = allowedCaster; + } + + public PlayFromNotOwnHandZoneAllEffect(final PlayFromNotOwnHandZoneAllEffect effect) { + super(effect); + this.filter = effect.filter; + this.fromZone = effect.fromZone; + this.onlyOwnedCards = effect.onlyOwnedCards; + this.allowedCaster = effect.allowedCaster; + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public PlayFromNotOwnHandZoneAllEffect copy() { + return new PlayFromNotOwnHandZoneAllEffect(this); + } + + @Override + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + Card card = game.getCard(objectId); + if (card != null) { + switch (allowedCaster) { + case YOU: + if (affectedControllerId != source.getControllerId()) { + return false; + } + break; + case OPPONENT: + if (!game.getOpponents(source.getControllerId()).contains(affectedControllerId)) { + return false; + } + break; + } + return !onlyOwnedCards || card.getOwnerId().equals(source.getControllerId()) + && filter.match(card, game) + && game.getState().getZone(card.getId()).match(fromZone); + } + return false; + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/asthought/PlayFromNotOwnHandZoneTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/asthought/PlayFromNotOwnHandZoneTargetEffect.java new file mode 100644 index 00000000000..ec878eb5b14 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/asthought/PlayFromNotOwnHandZoneTargetEffect.java @@ -0,0 +1,82 @@ +package mage.abilities.effects.common.asthought; + +import java.util.List; +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.constants.AsThoughEffectType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.game.Game; + +/** + * + * @author LevelX2 + */ +public class PlayFromNotOwnHandZoneTargetEffect extends AsThoughEffectImpl { + + private final Zone fromZone; + private final TargetController allowedCaster; + + public PlayFromNotOwnHandZoneTargetEffect() { + this(Duration.EndOfTurn); + } + + public PlayFromNotOwnHandZoneTargetEffect(Duration duration) { + this(Zone.ALL, TargetController.YOU, duration); + } + + public PlayFromNotOwnHandZoneTargetEffect(Zone fromZone, Duration duration) { + this(fromZone, TargetController.YOU, duration); + } + + public PlayFromNotOwnHandZoneTargetEffect(Zone fromZone, TargetController allowedCaster, Duration duration) { + super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, duration, Outcome.Benefit); + this.fromZone = fromZone; + this.allowedCaster = allowedCaster; + } + + public PlayFromNotOwnHandZoneTargetEffect(final PlayFromNotOwnHandZoneTargetEffect effect) { + super(effect); + this.fromZone = effect.fromZone; + this.allowedCaster = effect.allowedCaster; + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public PlayFromNotOwnHandZoneTargetEffect copy() { + return new PlayFromNotOwnHandZoneTargetEffect(this); + } + + @Override + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + switch (allowedCaster) { + case YOU: + if (affectedControllerId != source.getControllerId()) { + return false; + } + break; + case OPPONENT: + if (!game.getOpponents(source.getControllerId()).contains(affectedControllerId)) { + return false; + } + break; + case ANY: + break; + } + List targets = getTargetPointer().getTargets(game, source); + if (targets.isEmpty()) { + this.discard(); + return false; + } + return targets.contains(objectId) + && affectedControllerId.equals(source.getControllerId()) + && game.getState().getZone(objectId).match(fromZone); + } +} diff --git a/Mage/src/main/java/mage/abilities/keyword/AftermathAbility.java b/Mage/src/main/java/mage/abilities/keyword/AftermathAbility.java index d661dea2150..bb9c97f3ccd 100644 --- a/Mage/src/main/java/mage/abilities/keyword/AftermathAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/AftermathAbility.java @@ -1,4 +1,3 @@ - package mage.abilities.keyword; import java.util.UUID; @@ -68,16 +67,19 @@ class AftermathCastFromGraveyard extends AsThoughEffectImpl { } @Override - public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - if (objectId.equals(source.getSourceId()) + public boolean applies(UUID objectId, Ability affectedAbility, Ability source, Game game, UUID affectedControllerId) { + if (affectedAbility != null && affectedAbility.getSourceId().equals(source.getSourceId()) && affectedControllerId.equals(source.getControllerId())) { - Card card = game.getCard(source.getSourceId()); - if (card != null && game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) { - return true; - } + return game.getState().getZone(objectId).equals(Zone.GRAVEYARD); } return false; } + + @Override + public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { + return false; + } + } class AftermathCantCastFromHand extends ContinuousRuleModifyingEffectImpl { @@ -168,17 +170,14 @@ class AftermathExileAsResolvesFromGraveyard extends ReplacementEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - UUID sourceId = source.getSourceId(); Card sourceCard = game.getCard(source.getSourceId()); if (sourceCard instanceof SplitCardHalf) { sourceCard = ((SplitCardHalf) sourceCard).getParentCard(); - sourceId = sourceCard.getId(); } - if (sourceCard != null) { Player player = game.getPlayer(sourceCard.getOwnerId()); if (player != null) { - return player.moveCardToExileWithInfo(sourceCard, null, "", sourceId, game, ((ZoneChangeEvent) event).getFromZone(), true); + return player.moveCards(sourceCard, Zone.EXILED, source, game); } } return false; diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index 2a0560ecc4b..2659dfd1450 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -1,5 +1,9 @@ package mage.players; +import java.io.Serializable; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.Map.Entry; import mage.ConditionalMana; import mage.MageObject; import mage.MageObjectReference; @@ -68,11 +72,6 @@ import mage.util.GameLog; import mage.util.RandomUtil; import org.apache.log4j.Logger; -import java.io.Serializable; -import java.text.SimpleDateFormat; -import java.util.*; -import java.util.Map.Entry; - public abstract class PlayerImpl implements Player, Serializable { private static final Logger logger = Logger.getLogger(PlayerImpl.class); @@ -2563,7 +2562,7 @@ public abstract class PlayerImpl implements Player, Serializable { /** * @param game * @param appliedEffects - * @param numSides Number of sides the dice has + * @param numSides Number of sides the dice has * @return the number that the player rolled */ @Override @@ -2597,10 +2596,10 @@ public abstract class PlayerImpl implements Player, Serializable { /** * @param game * @param appliedEffects - * @param numberChaosSides The number of chaos sides the planar die - * currently has (normally 1 but can be 5) + * @param numberChaosSides The number of chaos sides the planar die + * currently has (normally 1 but can be 5) * @param numberPlanarSides The number of chaos sides the planar die - * currently has (normally 1) + * currently has (normally 1) * @return the outcome that the player rolled. Either ChaosRoll, PlanarRoll * or NilRoll */ @@ -2757,7 +2756,7 @@ public abstract class PlayerImpl implements Player, Serializable { /** * @param ability - * @param available if null, it won't be checked if enough mana is available + * @param available if null, it won't be checked if enough mana is available * @param sourceObject * @param game * @return @@ -2927,7 +2926,7 @@ public abstract class PlayerImpl implements Player, Serializable { } private void getPlayableFromGraveyardCard(Game game, Card card, Abilities candidateAbilities, ManaOptions availableMana, List output) { - MageObjectReference permittingObject = game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, null, this.getId(), game); + MageObjectReference permittingObject = game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, card.getSpellAbility(), this.getId(), game); for (ActivatedAbility ability : candidateAbilities.getActivatedAbilities(Zone.ALL)) { boolean possible = false; if (ability.getZone().match(Zone.GRAVEYARD)) { @@ -3033,7 +3032,7 @@ public abstract class PlayerImpl implements Player, Serializable { if (player != null) { if (/*player.isTopCardRevealed() &&*/player.getLibrary().hasCards()) { Card card = player.getLibrary().getFromTop(game); - if (null != game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, null, getId(), game)) { + if (null != game.getContinuousEffects().asThough(card.getId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, card.getSpellAbility(), getId(), game)) { for (ActivatedAbility ability : card.getAbilities().getActivatedAbilities(Zone.HAND)) { if (ability instanceof SpellAbility || ability instanceof PlayLandAbility) { playable.add(ability); @@ -3309,7 +3308,7 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean canPaySacrificeCost(Permanent permanent, UUID sourceId, - UUID controllerId, Game game + UUID controllerId, Game game ) { return sacrificeCostFilter == null || !sacrificeCostFilter.match(permanent, sourceId, controllerId, game); } @@ -3457,8 +3456,8 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean moveCards(Card card, Zone toZone, - Ability source, Game game, - boolean tapped, boolean faceDown, boolean byOwner, List appliedEffects + Ability source, Game game, + boolean tapped, boolean faceDown, boolean byOwner, List appliedEffects ) { Set cardList = new HashSet<>(); if (card != null) { @@ -3469,22 +3468,22 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean moveCards(Cards cards, Zone toZone, - Ability source, Game game + Ability source, Game game ) { return moveCards(cards.getCards(game), toZone, source, game); } @Override public boolean moveCards(Set cards, Zone toZone, - Ability source, Game game + Ability source, Game game ) { return moveCards(cards, toZone, source, game, false, false, false, null); } @Override public boolean moveCards(Set cards, Zone toZone, - Ability source, Game game, - boolean tapped, boolean faceDown, boolean byOwner, List appliedEffects + Ability source, Game game, + boolean tapped, boolean faceDown, boolean byOwner, List appliedEffects ) { if (cards.isEmpty()) { return true; @@ -3570,8 +3569,8 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean moveCardsToExile(Card card, Ability source, - Game game, boolean withName, UUID exileId, - String exileZoneName + Game game, boolean withName, UUID exileId, + String exileZoneName ) { Set cards = new HashSet<>(); cards.add(card); @@ -3580,8 +3579,8 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean moveCardsToExile(Set cards, Ability source, - Game game, boolean withName, UUID exileId, - String exileZoneName + Game game, boolean withName, UUID exileId, + String exileZoneName ) { if (cards.isEmpty()) { return true; @@ -3596,14 +3595,14 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean moveCardToHandWithInfo(Card card, UUID sourceId, - Game game + Game game ) { return this.moveCardToHandWithInfo(card, sourceId, game, true); } @Override public boolean moveCardToHandWithInfo(Card card, UUID sourceId, - Game game, boolean withName + Game game, boolean withName ) { boolean result = false; Zone fromZone = game.getState().getZone(card.getId()); @@ -3628,7 +3627,7 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public Set moveCardsToGraveyardWithInfo(Set allCards, Ability source, - Game game, Zone fromZone + Game game, Zone fromZone ) { UUID sourceId = source == null ? null : source.getSourceId(); Set movedCards = new LinkedHashSet<>(); @@ -3636,7 +3635,7 @@ public abstract class PlayerImpl implements Player, Serializable { // identify cards from one owner Cards cards = new CardsImpl(); UUID ownerId = null; - for (Iterator it = allCards.iterator(); it.hasNext(); ) { + for (Iterator it = allCards.iterator(); it.hasNext();) { Card card = it.next(); if (cards.isEmpty()) { ownerId = card.getOwnerId(); @@ -3697,7 +3696,7 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean moveCardToGraveyardWithInfo(Card card, UUID sourceId, - Game game, Zone fromZone + Game game, Zone fromZone ) { if (card == null) { return false; @@ -3726,8 +3725,8 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean moveCardToLibraryWithInfo(Card card, UUID sourceId, - Game game, Zone fromZone, - boolean toTop, boolean withName + Game game, Zone fromZone, + boolean toTop, boolean withName ) { if (card == null) { return false; @@ -3761,7 +3760,7 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean moveCardToExileWithInfo(Card card, UUID exileId, String exileName, UUID sourceId, - Game game, Zone fromZone, boolean withName) { + Game game, Zone fromZone, boolean withName) { if (card == null) { return false; } diff --git a/Mage/src/main/java/mage/target/targetpointer/FixedTarget.java b/Mage/src/main/java/mage/target/targetpointer/FixedTarget.java index c931962322d..c8a14e5c270 100644 --- a/Mage/src/main/java/mage/target/targetpointer/FixedTarget.java +++ b/Mage/src/main/java/mage/target/targetpointer/FixedTarget.java @@ -21,6 +21,12 @@ public class FixedTarget implements TargetPointer { this.initialized = false; } + public FixedTarget(Card card, Game game) { + this.targetId = card.getId(); + this.zoneChangeCounter = card.getZoneChangeCounter(game); + this.initialized = true; + } + public FixedTarget(Permanent permanent, Game game) { this.targetId = permanent.getId(); this.zoneChangeCounter = permanent.getZoneChangeCounter(game);