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).

This commit is contained in:
LevelX2 2018-10-03 13:44:01 +02:00
parent c097ec053f
commit c41c6e1fe9
25 changed files with 304 additions and 476 deletions

View file

@ -1,4 +1,3 @@
package mage.cards.a; package mage.cards.a;
import java.util.HashMap; import java.util.HashMap;
@ -7,18 +6,18 @@ import java.util.Map.Entry;
import java.util.UUID; import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneAllEffect;
import mage.abilities.keyword.CyclingAbility; import mage.abilities.keyword.CyclingAbility;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.cards.Cards; import mage.cards.Cards;
import mage.cards.CardsImpl; import mage.cards.CardsImpl;
import mage.constants.AsThoughEffectType;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.constants.WatcherScope; import mage.constants.WatcherScope;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.FilterCard; import mage.filter.FilterCard;
@ -42,7 +41,14 @@ public final class AbandonedSarcophagus extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
// You may cast nonland cards with cycling from your graveyard. // 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. // 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()); 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 { class AbandonedSarcophagusReplacementEffect extends ReplacementEffectImpl {
boolean cardHasCycling; boolean cardHasCycling;

View file

@ -1,4 +1,3 @@
package mage.cards.a; package mage.cards.a;
import java.util.UUID; import java.util.UUID;
@ -8,6 +7,7 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.abilities.keyword.ProwessAbility; import mage.abilities.keyword.ProwessAbility;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
@ -75,7 +75,7 @@ class AbbotOfKeralKeepExileEffect extends OneShotEffect {
if (card != null) { if (card != null) {
String exileName = sourcePermanent.getIdName() + " <this card may be played the turn it was exiled>"; String exileName = sourcePermanent.getIdName() + " <this card may be played the turn it was exiled>";
controller.moveCardsToExile(card, source, game, true, source.getSourceId(), exileName); 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))); effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game)));
game.addEffect(effect, source); game.addEffect(effect, source);
} }

View file

@ -1,4 +1,3 @@
package mage.cards.a; package mage.cards.a;
import java.util.HashSet; import java.util.HashSet;
@ -6,9 +5,9 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -44,7 +43,7 @@ class ActOnImpulseExileEffect extends OneShotEffect {
public ActOnImpulseExileEffect() { public ActOnImpulseExileEffect() {
super(Outcome.Benefit); 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) { public ActOnImpulseExileEffect(final ActOnImpulseExileEffect effect) {
@ -71,7 +70,7 @@ class ActOnImpulseExileEffect extends OneShotEffect {
} }
} }
if (!cards.isEmpty()) { if (!cards.isEmpty()) {
ContinuousEffect effect = new ActOnImpulseMayPlayExiledEffect(); ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn);
effect.setTargetPointer(new FixedTargets(cards, game)); effect.setTargetPointer(new FixedTargets(cards, game));
game.addEffect(effect, source); 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);
}
}

View file

@ -1,4 +1,3 @@
package mage.cards.a; package mage.cards.a;
import java.util.UUID; import java.util.UUID;
@ -6,18 +5,18 @@ import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AsThoughEffectType;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.players.Library; import mage.players.Library;
@ -81,7 +80,7 @@ class AerialCaravanExileEffect extends OneShotEffect {
if (card != null) { if (card != null) {
String exileName = sourcePermanent.getIdName() + " <this card may be played the turn it was exiled>"; String exileName = sourcePermanent.getIdName() + " <this card may be played the turn it was exiled>";
controller.moveCardsToExile(card, source, game, true, source.getSourceId(), exileName); 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))); effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game)));
game.addEffect(effect, source); game.addEffect(effect, source);
} }
@ -90,31 +89,3 @@ class AerialCaravanExileEffect extends OneShotEffect {
return false; 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));
}
}

View file

