From 50cd0af6018637c7907c26a58a7f2d71604d2f06 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 4 Jan 2019 17:21:07 +0100 Subject: [PATCH] * Kess, Dissident Mage - Fixed that it did not allow split cards from graveyard. Fixed some other problems with the card. --- .../src/mage/cards/d/DaruSpiritualist.java | 11 +- .../src/mage/cards/k/KessDissidentMage.java | 130 ++++++------------ .../abilities/effects/ContinuousEffects.java | 6 +- 3 files changed, 51 insertions(+), 96 deletions(-) diff --git a/Mage.Sets/src/mage/cards/d/DaruSpiritualist.java b/Mage.Sets/src/mage/cards/d/DaruSpiritualist.java index 1e684d94f6..dbf5f6a79d 100644 --- a/Mage.Sets/src/mage/cards/d/DaruSpiritualist.java +++ b/Mage.Sets/src/mage/cards/d/DaruSpiritualist.java @@ -1,4 +1,3 @@ - package mage.cards.d; import java.util.UUID; @@ -12,8 +11,6 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.mageobject.SubtypePredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; @@ -50,12 +47,6 @@ public final class DaruSpiritualist extends CardImpl { class DaruSpiritualistTriggeredAbility extends TriggeredAbilityImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Cleric creature you control"); - - static { - filter.add(new SubtypePredicate(SubType.CLERIC)); - } - public DaruSpiritualistTriggeredAbility(Effect effect) { super(Zone.BATTLEFIELD, effect); } @@ -77,7 +68,7 @@ class DaruSpiritualistTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { Permanent creature = game.getPermanent(event.getTargetId()); - if (creature != null && filter.match(creature, getSourceId(), getControllerId(), game)) { + if (creature != null && creature.hasSubtype(SubType.CLERIC, game) && creature.getControllerId().equals(getControllerId()) && creature.isCreature()) { this.getEffects().setTargetPointer(new FixedTarget(creature, game)); return true; } diff --git a/Mage.Sets/src/mage/cards/k/KessDissidentMage.java b/Mage.Sets/src/mage/cards/k/KessDissidentMage.java index bc3cc94473..ecc3620585 100644 --- a/Mage.Sets/src/mage/cards/k/KessDissidentMage.java +++ b/Mage.Sets/src/mage/cards/k/KessDissidentMage.java @@ -1,14 +1,15 @@ - package mage.cards.k; -import java.util.Optional; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; import java.util.UUID; import mage.MageInt; +import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.AsThoughEffectImpl; -import mage.abilities.effects.ContinuousEffect; -import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.keyword.FlashbackAbility; import mage.abilities.keyword.FlyingAbility; @@ -18,22 +19,16 @@ import mage.cards.CardSetInfo; import mage.constants.AsThoughEffectType; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Layer; import mage.constants.Outcome; -import mage.constants.SubLayer; import mage.constants.SubType; import mage.constants.SuperType; import mage.constants.WatcherScope; import mage.constants.Zone; -import mage.filter.FilterCard; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.CardTypePredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.game.stack.Spell; import mage.players.Player; -import mage.target.targetpointer.FixedTarget; import mage.watchers.Watcher; /** @@ -55,7 +50,9 @@ public final class KessDissidentMage extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // During each of your turns, you may cast an instant or sorcery card from your graveyard. If a card cast this way would be put into your graveyard this turn, exile it instead. - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new KessDissidentMageContinuousEffect()), new KessDissidentMageWatcher()); + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new KessDissidentMageCastFromGraveyardEffect()); + ability.addEffect(new KessDissidentMageReplacementEffect()); + this.addAbility(ability, new KessDissidentMageWatcher()); } public KessDissidentMage(final KessDissidentMage card) { @@ -68,56 +65,11 @@ public final class KessDissidentMage extends CardImpl { } } -class KessDissidentMageContinuousEffect extends ContinuousEffectImpl { - - private static final FilterCard filter = new FilterCard("Instant or sorcery spell"); - - static { - filter.add(Predicates.or( - new CardTypePredicate(CardType.INSTANT), - new CardTypePredicate(CardType.SORCERY) - )); - } - - KessDissidentMageContinuousEffect() { - super(Duration.WhileOnBattlefield, Layer.PlayerEffects, SubLayer.NA, Outcome.Benefit); - staticText = "During each of your turns, you may cast an instant or sorcery card from your graveyard. If a card cast this way would be put into your graveyard, exile it instead"; - } - - KessDissidentMageContinuousEffect(final KessDissidentMageContinuousEffect effect) { - super(effect); - } - - @Override - public KessDissidentMageContinuousEffect copy() { - return new KessDissidentMageContinuousEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - if (!game.isActivePlayer(player.getId())) { - return false; - } - for (Card card : player.getGraveyard().getCards(filter, game)) { - ContinuousEffect effect = new KessDissidentMageCastFromGraveyardEffect(); - effect.setTargetPointer(new FixedTarget(card.getId())); - game.addEffect(effect, source); - effect = new KessDissidentMageReplacementEffect(card.getId()); - game.addEffect(effect, source); - } - return true; - } - return false; - } -} - class KessDissidentMageCastFromGraveyardEffect extends AsThoughEffectImpl { KessDissidentMageCastFromGraveyardEffect() { - super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit); - staticText = "You may cast an instant or sorcery card from your graveyard"; + super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "During each of your turns, you may cast an instant or sorcery card from your graveyard"; } KessDissidentMageCastFromGraveyardEffect(final KessDissidentMageCastFromGraveyardEffect effect) { @@ -136,14 +88,13 @@ class KessDissidentMageCastFromGraveyardEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - if (objectId.equals(getTargetPointer().getFirst(game, source))) { - if (affectedControllerId.equals(source.getControllerId())) { - if (game.isActivePlayer(source.getControllerId())) { - KessDissidentMageWatcher watcher = (KessDissidentMageWatcher) game.getState().getWatchers().get(KessDissidentMageWatcher.class.getSimpleName(), source.getSourceId()); - if (!(source instanceof FlashbackAbility)) { - return !watcher.isAbilityUsed(); - } - } + if (!(source instanceof FlashbackAbility) && affectedControllerId.equals(source.getControllerId()) && game.isActivePlayer(source.getControllerId())) { + Card card = game.getCard(objectId); + if (card != null && (card.isInstant() || card.isSorcery()) + && game.getState().getZone(objectId).equals(Zone.GRAVEYARD)) { + // check if not already a card was cast this turn with this ability + KessDissidentMageWatcher watcher = (KessDissidentMageWatcher) game.getState().getWatchers().get(KessDissidentMageWatcher.class.getSimpleName()); + return !watcher.isAbilityUsed(new MageObjectReference(source.getSourceId(), game)); } } return false; @@ -152,17 +103,13 @@ class KessDissidentMageCastFromGraveyardEffect extends AsThoughEffectImpl { class KessDissidentMageReplacementEffect extends ReplacementEffectImpl { - private final UUID cardId; - - KessDissidentMageReplacementEffect(UUID cardId) { - super(Duration.EndOfTurn, Outcome.Exile); - this.cardId = cardId; + KessDissidentMageReplacementEffect() { + super(Duration.EndOfGame, Outcome.Exile); staticText = "If a card cast this way would be put into your graveyard, exile it instead"; } KessDissidentMageReplacementEffect(final KessDissidentMageReplacementEffect effect) { super(effect); - this.cardId = effect.cardId; } @Override @@ -173,9 +120,9 @@ class KessDissidentMageReplacementEffect extends ReplacementEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { Player controller = game.getPlayer(source.getControllerId()); - Card card = game.getCard(this.cardId); + Card card = game.getCard(event.getTargetId()); if (controller != null && card != null) { - controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.STACK, true); + controller.moveCards(card, Zone.EXILED, source, game); return true; } return false; @@ -189,31 +136,39 @@ class KessDissidentMageReplacementEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - return zEvent.getToZone() == Zone.GRAVEYARD - && zEvent.getTargetId().equals(this.cardId); + if (zEvent.getToZone() == Zone.GRAVEYARD) { + KessDissidentMageWatcher watcher = (KessDissidentMageWatcher) game.getState().getWatchers().get(KessDissidentMageWatcher.class.getSimpleName()); + if (source.getSourceId().equals(watcher.spellCastWasAllowedBy(new MageObjectReference(event.getTargetId(), game)))) { + return true; + } + } + return false; } } class KessDissidentMageWatcher extends Watcher { - boolean abilityUsed = false; + // Which kess object did cast which spell from graveyard + private final Set allowingObjects = new HashSet<>(); + private final Map castSpells = new HashMap<>(); KessDissidentMageWatcher() { - super(KessDissidentMageWatcher.class.getSimpleName(), WatcherScope.CARD); + super(KessDissidentMageWatcher.class.getSimpleName(), WatcherScope.GAME); } KessDissidentMageWatcher(final KessDissidentMageWatcher watcher) { super(watcher); - this.abilityUsed = watcher.abilityUsed; + this.allowingObjects.addAll(watcher.allowingObjects); + this.castSpells.putAll(watcher.castSpells); } @Override public void watch(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.SPELL_CAST && event.getZone() == Zone.GRAVEYARD) { Spell spell = (Spell) game.getObject(event.getTargetId()); - if (spell.isInstant() || spell.isSorcery()) { - Optional source = game.getAbility(event.getSourceId(), event.getSourceId()); - abilityUsed = true; + if (null != event.getAdditionalReference() && spell.isInstant() || spell.isSorcery()) { + allowingObjects.add(event.getAdditionalReference()); + castSpells.put(new MageObjectReference(spell.getSourceId(), game), event.getAdditionalReference().getSourceId()); } } } @@ -226,10 +181,15 @@ class KessDissidentMageWatcher extends Watcher { @Override public void reset() { super.reset(); - abilityUsed = false; + allowingObjects.clear(); } - public boolean isAbilityUsed() { - return abilityUsed; + public boolean isAbilityUsed(MageObjectReference mor) { + return allowingObjects.contains(mor); } + + public UUID spellCastWasAllowedBy(MageObjectReference mor) { + return castSpells.getOrDefault(mor, null); + } + } diff --git a/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java b/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java index ce14ca33b4..5f1bad6e5b 100644 --- a/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java +++ b/Mage/src/main/java/mage/abilities/effects/ContinuousEffects.java @@ -494,7 +494,11 @@ public class ContinuousEffects implements Serializable { if (affectedAbility != null && affectedAbility.getSourceObject(game) instanceof SplitCardHalf) { idToCheck = ((SplitCardHalf) affectedAbility.getSourceObject(game)).getParentCard().getId(); } else { - idToCheck = objectId; + if (game.getObject(objectId) instanceof SplitCardHalf) { + idToCheck = ((SplitCardHalf) game.getObject(objectId)).getParentCard().getId(); + } else { + idToCheck = objectId; + } } for (AsThoughEffect effect : asThoughEffectsList) { Set abilities = asThoughEffectsMap.get(type).getAbility(effect.getId());