From a5d83aedc0b60d6e15a2949e7c19ef33d266447a Mon Sep 17 00:00:00 2001 From: theelk801 <theelk801@gmail.com> Date: Tue, 25 Apr 2023 08:03:28 -0400 Subject: [PATCH] [ONC] Implement Neyali, Suns' Vanguard --- .../src/mage/cards/n/NeyaliSunsVanguard.java | 176 ++++++++++++++++++ .../sets/PhyrexiaAllWillBeOneCommander.java | 1 + 2 files changed, 177 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/n/NeyaliSunsVanguard.java diff --git a/Mage.Sets/src/mage/cards/n/NeyaliSunsVanguard.java b/Mage.Sets/src/mage/cards/n/NeyaliSunsVanguard.java new file mode 100644 index 0000000000..37262e2102 --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NeyaliSunsVanguard.java @@ -0,0 +1,176 @@ +package mage.cards.n; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.DoubleStrikeAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.predicate.permanent.AttackingPredicate; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.Controllable; +import mage.game.Game; +import mage.game.events.DefenderAttackedEvent; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.permanent.PermanentToken; +import mage.players.Player; +import mage.util.CardUtil; +import mage.watchers.Watcher; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class NeyaliSunsVanguard extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("attacking tokens"); + + static { + filter.add(AttackingPredicate.instance); + filter.add(TokenPredicate.TRUE); + } + + public NeyaliSunsVanguard(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{W}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.REBEL); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Attacking tokens you control have double strike. + this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect( + DoubleStrikeAbility.getInstance(), Duration.WhileOnBattlefield, filter + ))); + + // Whenever one or more tokens you control attack a player, exile the top card of your library. During any turn you attacked with a token, you may play that card. + this.addAbility(new NeyaliSunsVanguardTriggeredAbility()); + } + + private NeyaliSunsVanguard(final NeyaliSunsVanguard card) { + super(card); + } + + @Override + public NeyaliSunsVanguard copy() { + return new NeyaliSunsVanguard(this); + } +} + +class NeyaliSunsVanguardTriggeredAbility extends TriggeredAbilityImpl { + + NeyaliSunsVanguardTriggeredAbility() { + super(Zone.BATTLEFIELD, new NeyaliSunsVanguardEffect()); + this.addWatcher(new NeyaliSunsVanguardWatcher()); + } + + private NeyaliSunsVanguardTriggeredAbility(final NeyaliSunsVanguardTriggeredAbility ability) { + super(ability); + } + + @Override + public NeyaliSunsVanguardTriggeredAbility copy() { + return new NeyaliSunsVanguardTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DEFENDER_ATTACKED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return game.getPlayer(event.getTargetId()) != null + && ((DefenderAttackedEvent) event) + .getAttackers(game) + .stream() + .filter(PermanentToken.class::isInstance) + .map(Controllable::getControllerId) + .anyMatch(this::isControlledBy); + } + + @Override + public String getRule() { + return "Whenever one or more tokens you control attack a player, exile the top card of your library. " + + "During any turn you attacked with a token, you may play that card."; + } +} + +class NeyaliSunsVanguardEffect extends OneShotEffect { + + NeyaliSunsVanguardEffect() { + super(Outcome.Benefit); + } + + private NeyaliSunsVanguardEffect(final NeyaliSunsVanguardEffect effect) { + super(effect); + } + + @Override + public NeyaliSunsVanguardEffect copy() { + return new NeyaliSunsVanguardEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + Card card = player.getLibrary().getFromTop(game); + if (card == null) { + return false; + } + player.moveCards(card, Zone.EXILED, source, game); + CardUtil.makeCardPlayable( + game, source, card, Duration.Custom, false, + source.getControllerId(), NeyaliSunsVanguardWatcher::checkPlayer + ); + return true; + } +} + +class NeyaliSunsVanguardWatcher extends Watcher { + + private final Set<UUID> set = new HashSet<>(); + + NeyaliSunsVanguardWatcher() { + super(WatcherScope.GAME); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() != GameEvent.EventType.ATTACKER_DECLARED) { + return; + } + Permanent permanent = game.getPermanent(event.getSourceId()); + if (permanent instanceof PermanentToken) { + set.add(permanent.getControllerId()); + } + } + + @Override + public void reset() { + super.reset(); + set.clear(); + } + + static boolean checkPlayer(Game game, Ability source) { + return game + .getState() + .getWatcher(NeyaliSunsVanguardWatcher.class) + .set + .contains(source.getControllerId()); + } +} diff --git a/Mage.Sets/src/mage/sets/PhyrexiaAllWillBeOneCommander.java b/Mage.Sets/src/mage/sets/PhyrexiaAllWillBeOneCommander.java index 69d50db9ff..e2dbcfd4cc 100644 --- a/Mage.Sets/src/mage/sets/PhyrexiaAllWillBeOneCommander.java +++ b/Mage.Sets/src/mage/sets/PhyrexiaAllWillBeOneCommander.java @@ -119,6 +119,7 @@ public final class PhyrexiaAllWillBeOneCommander extends ExpansionSet { cards.add(new SetCardInfo("Myr Battlesphere", 138, Rarity.RARE, mage.cards.m.MyrBattlesphere.class)); cards.add(new SetCardInfo("Myriad Landscape", 159, Rarity.UNCOMMON, mage.cards.m.MyriadLandscape.class)); cards.add(new SetCardInfo("Necroblossom Snarl", 160, Rarity.RARE, mage.cards.n.NecroblossomSnarl.class)); + cards.add(new SetCardInfo("Neyali, Suns' Vanguard", 2, Rarity.MYTHIC, mage.cards.n.NeyaliSunsVanguard.class)); cards.add(new SetCardInfo("Night's Whisper", 94, Rarity.COMMON, mage.cards.n.NightsWhisper.class)); cards.add(new SetCardInfo("Norn's Annex", 83, Rarity.RARE, mage.cards.n.NornsAnnex.class)); cards.add(new SetCardInfo("Norn's Choirmaster", 8, Rarity.RARE, mage.cards.n.NornsChoirmaster.class, NON_FULL_USE_VARIOUS));