Implemented Mnemonic Betrayal

This commit is contained in:
Evan Kranzler 2018-09-22 10:06:40 -04:00
parent cb138473e5
commit 24536032cd
3 changed files with 221 additions and 1 deletions

View file

@ -0,0 +1,219 @@
package mage.cards.m;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileSpellEffect;
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.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
/**
*
* @author TheElk801
*/
public final class MnemonicBetrayal extends CardImpl {
public MnemonicBetrayal(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}{B}");
// Exile all cards from all opponents' graveyards. You may cast those cards this turn, and you may spend mana as though it were mana of any type to cast those spells. At the beginning of the next end step, if any of those cards remain exiled, return them to their owner's graveyards.
this.getSpellAbility().addEffect(new MnemonicBetrayalExileEffect());
// Exile Mnemonic Betrayal.
this.getSpellAbility().addEffect(ExileSpellEffect.getInstance());
}
public MnemonicBetrayal(final MnemonicBetrayal card) {
super(card);
}
@Override
public MnemonicBetrayal copy() {
return new MnemonicBetrayal(this);
}
}
class MnemonicBetrayalExileEffect extends OneShotEffect {
public MnemonicBetrayalExileEffect() {
super(Outcome.Benefit);
this.staticText = "Exile all cards from all opponents' graveyards. "
+ "You may cast those cards this turn, "
+ "and you may spend mana as though it were mana of any type "
+ "to cast those spells. At the beginning of the next end step, "
+ "if any of those cards remain exiled, "
+ "return them to their owner's graveyards.";
}
public MnemonicBetrayalExileEffect(final MnemonicBetrayalExileEffect effect) {
super(effect);
}
@Override
public MnemonicBetrayalExileEffect copy() {
return new MnemonicBetrayalExileEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
Cards cards = new CardsImpl();
Map<UUID, Integer> cardMap = new HashMap();
for (UUID playerId : game.getOpponents(source.getControllerId())) {
Player player = game.getPlayer(playerId);
if (player != null) {
cards.addAll(player.getGraveyard());
}
}
for (Card card : cards.getCards(game)) {
cardMap.put(card.getId(), card.getZoneChangeCounter(game));
game.addEffect(new MnemonicBetrayalCastFromExileEffect(card, game), source);
}
controller.moveCardsToExile(cards.getCards(game), source, game, true, source.getSourceId(), source.getSourceObjectIfItStillExists(game).getName());
game.addDelayedTriggeredAbility(new MnemonicBetrayalDelayedTriggeredAbility(cards, cardMap));
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
&& affectedControllerId.equals(source.getControllerId());
}
}
class MnemonicBetrayalDelayedTriggeredAbility extends DelayedTriggeredAbility {
private final Cards cards;
private final Map<UUID, Integer> cardMap = new HashMap();
public MnemonicBetrayalDelayedTriggeredAbility(Cards cards, Map<UUID, Integer> cardMap) {
super(new MnemonicBetrayalReturnEffect(cards, cardMap));
this.triggerOnlyOnce = true;
this.cards = cards;
this.cardMap.putAll(cardMap);
}
public MnemonicBetrayalDelayedTriggeredAbility(final MnemonicBetrayalDelayedTriggeredAbility ability) {
super(ability);
this.cards = ability.cards.copy();
this.cardMap.putAll(ability.cardMap);
}
@Override
public MnemonicBetrayalDelayedTriggeredAbility copy() {
return new MnemonicBetrayalDelayedTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.END_TURN_STEP_PRE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return true;
}
@Override
public boolean checkInterveningIfClause(Game game) {
return cards.stream().anyMatch((cardId) -> (game.getState().getZone(cardId) == Zone.EXILED
&& game.getState().getZoneChangeCounter(cardId) == cardMap.getOrDefault(cardId, -5) + 1));
}
@Override
public String getRule() {
return "At the beginning of the next end step, "
+ "if any of those cards remain exiled, "
+ "return them to their owner's graveyards.";
}
}
class MnemonicBetrayalReturnEffect extends OneShotEffect {
private final Cards cards;
private final Map<UUID, Integer> cardMap = new HashMap();
public MnemonicBetrayalReturnEffect(Cards cards, Map<UUID, Integer> cardMap) {
super(Outcome.Benefit);
this.cards = cards;
this.cardMap.putAll(cardMap);
}
public MnemonicBetrayalReturnEffect(final MnemonicBetrayalReturnEffect effect) {
super(effect);
this.cards = effect.cards.copy();
this.cardMap.putAll(effect.cardMap);
}
@Override
public MnemonicBetrayalReturnEffect copy() {
return new MnemonicBetrayalReturnEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
Cards cardsToReturn = new CardsImpl();
for (Card card : cards.getCards(game)) {
if (game.getState().getZone(card.getId()) == Zone.EXILED
&& card.getZoneChangeCounter(game) == cardMap.getOrDefault(card.getId(), -5) + 1) {
cardsToReturn.add(card);
}
}
return player.moveCards(cardsToReturn, Zone.GRAVEYARD, source, game);
}
}

View file

@ -180,6 +180,7 @@ public final class GuildsOfRavnica extends ExpansionSet {
cards.add(new SetCardInfo("Midnight Reaper", 77, Rarity.RARE, mage.cards.m.MidnightReaper.class));
cards.add(new SetCardInfo("Might of the Masses", 137, Rarity.UNCOMMON, mage.cards.m.MightOfTheMasses.class));
cards.add(new SetCardInfo("Mission Briefing", 44, Rarity.RARE, mage.cards.m.MissionBriefing.class));
cards.add(new SetCardInfo("Mnemonic Betrayal", 189, Rarity.MYTHIC, mage.cards.m.MnemonicBetrayal.class));
cards.add(new SetCardInfo("Molderhulk", 190, Rarity.UNCOMMON, mage.cards.m.Molderhulk.class));
cards.add(new SetCardInfo("Moodmark Painter", 78, Rarity.COMMON, mage.cards.m.MoodmarkPainter.class));
cards.add(new SetCardInfo("Mountain", 263, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS));

View file

@ -13,7 +13,7 @@ import mage.game.Game;
public abstract class DelayedTriggeredAbility extends TriggeredAbilityImpl {
private Duration duration;
private boolean triggerOnlyOnce;
protected boolean triggerOnlyOnce;
public DelayedTriggeredAbility(Effect effect) {
this(effect, Duration.EndOfGame);