mirror of
https://github.com/correl/mage.git
synced 2024-12-26 19:16:54 +00:00
[GRN] fixed Mnemonic Betrayal not allowing exiled cards to be cast correctly
This commit is contained in:
parent
28dfaaffa1
commit
373a7f689e
1 changed files with 54 additions and 140 deletions
|
@ -1,21 +1,25 @@
|
||||||
package mage.cards.m;
|
package mage.cards.m;
|
||||||
|
|
||||||
|
import mage.MageObjectReference;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.DelayedTriggeredAbility;
|
import mage.abilities.DelayedTriggeredAbility;
|
||||||
import mage.abilities.effects.AsThoughEffectImpl;
|
|
||||||
import mage.abilities.effects.AsThoughManaEffect;
|
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.abilities.effects.common.ExileSpellEffect;
|
import mage.abilities.effects.common.ExileSpellEffect;
|
||||||
import mage.cards.*;
|
import mage.cards.*;
|
||||||
import mage.constants.*;
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.players.ManaPoolItem;
|
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.util.CardUtil;
|
import mage.util.CardUtil;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
import java.util.HashSet;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author TheElk801
|
* @author TheElk801
|
||||||
|
@ -32,7 +36,7 @@ public final class MnemonicBetrayal extends CardImpl {
|
||||||
this.getSpellAbility().addEffect(new MnemonicBetrayalExileEffect());
|
this.getSpellAbility().addEffect(new MnemonicBetrayalExileEffect());
|
||||||
|
|
||||||
// Exile Mnemonic Betrayal.
|
// Exile Mnemonic Betrayal.
|
||||||
this.getSpellAbility().addEffect(new ExileSpellEffect());
|
this.getSpellAbility().addEffect(new ExileSpellEffect().concatBy("<br>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private MnemonicBetrayal(final MnemonicBetrayal card) {
|
private MnemonicBetrayal(final MnemonicBetrayal card) {
|
||||||
|
@ -49,12 +53,11 @@ class MnemonicBetrayalExileEffect extends OneShotEffect {
|
||||||
|
|
||||||
public MnemonicBetrayalExileEffect() {
|
public MnemonicBetrayalExileEffect() {
|
||||||
super(Outcome.Benefit);
|
super(Outcome.Benefit);
|
||||||
this.staticText = "Exile all cards from all opponents' graveyards. "
|
this.staticText = "exile all cards from all opponents’ graveyards. " +
|
||||||
+ "You may cast those cards this turn, "
|
"You may cast spells from among those cards this turn, " +
|
||||||
+ "and you may spend mana as though it were mana of any type "
|
"and you may spend mana as though it were mana of any type to cast those spells. " +
|
||||||
+ "to cast those spells. At the beginning of the next end step, "
|
"At the beginning of the next end step, if any of those cards remain exiled, " +
|
||||||
+ "if any of those cards remain exiled, "
|
"return them to their owners’ graveyards";
|
||||||
+ "return them to their owner's graveyards";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MnemonicBetrayalExileEffect(final MnemonicBetrayalExileEffect effect) {
|
public MnemonicBetrayalExileEffect(final MnemonicBetrayalExileEffect effect) {
|
||||||
|
@ -73,131 +76,46 @@ class MnemonicBetrayalExileEffect extends OneShotEffect {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Cards cards = new CardsImpl();
|
Cards cards = new CardsImpl();
|
||||||
Map<UUID, Integer> cardMap = new HashMap<>();
|
game.getOpponents(source.getControllerId())
|
||||||
game.getOpponents(source.getControllerId()).stream().map((playerId)
|
.stream()
|
||||||
-> game.getPlayer(playerId)).filter((player) -> (player != null)).forEachOrdered((player) -> {
|
.map(game::getPlayer)
|
||||||
cards.addAll(player.getGraveyard());
|
.filter(Objects::nonNull)
|
||||||
});
|
.map(Player::getGraveyard)
|
||||||
cards.getCards(game).stream().map((card) -> {
|
.map(g -> g.getCards(game))
|
||||||
cardMap.put(card.getId(), card.getZoneChangeCounter(game));
|
.forEach(cards::addAll);
|
||||||
return card;
|
controller.moveCardsToExile(
|
||||||
}).map((card) -> {
|
cards.getCards(game), source, game, true,
|
||||||
game.addEffect(new MnemonicBetrayalCastFromExileEffect(card, game), source);
|
source.getSourceId(), CardUtil.getSourceLogName(game, source)
|
||||||
return card;
|
);
|
||||||
}).forEachOrdered((card) -> {
|
for (Card card : cards.getCards(game)) {
|
||||||
game.addEffect(new MnemonicBetrayalAnyColorEffect(card, game), source);
|
if (card.isLand()) {
|
||||||
});
|
continue;
|
||||||
controller.moveCardsToExile(cards.getCards(game), source, game, true,
|
|
||||||
source.getSourceId(), source.getSourceObjectIfItStillExists(game).getName());
|
|
||||||
game.addDelayedTriggeredAbility(new MnemonicBetrayalDelayedTriggeredAbility(cards, cardMap), source);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MnemonicBetrayalCastFromExileEffect extends AsThoughEffectImpl {
|
|
||||||
|
|
||||||
private final Card card;
|
|
||||||
private final int zoneCounter;
|
|
||||||
|
|
||||||
public MnemonicBetrayalCastFromExileEffect(Card card, Game game) {
|
|
||||||
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit);
|
|
||||||
this.card = card;
|
|
||||||
this.zoneCounter = card.getZoneChangeCounter(game) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MnemonicBetrayalCastFromExileEffect(final MnemonicBetrayalCastFromExileEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
this.card = effect.card;
|
|
||||||
this.zoneCounter = effect.zoneCounter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MnemonicBetrayalCastFromExileEffect copy() {
|
|
||||||
return new MnemonicBetrayalCastFromExileEffect(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
|
||||||
if (card.getZoneChangeCounter(game) != zoneCounter) {
|
|
||||||
this.discard();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return objectId.equals(card.getId())
|
|
||||||
&& card.getZoneChangeCounter(game) == zoneCounter
|
|
||||||
&& source.isControlledBy(affectedControllerId)
|
|
||||||
&& !card.isLand(); // cast only not play
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MnemonicBetrayalAnyColorEffect extends AsThoughEffectImpl implements AsThoughManaEffect {
|
|
||||||
|
|
||||||
private final Card card;
|
|
||||||
private final int zoneCounter;
|
|
||||||
|
|
||||||
public MnemonicBetrayalAnyColorEffect(Card card, Game game) {
|
|
||||||
super(AsThoughEffectType.SPEND_OTHER_MANA, Duration.Custom, Outcome.Benefit);
|
|
||||||
this.card = card;
|
|
||||||
this.zoneCounter = card.getZoneChangeCounter(game) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MnemonicBetrayalAnyColorEffect(final MnemonicBetrayalAnyColorEffect effect) {
|
|
||||||
super(effect);
|
|
||||||
this.card = effect.card;
|
|
||||||
this.zoneCounter = effect.zoneCounter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Game game, Ability source) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MnemonicBetrayalAnyColorEffect copy() {
|
|
||||||
return new MnemonicBetrayalAnyColorEffect(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
|
||||||
objectId = CardUtil.getMainCardId(game, objectId); // for split cards
|
|
||||||
if (objectId.equals(card.getId())
|
|
||||||
&& card.getZoneChangeCounter(game) <= zoneCounter + 1
|
|
||||||
&& source.isControlledBy(affectedControllerId)) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
if (objectId.equals(card.getId())) {
|
|
||||||
this.discard();
|
|
||||||
}
|
}
|
||||||
|
CardUtil.makeCardPlayable(game, source, card, Duration.EndOfTurn, true);
|
||||||
}
|
}
|
||||||
return false;
|
cards.retainZone(Zone.EXILED, game);
|
||||||
}
|
game.addDelayedTriggeredAbility(new MnemonicBetrayalDelayedTriggeredAbility(
|
||||||
|
cards.stream()
|
||||||
@Override
|
.map(uuid -> new MageObjectReference(uuid, game))
|
||||||
public ManaType getAsThoughManaType(ManaType manaType, ManaPoolItem mana, UUID affectedControllerId, Ability source, Game game) {
|
.collect(Collectors.toSet())
|
||||||
return mana.getFirstAvailable();
|
), source);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MnemonicBetrayalDelayedTriggeredAbility extends DelayedTriggeredAbility {
|
class MnemonicBetrayalDelayedTriggeredAbility extends DelayedTriggeredAbility {
|
||||||
|
|
||||||
private final Cards cards;
|
private final Set<MageObjectReference> morSet = new HashSet<>();
|
||||||
private final Map<UUID, Integer> cardMap = new HashMap<>();
|
|
||||||
|
|
||||||
public MnemonicBetrayalDelayedTriggeredAbility(Cards cards, Map<UUID, Integer> cardMap) {
|
public MnemonicBetrayalDelayedTriggeredAbility(Set<MageObjectReference> morSet) {
|
||||||
super(new MnemonicBetrayalReturnEffect(cards, cardMap));
|
super(new MnemonicBetrayalReturnEffect(morSet));
|
||||||
this.triggerOnlyOnce = true;
|
this.triggerOnlyOnce = true;
|
||||||
this.cards = cards;
|
this.morSet.addAll(morSet);
|
||||||
this.cardMap.putAll(cardMap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MnemonicBetrayalDelayedTriggeredAbility(final MnemonicBetrayalDelayedTriggeredAbility ability) {
|
public MnemonicBetrayalDelayedTriggeredAbility(final MnemonicBetrayalDelayedTriggeredAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
this.cards = ability.cards.copy();
|
this.morSet.addAll(ability.morSet);
|
||||||
this.cardMap.putAll(ability.cardMap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -217,8 +135,7 @@ class MnemonicBetrayalDelayedTriggeredAbility extends DelayedTriggeredAbility {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkInterveningIfClause(Game game) {
|
public boolean checkInterveningIfClause(Game game) {
|
||||||
return cards.stream().anyMatch((cardId) -> (game.getState().getZone(cardId) == Zone.EXILED
|
return morSet.stream().map(mor -> mor.getCard(game)).anyMatch(Objects::nonNull);
|
||||||
&& game.getState().getZoneChangeCounter(cardId) == cardMap.getOrDefault(cardId, -5) + 1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -231,19 +148,16 @@ class MnemonicBetrayalDelayedTriggeredAbility extends DelayedTriggeredAbility {
|
||||||
|
|
||||||
class MnemonicBetrayalReturnEffect extends OneShotEffect {
|
class MnemonicBetrayalReturnEffect extends OneShotEffect {
|
||||||
|
|
||||||
private final Cards cards;
|
private final Set<MageObjectReference> morSet = new HashSet<>();
|
||||||
private final Map<UUID, Integer> cardMap = new HashMap<>();
|
|
||||||
|
|
||||||
public MnemonicBetrayalReturnEffect(Cards cards, Map<UUID, Integer> cardMap) {
|
public MnemonicBetrayalReturnEffect(Set<MageObjectReference> morSet) {
|
||||||
super(Outcome.Benefit);
|
super(Outcome.Benefit);
|
||||||
this.cards = cards;
|
this.morSet.addAll(morSet);
|
||||||
this.cardMap.putAll(cardMap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MnemonicBetrayalReturnEffect(final MnemonicBetrayalReturnEffect effect) {
|
public MnemonicBetrayalReturnEffect(final MnemonicBetrayalReturnEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
this.cards = effect.cards.copy();
|
this.morSet.addAll(effect.morSet);
|
||||||
this.cardMap.putAll(effect.cardMap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -257,11 +171,11 @@ class MnemonicBetrayalReturnEffect extends OneShotEffect {
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Cards cardsToReturn = new CardsImpl();
|
return player != null && player.moveCards(new CardsImpl(
|
||||||
cards.getCards(game).stream().filter((card) -> (game.getState().getZone(card.getId()) == Zone.EXILED
|
morSet.stream()
|
||||||
&& card.getZoneChangeCounter(game) == cardMap.getOrDefault(card.getId(), -5) + 1)).forEachOrdered((card) -> {
|
.map(mor -> mor.getCard(game))
|
||||||
cardsToReturn.add(card);
|
.filter(Objects::nonNull)
|
||||||
});
|
.collect(Collectors.toList())
|
||||||
return player.moveCards(cardsToReturn, Zone.GRAVEYARD, source, game);
|
), Zone.GRAVEYARD, source, game);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue