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

View file

@ -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() + " <this card may be played the turn it was exiled>";
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);
}

View file

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

View file

@ -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() + " <this card may be played the turn it was exiled>";
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));
}
}

View file

@ -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() {

View file

@ -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() + " <this card may be played the turn it was exiled>", 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() {

View file

@ -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());

View file

@ -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() {

View file

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

View file

@ -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() + " <this card may be played the turn it was exiled>";
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));
}
}

View file

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

View file

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

View file

@ -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() {

View file

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

View file

@ -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() + " <this card may be played the turn it was exiled";
player.moveCardsToExile(card, source, game, true, source.getSourceId(), exileName);
if (game.getState().getZone(card.getId()) == Zone.EXILED) {
ContinuousEffect effect = new ElkinLairPlayExiledEffect(Duration.EndOfTurn);
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);
DelayedTriggeredAbility delayed = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new ElkinLairPutIntoGraveyardEffect());

View file

@ -2,14 +2,13 @@ package mage.cards.m;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl;
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;
@ -81,8 +80,8 @@ class MissionBriefingEffect extends OneShotEffect {
}
Card card = game.getCard(target.getFirstTarget());
if (card != null) {
ContinuousEffect effect = new MissionBriefingCastFromGraveyardEffect();
effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game)));
ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect();
effect.setTargetPointer(new FixedTarget(card, game));
game.addEffect(effect, source);
effect = new MissionBriefingReplacementEffect(card.getId());
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 {
private final UUID cardId;

View file

@ -1,4 +1,3 @@
package mage.cards.n;
import java.util.Set;
@ -77,7 +76,7 @@ class NarsetEnlightenedMasterExileEffect extends OneShotEffect {
&& !card.isCreature()
&& !card.isLand()) {
ContinuousEffect effect = new NarsetEnlightenedMasterCastFromExileEffect();
effect.setTargetPointer(new FixedTarget(card.getId()));
effect.setTargetPointer(new FixedTarget(card, game));
game.addEffect(effect, source);
}
}
@ -115,7 +114,8 @@ class NarsetEnlightenedMasterCastFromExileEffect extends AsThoughEffectImpl {
@Override
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);
if (card != null) {
Player player = game.getPlayer(affectedControllerId);

View file

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

View file

@ -13,6 +13,7 @@ import mage.abilities.keyword.SpliceOntoArcaneAbility;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.cards.SplitCardHalf;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicate;
@ -488,15 +489,23 @@ public class ContinuousEffects implements Serializable {
*/
public MageObjectReference asThough(UUID objectId, AsThoughEffectType type, Ability affectedAbility, UUID controllerId, Game game) {
List<AsThoughEffect> asThoughEffectsList = getApplicableAsThoughEffects(type, game);
for (AsThoughEffect effect : asThoughEffectsList) {
Set<Ability> 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<Ability> 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);
}
}
}

View file

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

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

View file

@ -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<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)) {
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<UUID> appliedEffects
Ability source, Game game,
boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects
) {
Set<Card> 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<Card> 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<Card> cards, Zone toZone,
Ability source, Game game,
boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects
Ability source, Game game,
boolean tapped, boolean faceDown, boolean byOwner, List<UUID> 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<Card> cards = new HashSet<>();
cards.add(card);
@ -3580,8 +3579,8 @@ public abstract class PlayerImpl implements Player, Serializable {
@Override
public boolean moveCardsToExile(Set<Card> 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<Card> moveCardsToGraveyardWithInfo(Set<Card> allCards, Ability source,
Game game, Zone fromZone
Game game, Zone fromZone
) {
UUID sourceId = source == null ? null : source.getSourceId();
Set<Card> 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<Card> it = allCards.iterator(); it.hasNext(); ) {
for (Iterator<Card> 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;
}

View file

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