From 68706b4b6544f44c5bc430a7b3d47cea4a309645 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Sun, 8 Nov 2020 18:52:53 -0500 Subject: [PATCH] [CMR] Implemented Bell Biv deBorca, Spectral Sergeant --- .../cards/b/BellBorcaSpectralSergeant.java | 195 ++++++++++++++++++ Mage.Sets/src/mage/sets/CommanderLegends.java | 1 + 2 files changed, 196 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/b/BellBorcaSpectralSergeant.java diff --git a/Mage.Sets/src/mage/cards/b/BellBorcaSpectralSergeant.java b/Mage.Sets/src/mage/cards/b/BellBorcaSpectralSergeant.java new file mode 100644 index 00000000000..51be601eb60 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BellBorcaSpectralSergeant.java @@ -0,0 +1,195 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.MageSingleton; +import mage.abilities.StaticAbility; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect; +import mage.abilities.effects.common.continuous.SetPowerSourceEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; +import mage.players.Library; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; +import mage.watchers.Watcher; + +import java.io.ObjectStreamException; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BellBorcaSpectralSergeant extends CardImpl { + + public BellBorcaSpectralSergeant(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{W}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.SPIRIT); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(0); + this.toughness = new MageInt(5); + + // Note the converted mana cost of each card as it's put into exile. + this.addAbility(BellBorcaSpectralSergeantAbility.getInstance()); + + // Bell Borca, Spectral Sergeant's power is equal to the greatest number noted for it this turn. + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerSourceEffect( + BellBorcaSpectralSergeantValue.instance, Duration.EndOfGame + ).setText("{this}'s power is equal to the greatest number noted for it this turn"))); + + // At the beginning of your upkeep, exile the top card of your library. You may play that card this turn. + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new BellBorcaSpectralSergeantEffect(), TargetController.YOU, false + )); + } + + private BellBorcaSpectralSergeant(final BellBorcaSpectralSergeant card) { + super(card); + } + + @Override + public BellBorcaSpectralSergeant copy() { + return new BellBorcaSpectralSergeant(this); + } +} + +class BellBorcaSpectralSergeantAbility extends StaticAbility implements MageSingleton { + + private static final BellBorcaSpectralSergeantAbility instance = new BellBorcaSpectralSergeantAbility(); + + private Object readResolve() throws ObjectStreamException { + return instance; + } + + private BellBorcaSpectralSergeantAbility() { + super(Zone.BATTLEFIELD, new InfoEffect("note the converted mana cost of each card as it's put into exile")); + } + + @Override + public BellBorcaSpectralSergeantAbility copy() { + return instance; + } + + public static BellBorcaSpectralSergeantAbility getInstance() { + return instance; + } +} + +enum BellBorcaSpectralSergeantValue implements DynamicValue { + instance; + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + BellBorcaSpectralSergeantWatcher watcher = game.getState().getWatcher(BellBorcaSpectralSergeantWatcher.class); + return watcher == null ? 0 : watcher.getValue(sourceAbility.getSourceId()); + } + + @Override + public BellBorcaSpectralSergeantValue copy() { + return instance; + } + + @Override + public String getMessage() { + return ""; + } +} + +class BellBorcaSpectralSergeantWatcher extends Watcher { + + private static final FilterPermanent filter = new FilterPermanent(); + + static { + filter.add(new AbilityPredicate(BellBorcaSpectralSergeantAbility.class)); + } + + private final Map cmcMap = new HashMap<>(); + + BellBorcaSpectralSergeantWatcher() { + super(WatcherScope.GAME); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() != GameEvent.EventType.ZONE_CHANGE + || ((ZoneChangeEvent) event).getToZone() != Zone.EXILED) { + return; + } + Card card = game.getCard(event.getTargetId()); + if (card == null || card.isFaceDown(game)) { + return; + } + int cmc = card.getConvertedManaCost(); + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, game.getActivePlayerId(), game)) { + if (permanent == null) { + continue; + } + cmcMap.put(permanent.getId(), cmc); + } + } + + @Override + public void reset() { + cmcMap.clear(); + super.reset(); + } + + int getValue(UUID sourceId) { + return cmcMap.getOrDefault(sourceId, 0); + } +} + +class BellBorcaSpectralSergeantEffect extends OneShotEffect { + + BellBorcaSpectralSergeantEffect() { + super(Outcome.Benefit); + staticText = "exile the top card of your library. You may play that card this turn"; + } + + private BellBorcaSpectralSergeantEffect(final BellBorcaSpectralSergeantEffect effect) { + super(effect); + } + + @Override + public BellBorcaSpectralSergeantEffect copy() { + return new BellBorcaSpectralSergeantEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (sourcePermanent == null || controller == null || !controller.getLibrary().hasCards()) { + return false; + } + Library library = controller.getLibrary(); + Card card = library.getFromTop(game); + if (card == null) { + return true; + } + String exileName = sourcePermanent.getIdName() + " "; + controller.moveCardsToExile(card, source, game, true, source.getSourceId(), exileName); + ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn); + effect.setTargetPointer(new FixedTarget(card, game)); + game.addEffect(effect, source); + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/CommanderLegends.java b/Mage.Sets/src/mage/sets/CommanderLegends.java index adbe4cfeece..3f5b1f12044 100644 --- a/Mage.Sets/src/mage/sets/CommanderLegends.java +++ b/Mage.Sets/src/mage/sets/CommanderLegends.java @@ -69,6 +69,7 @@ public final class CommanderLegends extends ExpansionSet { cards.add(new SetCardInfo("Azure Fleet Admiral", 58, Rarity.COMMON, mage.cards.a.AzureFleetAdmiral.class)); cards.add(new SetCardInfo("Beast Within", 423, Rarity.UNCOMMON, mage.cards.b.BeastWithin.class)); cards.add(new SetCardInfo("Belbe, Corrupted Observer", 270, Rarity.RARE, mage.cards.b.BelbeCorruptedObserver.class)); + cards.add(new SetCardInfo("Bell Borca, Spectral Sergeant", 271, Rarity.RARE, mage.cards.b.BellBorcaSpectralSergeant.class)); cards.add(new SetCardInfo("Benevolent Blessing", 13, Rarity.COMMON, mage.cards.b.BenevolentBlessing.class)); cards.add(new SetCardInfo("Biowaste Blob", 219, Rarity.RARE, mage.cards.b.BiowasteBlob.class)); cards.add(new SetCardInfo("Bitter Revelation", 109, Rarity.COMMON, mage.cards.b.BitterRevelation.class));