From f0b08424e645ce1835122d96c728ed7d236f790e Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Sun, 21 Nov 2021 17:20:26 -0500 Subject: [PATCH] [VOC] Implemented Umbris, Fear Manifest --- .../src/mage/cards/u/UmbrisFearManifest.java | 140 ++++++++++++++++++ .../src/mage/sets/CrimsonVowCommander.java | 1 + 2 files changed, 141 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/u/UmbrisFearManifest.java diff --git a/Mage.Sets/src/mage/cards/u/UmbrisFearManifest.java b/Mage.Sets/src/mage/cards/u/UmbrisFearManifest.java new file mode 100644 index 00000000000..1bcc17d63e8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/u/UmbrisFearManifest.java @@ -0,0 +1,140 @@ +package mage.cards.u; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.Predicates; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetOpponent; + +import java.util.Collection; +import java.util.Objects; +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class UmbrisFearManifest extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledPermanent("Nightmare or Horror"); + + static { + filter.add(Predicates.or( + SubType.NIGHTMARE.getPredicate(), + SubType.HORROR.getPredicate() + )); + } + + public UmbrisFearManifest(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{B}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.NIGHTMARE); + this.subtype.add(SubType.HORROR); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Umbris, Fear Manifest gets +1/+1 for each card your opponents own in exile. + this.addAbility(new SimpleStaticAbility(new BoostSourceEffect( + UmbrisFearManifestValue.instance, + UmbrisFearManifestValue.instance, + Duration.WhileOnBattlefield + ))); + + // Whenever Umbris or another Nightmare or Horror enters the battlefield under your control, target opponent exiles cards from the top of their library until they exile a land card. + Ability ability = new EntersBattlefieldThisOrAnotherTriggeredAbility( + new UmbrisFearManifestEffect(), filter, false, true + ); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); + } + + private UmbrisFearManifest(final UmbrisFearManifest card) { + super(card); + } + + @Override + public UmbrisFearManifest copy() { + return new UmbrisFearManifest(this); + } +} + +enum UmbrisFearManifestValue implements DynamicValue { + instance; + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + return game + .getState() + .getExile() + .getExileZones() + .stream() + .map(exileZone -> exileZone.getCards(game)) + .flatMap(Collection::stream) + .filter(Objects::nonNull) + .map(Card::getOwnerId) + .filter(game.getOpponents(sourceAbility.getSourceId())::contains) + .mapToInt(x -> 1) + .sum(); + } + + @Override + public UmbrisFearManifestValue copy() { + return this; + } + + @Override + public String getMessage() { + return "card your opponents own in exile"; + } + + @Override + public String toString() { + return "1"; + } +} + +class UmbrisFearManifestEffect extends OneShotEffect { + + UmbrisFearManifestEffect() { + super(Outcome.Benefit); + staticText = "target opponent exiles cards from the top of their library until they exile a land card"; + } + + private UmbrisFearManifestEffect(final UmbrisFearManifestEffect effect) { + super(effect); + } + + @Override + public UmbrisFearManifestEffect copy() { + return new UmbrisFearManifestEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getFirstTarget()); + if (player == null) { + return false; + } + for (int i = 0; i < 1000; i++) { // avoiding a loop + Card card = player.getLibrary().getFromTop(game); + player.moveCards(card, Zone.EXILED, source, game); + if (card.isLand(game)) { + break; + } + } + return true; + } +} diff --git a/Mage.Sets/src/mage/sets/CrimsonVowCommander.java b/Mage.Sets/src/mage/sets/CrimsonVowCommander.java index 7db516ebf56..aa1b2ede10e 100644 --- a/Mage.Sets/src/mage/sets/CrimsonVowCommander.java +++ b/Mage.Sets/src/mage/sets/CrimsonVowCommander.java @@ -148,6 +148,7 @@ public final class CrimsonVowCommander extends ExpansionSet { cards.add(new SetCardInfo("Thundering Mightmare", 37, Rarity.RARE, mage.cards.t.ThunderingMightmare.class)); cards.add(new SetCardInfo("Timin, Youthful Geist", 16, Rarity.RARE, mage.cards.t.TiminYouthfulGeist.class)); cards.add(new SetCardInfo("Twilight Drover", 100, Rarity.RARE, mage.cards.t.TwilightDrover.class)); + cards.add(new SetCardInfo("Umbris, Fear Manifest", 38, Rarity.MYTHIC, mage.cards.u.UmbrisFearManifest.class)); cards.add(new SetCardInfo("Unclaimed Territory", 188, Rarity.UNCOMMON, mage.cards.u.UnclaimedTerritory.class)); cards.add(new SetCardInfo("Underworld Connections", 138, Rarity.RARE, mage.cards.u.UnderworldConnections.class)); cards.add(new SetCardInfo("Unstable Obelisk", 170, Rarity.UNCOMMON, mage.cards.u.UnstableObelisk.class));