@ -4,14 +4,13 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.abilities.effects.mana.AddManaOfAnyColorEffect; import mage.abilities.effects.mana.AddManaOfAnyColorEffect;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AsThoughEffectType;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
@ -79,7 +78,7 @@ class ApexOfPowerSpellEffect extends OneShotEffect {
if (card.isLand()) { if (card.isLand()) {
continue; continue;
} }
ContinuousEffect effect = new ApexOfPowerCastFromExileEffect(); ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn);
effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game))); effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game)));
game.addEffect(effect, source); 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 { class ApexOfPowerManaEffect extends OneShotEffect {
public ApexOfPowerManaEffect() { public ApexOfPowerManaEffect() {

View file

@ -1,4 +1,3 @@
package mage.cards.c; package mage.cards.c;
import java.util.HashSet; import java.util.HashSet;
@ -9,9 +8,9 @@ import mage.MageObjectReference;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility; import mage.abilities.LoyaltyAbility;
import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility; import mage.abilities.common.PlaneswalkerEntersWithLoyaltyCountersAbility;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.abilities.effects.common.combat.CantBlockTargetEffect; import mage.abilities.effects.common.combat.CantBlockTargetEffect;
import mage.cards.*; import mage.cards.*;
import mage.constants.*; import mage.constants.*;
@ -20,7 +19,6 @@ import mage.filter.common.FilterInstantOrSorceryCard;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.game.stack.StackObject; import mage.game.stack.StackObject;
import mage.players.Library;
import mage.players.Player; import mage.players.Player;
import mage.target.Target; import mage.target.Target;
import mage.target.TargetCard; import mage.target.TargetCard;
@ -177,12 +175,13 @@ class ChandraPyromasterEffect2 extends OneShotEffect {
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = source.getSourceObject(game); MageObject sourceObject = source.getSourceObject(game);
if (controller != null && sourceObject != null && controller.getLibrary().hasCards()) { if (controller != null && sourceObject != null) {
Library library = controller.getLibrary(); Card card = controller.getLibrary().getFromTop(game);
Card card = library.getFromTop(game);
if (card != null) { if (card != null) {
controller.moveCardToExileWithInfo(card, source.getSourceId(), sourceObject.getIdName() + " <this card may be played the turn it was exiled>", source.getSourceId(), game, Zone.LIBRARY, true); controller.moveCards(card, Zone.EXILED, source, game);
game.addEffect(new ChandraPyromasterPlayEffect(new MageObjectReference(card, game)), source); ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn);
effect.setTargetPointer(new FixedTarget(card, game));
game.addEffect(effect, source);
} }
return true; 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 { class ChandraPyromasterEffect3 extends OneShotEffect {
public ChandraPyromasterEffect3() { public ChandraPyromasterEffect3() {

View file

@ -1,4 +1,3 @@
package mage.cards.c; package mage.cards.c;
import java.util.Set; import java.util.Set;

View file

@ -1,4 +1,3 @@
package mage.cards.c; package mage.cards.c;
import java.util.UUID; import java.util.UUID;
@ -8,6 +7,7 @@ import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.AsThoughManaEffect; import mage.abilities.effects.AsThoughManaEffect;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -82,10 +82,10 @@ class CunningAbductionExileEffect extends OneShotEffect {
if (card != null) { if (card != null) {
// move card to exile // move card to exile
UUID exileId = CardUtil.getCardExileZoneId(game, source); 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 // allow to cast the card
ContinuousEffect effect = new CunningAbductionCastFromExileEffect(); ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.Custom);
effect.setTargetPointer(new FixedTarget(card.getId())); effect.setTargetPointer(new FixedTarget(card, game));
game.addEffect(effect, source); game.addEffect(effect, source);
// and you may spend mana as though it were mana of any color to cast it // and you may spend mana as though it were mana of any color to cast it
effect = new CunningAbductionSpendAnyManaEffect(); 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 { class CunningAbductionSpendAnyManaEffect extends AsThoughEffectImpl implements AsThoughManaEffect {
public CunningAbductionSpendAnyManaEffect() { public CunningAbductionSpendAnyManaEffect() {

View file

@ -1,22 +1,20 @@
package mage.cards.d; package mage.cards.d;
import java.util.UUID; import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.costs.common.PayLifeCost; import mage.abilities.costs.common.PayLifeCost;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AsThoughEffectType;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.common.FilterNonlandCard; import mage.filter.common.FilterNonlandCard;
import mage.game.ExileZone;
import mage.game.Game; import mage.game.Game;
import mage.players.Player; import mage.players.Player;
import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetCardInLibrary;
@ -76,7 +74,7 @@ class DarkDecisionEffect extends OneShotEffect {
Card card = game.getCard(targetId); Card card = game.getCard(targetId);
if (card != null) { if (card != null) {
controller.moveCardsToExile(card, source, game, true, source.getSourceId(), sourceObject.getIdName()); 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)); effect.setTargetPointer(new FixedTarget(card.getId(), game));
game.addEffect(effect, source); 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;
}
}

View file

@ -6,17 +6,17 @@ import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.cards.Card; import mage.cards.Card;
import mage.constants.SubType;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AsThoughEffectType;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import static mage.filter.StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT; import static mage.filter.StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
@ -88,8 +88,8 @@ class DarkDwellerOracleExileEffect extends OneShotEffect {
if (card != null) { if (card != null) {
String exileName = sourcePermanent.getIdName() + " <this card may be played the turn it was exiled>"; String exileName = sourcePermanent.getIdName() + " <this card may be played the turn it was exiled>";
controller.moveCardsToExile(card, source, game, true, source.getSourceId(), exileName); controller.moveCardsToExile(card, source, game, true, source.getSourceId(), exileName);
ContinuousEffect effect = new DarkDwellerOracleCastFromExileEffect(); ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn);
effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game))); effect.setTargetPointer(new FixedTarget(card, game));
game.addEffect(effect, source); game.addEffect(effect, source);
} }
return true; return true;
@ -97,31 +97,3 @@ class DarkDwellerOracleExileEffect extends OneShotEffect {
return false; 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));
}
}

View file

@ -1,4 +1,3 @@
package mage.cards.d; package mage.cards.d;
import java.util.Objects; import java.util.Objects;
@ -12,6 +11,7 @@ import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.AsThoughManaEffect; import mage.abilities.effects.AsThoughManaEffect;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
@ -91,7 +91,7 @@ class DaxosOfMeletisEffect extends OneShotEffect {
Card card = damagedPlayer.getLibrary().getFromTop(game); Card card = damagedPlayer.getLibrary().getFromTop(game);
if (card != null) { if (card != null) {
// move card to exile // 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 // player gains life
int cmc = card.getConvertedManaCost(); int cmc = card.getConvertedManaCost();
if (cmc > 0) { 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). // Add effects only if the card has a spellAbility (e.g. not for lands).
if (card.getSpellAbility() != null) { if (card.getSpellAbility() != null) {
// allow to cast the card // 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 // and you may spend mana as though it were mana of any color to cast it
ContinuousEffect effect = new DaxosOfMeletisSpendAnyManaEffect(); effect = new DaxosOfMeletisSpendAnyManaEffect();
effect.setTargetPointer(new FixedTarget(card.getId())); effect.setTargetPointer(new FixedTarget(card, game));
game.addEffect(effect, source); game.addEffect(effect, source);
} }
} }

View file

@ -1,4 +1,3 @@
package mage.cards.d; package mage.cards.d;
import java.util.Set; import java.util.Set;
@ -11,6 +10,7 @@ import mage.abilities.effects.AsThoughManaEffect;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.abilities.keyword.EnchantAbility; import mage.abilities.keyword.EnchantAbility;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
@ -22,6 +22,7 @@ import mage.constants.ManaType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.TargetController; import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerPredicate; import mage.filter.predicate.permanent.ControllerPredicate;
import mage.game.Game; import mage.game.Game;
@ -101,11 +102,11 @@ class DeadMansChestEffect extends OneShotEffect {
controller.moveCardsToExile(cards, source, game, true, source.getSourceId(), sourceObject.getLogName()); controller.moveCardsToExile(cards, source, game, true, source.getSourceId(), sourceObject.getLogName());
for (Card card : cards) { for (Card card : cards) {
if (!card.isLand()) { if (!card.isLand()) {
ContinuousEffect effect = new DeadMansChestCastFromExileEffect(); ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.Custom);
effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game))); effect.setTargetPointer(new FixedTarget(card, game));
game.addEffect(effect, source); game.addEffect(effect, source);
effect = new DeadMansChestSpendManaEffect(); effect = new DeadMansChestSpendManaEffect();
effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game))); effect.setTargetPointer(new FixedTarget(card, game));
game.addEffect(effect, source); game.addEffect(effect, source);
} }
} }

View file

@ -1,4 +1,3 @@
package mage.cards.d; package mage.cards.d;
import java.util.Objects; import java.util.Objects;
@ -11,6 +10,7 @@ import mage.abilities.effects.AsThoughManaEffect;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
@ -102,14 +102,14 @@ class DireFleetDaredevilEffect extends OneShotEffect {
if (controller.moveCards(targetCard, Zone.EXILED, source, game)) { if (controller.moveCards(targetCard, Zone.EXILED, source, game)) {
targetCard = game.getCard(targetCard.getId()); targetCard = game.getCard(targetCard.getId());
if (targetCard != null) { if (targetCard != null) {
ContinuousEffect effect = new DireFleetDaredevilPlayEffect(); ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn);
effect.setTargetPointer(new FixedTarget(targetCard.getId(), targetCard.getZoneChangeCounter(game))); effect.setTargetPointer(new FixedTarget(targetCard, game));
game.addEffect(effect, source); game.addEffect(effect, source);
effect = new DireFleetDaredevilSpendAnyManaEffect(); effect = new DireFleetDaredevilSpendAnyManaEffect();
effect.setTargetPointer(new FixedTarget(targetCard.getId(), targetCard.getZoneChangeCounter(game))); effect.setTargetPointer(new FixedTarget(targetCard, game));
game.addEffect(effect, source); game.addEffect(effect, source);
effect = new DireFleetDaredevilReplacementEffect(); effect = new DireFleetDaredevilReplacementEffect();
effect.setTargetPointer(new FixedTarget(targetCard.getId(), targetCard.getZoneChangeCounter(game))); effect.setTargetPointer(new FixedTarget(targetCard, game));
game.addEffect(effect, source); 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 { class DireFleetDaredevilSpendAnyManaEffect extends AsThoughEffectImpl implements AsThoughManaEffect {
public DireFleetDaredevilSpendAnyManaEffect() { public DireFleetDaredevilSpendAnyManaEffect() {

View file

@ -1,4 +1,3 @@
package mage.cards.d; package mage.cards.d;
import java.util.Set; import java.util.Set;
@ -7,21 +6,23 @@ import mage.MageInt;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl; import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.*; import mage.constants.*;
import mage.game.Game; import mage.game.Game;
import mage.game.events.DamagedPlayerEvent; import mage.game.events.DamagedPlayerEvent;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType; import mage.game.events.GameEvent.EventType;
import mage.players.Player; import mage.players.Player;
import mage.target.targetpointer.FixedTarget; import mage.target.targetpointer.FixedTargets;
/** /**
* *
@ -114,14 +115,16 @@ class DreamPillagerEffect extends OneShotEffect {
Set<Card> cards = controller.getLibrary().getTopCards(game, amount); Set<Card> cards = controller.getLibrary().getTopCards(game, amount);
if (!cards.isEmpty()) { if (!cards.isEmpty()) {
controller.moveCards(cards, Zone.EXILED, source, game); controller.moveCards(cards, Zone.EXILED, source, game);
Cards canBeCast = new CardsImpl();
for (Card card : cards) { for (Card card : cards) {
if (!card.isLand()) { if (!card.isLand()) {
ContinuousEffect effect = new DreamPillagerCastFromExileEffect(); canBeCast.add(card);
effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game))); }
}
ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn);
effect.setTargetPointer(new FixedTargets(canBeCast, game));
game.addEffect(effect, source); game.addEffect(effect, source);
} }
}
}
return true; return true;
} }
return true; return true;
@ -129,31 +132,3 @@ class DreamPillagerEffect extends OneShotEffect {
return false; 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));
}
}

View file

@ -1,4 +1,3 @@
package mage.cards.e; package mage.cards.e;
import java.util.Set; import java.util.Set;
@ -10,6 +9,7 @@ import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbil
import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -20,9 +20,9 @@ import mage.constants.Outcome;
import mage.constants.SuperType; import mage.constants.SuperType;
import mage.constants.TargetController; import mage.constants.TargetController;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.filter.FilterCard;
import mage.players.Player; import mage.players.Player;
import mage.target.targetpointer.FixedTarget; import mage.target.targetpointer.FixedTarget;
import mage.util.RandomUtil; import mage.util.RandomUtil;
@ -81,8 +81,8 @@ class ElkinLairUpkeepEffect extends OneShotEffect {
String exileName = sourcePermanent.getIdName() + " <this card may be played the turn it was exiled"; String exileName = sourcePermanent.getIdName() + " <this card may be played the turn it was exiled";
player.moveCardsToExile(card, source, game, true, source.getSourceId(), exileName); player.moveCardsToExile(card, source, game, true, source.getSourceId(), exileName);
if (game.getState().getZone(card.getId()) == Zone.EXILED) { if (game.getState().getZone(card.getId()) == Zone.EXILED) {
ContinuousEffect effect = new ElkinLairPlayExiledEffect(Duration.EndOfTurn); ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn);
effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game))); effect.setTargetPointer(new FixedTarget(card, game));
game.addEffect(effect, source); game.addEffect(effect, source);
DelayedTriggeredAbility delayed = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ElkinLairPutIntoGraveyardEffect()); DelayedTriggeredAbility delayed = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ElkinLairPutIntoGraveyardEffect());

View file

@ -2,14 +2,13 @@ package mage.cards.m;
import java.util.UUID; import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AsThoughEffectType;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
@ -81,8 +80,8 @@ class MissionBriefingEffect extends OneShotEffect {
} }
Card card = game.getCard(target.getFirstTarget()); Card card = game.getCard(target.getFirstTarget());
if (card != null) { if (card != null) {
ContinuousEffect effect = new MissionBriefingCastFromGraveyardEffect(); ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect();
effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game))); effect.setTargetPointer(new FixedTarget(card, game));
game.addEffect(effect, source); game.addEffect(effect, source);
effect = new MissionBriefingReplacementEffect(card.getId()); effect = new MissionBriefingReplacementEffect(card.getId());
game.addEffect(effect, source); game.addEffect(effect, source);
@ -92,33 +91,6 @@ class MissionBriefingEffect extends OneShotEffect {
} }
} }
class MissionBriefingCastFromGraveyardEffect extends AsThoughEffectImpl {
public MissionBriefingCastFromGraveyardEffect() {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
}
public MissionBriefingCastFromGraveyardEffect(final MissionBriefingCastFromGraveyardEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public MissionBriefingCastFromGraveyardEffect copy() {
return new MissionBriefingCastFromGraveyardEffect(this);
}
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
return objectId.equals(this.getTargetPointer().getFirst(game, source))
&& affectedControllerId.equals(source.getControllerId());
}
}
class MissionBriefingReplacementEffect extends ReplacementEffectImpl { class MissionBriefingReplacementEffect extends ReplacementEffectImpl {
private final UUID cardId; private final UUID cardId;

View file

@ -1,4 +1,3 @@
package mage.cards.n; package mage.cards.n;
import java.util.Set; import java.util.Set;
@ -77,7 +76,7 @@ class NarsetEnlightenedMasterExileEffect extends OneShotEffect {
&& !card.isCreature() && !card.isCreature()
&& !card.isLand()) { && !card.isLand()) {
ContinuousEffect effect = new NarsetEnlightenedMasterCastFromExileEffect(); ContinuousEffect effect = new NarsetEnlightenedMasterCastFromExileEffect();
effect.setTargetPointer(new FixedTarget(card.getId())); effect.setTargetPointer(new FixedTarget(card, game));
game.addEffect(effect, source); game.addEffect(effect, source);
} }
} }
@ -115,7 +114,8 @@ class NarsetEnlightenedMasterCastFromExileEffect extends AsThoughEffectImpl {
@Override @Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
if (objectId.equals(getTargetPointer().getFirst(game, source)) && affectedControllerId.equals(source.getControllerId())) { if (objectId.equals(getTargetPointer().getFirst(game, source))
&& affectedControllerId.equals(source.getControllerId())) {
Card card = game.getCard(objectId); Card card = game.getCard(objectId);
if (card != null) { if (card != null) {
Player player = game.getPlayer(affectedControllerId); Player player = game.getPlayer(affectedControllerId);

View file

@ -1,4 +1,3 @@
package org.mage.test.cards.asthough; package org.mage.test.cards.asthough;
import mage.constants.PhaseStep; import mage.constants.PhaseStep;
@ -99,8 +98,9 @@ public class PlayFromNonHandZoneTest extends CardTestPlayerBase {
assertExileCount("Silvercoat Lion", 1); assertExileCount("Silvercoat Lion", 1);
assertPermanentCount(playerB, "Abzan Banner", 1); assertPermanentCount(playerB, "Abzan Banner", 1);
assertPermanentCount(playerB, "Dragon Grip", 1);
assertGraveyardCount(playerB, "Peach Garden Oath", 1); assertGraveyardCount(playerB, "Peach Garden Oath", 1);
assertExileCount(playerB, "Dragon Grip", 0);
assertGraveyardCount(playerB, "Dragon Grip", 0);
assertPowerToughness(playerB, "Narset, Enlightened Master", 5, 2); assertPowerToughness(playerB, "Narset, Enlightened Master", 5, 2);
@ -108,6 +108,8 @@ public class PlayFromNonHandZoneTest extends CardTestPlayerBase {
assertLife(playerA, 17); assertLife(playerA, 17);
assertLife(playerB, 22); assertLife(playerB, 22);
assertPermanentCount(playerB, "Dragon Grip", 1);
} }
@Test @Test
@ -140,7 +142,6 @@ public class PlayFromNonHandZoneTest extends CardTestPlayerBase {
assertExileCount(playerB, "Plains", 3); assertExileCount(playerB, "Plains", 3);
assertExileCount(playerB, 3); assertExileCount(playerB, 3);
} }
} }

View file

@ -13,6 +13,7 @@ import mage.abilities.keyword.SpliceOntoArcaneAbility;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.Cards; import mage.cards.Cards;
import mage.cards.CardsImpl; import mage.cards.CardsImpl;
import mage.cards.SplitCardHalf;
import mage.constants.*; import mage.constants.*;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.filter.predicate.Predicate; import mage.filter.predicate.Predicate;
@ -488,18 +489,26 @@ public class ContinuousEffects implements Serializable {
*/ */
public MageObjectReference asThough(UUID objectId, AsThoughEffectType type, Ability affectedAbility, UUID controllerId, Game game) { public MageObjectReference asThough(UUID objectId, AsThoughEffectType type, Ability affectedAbility, UUID controllerId, Game game) {
List<AsThoughEffect> asThoughEffectsList = getApplicableAsThoughEffects(type, game); List<AsThoughEffect> asThoughEffectsList = getApplicableAsThoughEffects(type, 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) { for (AsThoughEffect effect : asThoughEffectsList) {
Set<Ability> abilities = asThoughEffectsMap.get(type).getAbility(effect.getId()); Set<Ability> abilities = asThoughEffectsMap.get(type).getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
if (affectedAbility == null) { if (affectedAbility == null) {
if (effect.applies(objectId, ability, controllerId, game)) { if (effect.applies(idToCheck, ability, controllerId, game)) {
return new MageObjectReference(ability.getSourceObject(game), game); return new MageObjectReference(ability.getSourceObject(game), game);
} }
} else if (effect.applies(objectId, affectedAbility, ability, game, controllerId)) { } else if (effect.applies(idToCheck, affectedAbility, ability, game, controllerId)) {
return new MageObjectReference(ability.getSourceObject(game), game); return new MageObjectReference(ability.getSourceObject(game), game);
} }
} }
} }
}
return null; return null;
} }

View file

@ -1,4 +1,3 @@
package mage.abilities.effects.common; package mage.abilities.effects.common;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -39,7 +38,9 @@ public class AttachEffect extends OneShotEffect {
Permanent sourcePermanent = game.getPermanent(source.getSourceId()); Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (sourcePermanent != null) { if (sourcePermanent != null) {
int zcc = game.getState().getZoneChangeCounter(sourcePermanent.getId()); 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)); Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent != null) { if (permanent != null) {
return permanent.addAttachment(source.getSourceId(), game); return permanent.addAttachment(source.getSourceId(), game);

View file

@ -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;
}
}

View file

@ -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<UUID> 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);
}
}

View file

@ -1,4 +1,3 @@
package mage.abilities.keyword; package mage.abilities.keyword;
import java.util.UUID; import java.util.UUID;
@ -68,16 +67,19 @@ class AftermathCastFromGraveyard extends AsThoughEffectImpl {
} }
@Override @Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { public boolean applies(UUID objectId, Ability affectedAbility, Ability source, Game game, UUID affectedControllerId) {
if (objectId.equals(source.getSourceId()) if (affectedAbility != null && affectedAbility.getSourceId().equals(source.getSourceId())
&& affectedControllerId.equals(source.getControllerId())) { && affectedControllerId.equals(source.getControllerId())) {
Card card = game.getCard(source.getSourceId()); return game.getState().getZone(objectId).equals(Zone.GRAVEYARD);
if (card != null && game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) {
return true;
}
} }
return false; return false;
} }
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
return false;
}
} }
class AftermathCantCastFromHand extends ContinuousRuleModifyingEffectImpl { class AftermathCantCastFromHand extends ContinuousRuleModifyingEffectImpl {
@ -168,17 +170,14 @@ class AftermathExileAsResolvesFromGraveyard extends ReplacementEffectImpl {
@Override @Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) { public boolean replaceEvent(GameEvent event, Ability source, Game game) {
UUID sourceId = source.getSourceId();
Card sourceCard = game.getCard(source.getSourceId()); Card sourceCard = game.getCard(source.getSourceId());
if (sourceCard instanceof SplitCardHalf) { if (sourceCard instanceof SplitCardHalf) {
sourceCard = ((SplitCardHalf) sourceCard).getParentCard(); sourceCard = ((SplitCardHalf) sourceCard).getParentCard();
sourceId = sourceCard.getId();
} }
if (sourceCard != null) { if (sourceCard != null) {
Player player = game.getPlayer(sourceCard.getOwnerId()); Player player = game.getPlayer(sourceCard.getOwnerId());
if (player != null) { if (player != null) {
return player.moveCardToExileWithInfo(sourceCard, null, "", sourceId, game, ((ZoneChangeEvent) event).getFromZone(), true); return player.moveCards(sourceCard, Zone.EXILED, source, game);
} }
} }
return false; return false;

View file

@ -1,5 +1,9 @@
package mage.players; package mage.players;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;
import mage.ConditionalMana; import mage.ConditionalMana;
import mage.MageObject; import mage.MageObject;
import mage.MageObjectReference; import mage.MageObjectReference;
@ -68,11 +72,6 @@ import mage.util.GameLog;
import mage.util.RandomUtil; import mage.util.RandomUtil;
import org.apache.log4j.Logger; 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 { public abstract class PlayerImpl implements Player, Serializable {
private static final Logger logger = Logger.getLogger(PlayerImpl.class); private static final Logger logger = Logger.getLogger(PlayerImpl.class);
@ -2927,7 +2926,7 @@ public abstract class PlayerImpl implements Player, Serializable {
} }
private void getPlayableFromGraveyardCard(Game game, Card card, Abilities<Ability> candidateAbilities, ManaOptions availableMana, List<Ability> output) { private void getPlayableFromGraveyardCard(Game game, Card card, Abilities<Ability> candidateAbilities, ManaOptions availableMana, List<Ability> 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)) { for (ActivatedAbility ability : candidateAbilities.getActivatedAbilities(Zone.ALL)) {
boolean possible = false; boolean possible = false;
if (ability.getZone().match(Zone.GRAVEYARD)) { if (ability.getZone().match(Zone.GRAVEYARD)) {
@ -3033,7 +3032,7 @@ public abstract class PlayerImpl implements Player, Serializable {
if (player != null) { if (player != null) {
if (/*player.isTopCardRevealed() &&*/player.getLibrary().hasCards()) { if (/*player.isTopCardRevealed() &&*/player.getLibrary().hasCards()) {
Card card = player.getLibrary().getFromTop(game); 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)) { for (ActivatedAbility ability : card.getAbilities().getActivatedAbilities(Zone.HAND)) {
if (ability instanceof SpellAbility || ability instanceof PlayLandAbility) { if (ability instanceof SpellAbility || ability instanceof PlayLandAbility) {
playable.add(ability); playable.add(ability);

View file

@ -21,6 +21,12 @@ public class FixedTarget implements TargetPointer {
this.initialized = false; 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) { public FixedTarget(Permanent permanent, Game game) {
this.targetId = permanent.getId(); this.targetId = permanent.getId();
this.zoneChangeCounter = permanent.getZoneChangeCounter(game); this.zoneChangeCounter = permanent.getZoneChangeCounter(game);