[SNC] Implemented Riveteers Charm

This commit is contained in:
Evan Kranzler 2022-04-04 19:27:14 -04:00
parent 28e62abcce
commit be6dd5263d
6 changed files with 174 additions and 33 deletions

View file

@ -16,7 +16,7 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.target.common.TargetCreaturePermanent;
import mage.target.common.TargetAttackingCreature;
import java.util.UUID;
@ -45,7 +45,7 @@ public final class RaffineSchemingSeer extends CardImpl {
// Whenever you attack, target creature connives X, where X is the number of attacking creatures.
Ability ability = new AttacksWithCreaturesTriggeredAbility(new ConniveTargetEffect(xValue), 1);
ability.addTarget(new TargetCreaturePermanent());
ability.addTarget(new TargetAttackingCreature());
this.addAbility(ability);
}

View file

@ -0,0 +1,130 @@
package mage.cards.r;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.condition.Condition;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileGraveyardAllTargetPlayerEffect;
import mage.abilities.effects.common.SacrificeEffect;
import mage.cards.*;
import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent;
import mage.filter.predicate.permanent.MaxManaValueControlledPermanentPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
import mage.target.TargetPlayer;
import mage.target.common.TargetOpponent;
import mage.util.CardUtil;
import mage.watchers.Watcher;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class RiveteersCharm extends CardImpl {
private static final FilterPermanent filter = new FilterCreatureOrPlaneswalkerPermanent(
"creature or planeswalker they control with the highest mana value " +
"among creatures and planeswalkers they control"
);
static {
filter.add(MaxManaValueControlledPermanentPredicate.instance);
}
public RiveteersCharm(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}{R}{G}");
// Choose one
// Target opponent sacrifices a creature or planeswalker they control with the highest mana value among creatures and planeswalkers they control.
this.getSpellAbility().addEffect(new SacrificeEffect(filter, 1, "target opponent"));
this.getSpellAbility().addTarget(new TargetOpponent());
// Exile the top three cards of your library. Until your next end step, you may play those cards.
this.getSpellAbility().addMode(new Mode(new RiveteersCharmEffect()));
this.getSpellAbility().addWatcher(new RiveteersCharmWatcher());
// Exile target player's graveyard.
this.getSpellAbility().addMode(new Mode(new ExileGraveyardAllTargetPlayerEffect()).addTarget(new TargetPlayer()));
}
private RiveteersCharm(final RiveteersCharm card) {
super(card);
}
@Override
public RiveteersCharm copy() {
return new RiveteersCharm(this);
}
}
class RiveteersCharmEffect extends OneShotEffect {
RiveteersCharmEffect() {
super(Outcome.Benefit);
staticText = "exile the top three cards of your library. Until your next end step, you may play those cards";
}
private RiveteersCharmEffect(final RiveteersCharmEffect effect) {
super(effect);
}
@Override
public RiveteersCharmEffect copy() {
return new RiveteersCharmEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 3));
if (cards.isEmpty()) {
return false;
}
player.moveCards(cards, Zone.EXILED, source, game);
int count = RiveteersCharmWatcher.getCount(game, source);
Condition condition = (g, s) -> RiveteersCharmWatcher.getCount(g, s) == count;
for (Card card : cards.getCards(game)) {
CardUtil.makeCardPlayable(game, source, card, Duration.Custom, false, null, condition);
}
return true;
}
}
class RiveteersCharmWatcher extends Watcher {
private final Map<UUID, Integer> playerMap = new HashMap<>();
RiveteersCharmWatcher() {
super(WatcherScope.GAME);
}
@Override
public void watch(GameEvent event, Game game) {
switch (event.getType()) {
case END_TURN_STEP_PRE:
playerMap.compute(game.getActivePlayerId(), CardUtil::setOrIncrementValue);
return;
case BEGINNING_PHASE_PRE:
if (game.getTurnNum() == 1) {
playerMap.clear();
}
}
}
static int getCount(Game game, Ability source) {
return game
.getState()
.getWatcher(RiveteersCharmWatcher.class)
.playerMap
.getOrDefault(source.getControllerId(), 0);
}
}

View file

@ -1,19 +1,13 @@
package mage.cards.s;
import mage.MageObject;
import mage.abilities.effects.common.SacrificeOpponentsEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent;
import mage.filter.predicate.ObjectSourcePlayer;
import mage.filter.predicate.ObjectSourcePlayerPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.filter.predicate.permanent.MaxManaValueControlledPermanentPredicate;
import java.util.Objects;
import java.util.UUID;
/**
@ -27,7 +21,7 @@ public final class SoulShatter extends CardImpl {
);
static {
filter.add(SoulShatterPredicate.instance);
filter.add(MaxManaValueControlledPermanentPredicate.instance);
}
public SoulShatter(UUID ownerId, CardSetInfo setInfo) {
@ -46,25 +40,3 @@ public final class SoulShatter extends CardImpl {
return new SoulShatter(this);
}
}
enum SoulShatterPredicate implements ObjectSourcePlayerPredicate<Permanent> {
instance;
private static final FilterPermanent filter = new FilterCreatureOrPlaneswalkerPermanent();
static {
filter.add(TargetController.YOU.getControllerPredicate());
}
@Override
public boolean apply(ObjectSourcePlayer<Permanent> input, Game game) {
int cmc = game.getBattlefield()
.getActivePermanents(filter, input.getPlayerId(), game)
.stream()
.filter(Objects::nonNull)
.mapToInt(MageObject::getManaValue)
.max()
.orElse(0);
return input.getObject().getManaValue() >= cmc;
}
}

View file

@ -34,6 +34,7 @@ public final class StreetsOfNewCapenna extends ExpansionSet {
cards.add(new SetCardInfo("Plains", 272, Rarity.LAND, mage.cards.basiclands.Plains.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Raffine's Tower", 254, Rarity.RARE, mage.cards.r.RaffinesTower.class));
cards.add(new SetCardInfo("Raffine, Scheming Seer", 213, Rarity.MYTHIC, mage.cards.r.RaffineSchemingSeer.class));
cards.add(new SetCardInfo("Riveteers Charm", 217, Rarity.UNCOMMON, mage.cards.r.RiveteersCharm.class));
cards.add(new SetCardInfo("Spara's Headquarters", 257, Rarity.RARE, mage.cards.s.SparasHeadquarters.class));
cards.add(new SetCardInfo("Swamp", 276, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS));
cards.add(new SetCardInfo("Xander's Lounge", 260, Rarity.RARE, mage.cards.x.XandersLounge.class));

View file

@ -0,0 +1,37 @@
package mage.filter.predicate.permanent;
import mage.MageObject;
import mage.constants.TargetController;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent;
import mage.filter.predicate.ObjectSourcePlayer;
import mage.filter.predicate.ObjectSourcePlayerPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import java.util.Objects;
/**
* @author TheElk801
*/
public enum MaxManaValueControlledPermanentPredicate implements ObjectSourcePlayerPredicate<Permanent> {
instance;
private static final FilterPermanent filter = new FilterCreatureOrPlaneswalkerPermanent();
static {
filter.add(TargetController.YOU.getControllerPredicate());
}
@Override
public boolean apply(ObjectSourcePlayer<Permanent> input, Game game) {
int cmc = game.getBattlefield()
.getActivePermanents(filter, input.getPlayerId(), input.getSource(), game)
.stream()
.filter(Objects::nonNull)
.mapToInt(MageObject::getManaValue)
.max()
.orElse(0);
return input.getObject().getManaValue() >= cmc;
}
}

View file

@ -43923,7 +43923,8 @@ Jetmir, Nexus of Revels|Streets of New Capenna|193|M|{1}{R}{G}{W}|Legendary Crea
Lord Xander, the Collector|Streets of New Capenna|197|M|{4}{U}{B}{R}|Legendary Creature - Vampire Demon Noble|6|6|When Lord Xander, the Collector enters the battlefield, target opponent discards half the cards in their hand, rounded down.$Whenever Lord Xander attacks, defending player mills half their library, rounded down.$When Lord Xander dies, target opponent sacrifices half the nonland permanents they control, rounded down.|
Maestros Charm|Streets of New Capenna|199|U|{U}{B}{R}|Instant|||Choose one —$• Look at the top five cards of your library. Put one of those cards into your hand and the rest into your graveyard.$• Each opponent loses 3 life and you gain 3 life.$• Maestros Charm deals 5 damage to target creature or planeswalker.|
Obscura Charm|Streets of New Capenna|208|U|{W}{U}{B}|Instant|||Choose one —$• Return target multicolored permanent card with mana value 3 or less from your graveyard to the battlefield tapped.$• Counter target instant or sorcery spell.$• Destroy target creature or planeswalker with mana value 3 or less.|
Raffine, Scheming Seer|Streets of New Capenna|213|M|{W}{U}{B}|Legendary Creature - Sphinx Demon|1|4|Flying, ward {1}$Whenever you attack, target creature connives X, where X is the number of attacking creatures.|
Raffine, Scheming Seer|Streets of New Capenna|213|M|{W}{U}{B}|Legendary Creature - Sphinx Demon|1|4|Flying, ward {1}$Whenever you attack, target attacking creature connives X, where X is the number of attacking creatures.|
Riveteers Charm|Streets of New Capenna|217|U|{B}{R}{G}|Instant|||Choose one —$• Target opponent sacrifices a creature or planeswalker they control with the highest mana value among creatures and planeswalkers they control.$• Exile the top three cards of your library. Until your next end step, you may play those cards.$• Exile target player's graveyard.|
Jetmir's Garden|Streets of New Capenna|250|R||Land - Mountain Forest Plains|||({T}: Add {R}, {G}, or {W}.)$Jetmir's Garden enters the battlefield tapped.$Cycling {3}|
Raffine's Tower|Streets of New Capenna|254|R||Land - Plains Island Swamp|||({T}: Add {W}, {U}, or {B}.)$Raffine's Tower enters the battlefield tapped.$Cycling {3}|
Spara's Headquarters|Streets of New Capenna|257|R||Land - Forest Plains Island|||({T}: Add {G}, {W}, or {U}.)$Spara's Headquarters enters the battlefield tapped.$Cycling {3}|