From dfe9390a2a58f1fdc1ef094494e3171c4f86e047 Mon Sep 17 00:00:00 2001 From: Susucre <34709007+Susucre@users.noreply.github.com> Date: Fri, 31 May 2024 18:26:42 +0200 Subject: [PATCH] implement [MH3] Crabomination --- Mage.Sets/src/mage/cards/c/Crabomination.java | 108 ++++++++++++++++++ Mage.Sets/src/mage/sets/ModernHorizons3.java | 1 + .../mage/abilities/keyword/EmergeAbility.java | 39 +++++-- 3 files changed, 139 insertions(+), 9 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/c/Crabomination.java diff --git a/Mage.Sets/src/mage/cards/c/Crabomination.java b/Mage.Sets/src/mage/cards/c/Crabomination.java new file mode 100644 index 00000000000..74158b09d64 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/Crabomination.java @@ -0,0 +1,108 @@ +package mage.cards.c; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.EmergeAbility; +import mage.cards.*; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledArtifactPermanent; +import mage.filter.predicate.permanent.CanBeSacrificedPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetOpponent; +import mage.util.CardUtil; + +import java.util.UUID; + +/** + * @author Susucr + */ +public final class Crabomination extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledArtifactPermanent(); + + static { + filter.add(CanBeSacrificedPredicate.instance); + } + + public Crabomination(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}{B}"); + + this.subtype.add(SubType.CRAB); + this.subtype.add(SubType.DEMON); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Emerge from artifact {5}{B}{B} + this.addAbility(new EmergeAbility(this, "{5}{B}{B}", filter, "from artifact")); + + // When Crabomination enters the battlefield, target opponent exiles the top card of their library, a card at random from their graveyard, and a card at random from their hand. You may cast a spell from among cards exiled this way without paying its mana cost. + Ability ability = new EntersBattlefieldTriggeredAbility(new CrabominationEffect()); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); + } + + private Crabomination(final Crabomination card) { + super(card); + } + + @Override + public Crabomination copy() { + return new Crabomination(this); + } +} + +class CrabominationEffect extends OneShotEffect { + + CrabominationEffect() { + super(Outcome.Benefit); + staticText = "target opponent exiles the top card of their library, " + + "a card at random from their graveyard, " + + "and a card at random from their hand. " + + "You may cast a spell from among cards exiled this way without paying its mana cost"; + } + + private CrabominationEffect(final CrabominationEffect effect) { + super(effect); + } + + @Override + public CrabominationEffect copy() { + return new CrabominationEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player opponent = game.getPlayer(getTargetPointer().getFirst(game, source)); + Player controller = game.getPlayer(source.getControllerId()); + if (opponent == null || controller == null) { + return false; + } + Cards cards = new CardsImpl(); + Card fromTop = opponent.getLibrary().getFromTop(game); + if (fromTop != null) { + cards.add(fromTop); + } + Card fromGraveyard = opponent.getGraveyard().getRandom(game); + if (fromGraveyard != null) { + cards.add(fromGraveyard); + } + Card fromHand = opponent.getHand().getRandom(game); + if (fromHand != null) { + cards.add(fromHand); + } + opponent.moveCardsToExile(cards.getCards(game), source, game, true, null, ""); + game.getState().processAction(game); + cards.retainZone(Zone.EXILED, game); + CardUtil.castSpellWithAttributesForFree(controller, source, game, cards, StaticFilters.FILTER_CARD); + return true; + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/ModernHorizons3.java b/Mage.Sets/src/mage/sets/ModernHorizons3.java index 9796891dae4..2aca9b9a855 100644 --- a/Mage.Sets/src/mage/sets/ModernHorizons3.java +++ b/Mage.Sets/src/mage/sets/ModernHorizons3.java @@ -53,6 +53,7 @@ public final class ModernHorizons3 extends ExpansionSet { cards.add(new SetCardInfo("Consuming Corruption", 84, Rarity.UNCOMMON, mage.cards.c.ConsumingCorruption.class)); cards.add(new SetCardInfo("Contaminated Landscape", 218, Rarity.COMMON, mage.cards.c.ContaminatedLandscape.class)); cards.add(new SetCardInfo("Copycrook", 55, Rarity.UNCOMMON, mage.cards.c.Copycrook.class)); + cards.add(new SetCardInfo("Crabomination", 85, Rarity.RARE, mage.cards.c.Crabomination.class)); cards.add(new SetCardInfo("Cranial Ram", 180, Rarity.COMMON, mage.cards.c.CranialRam.class)); cards.add(new SetCardInfo("Cursed Mirror", 279, Rarity.RARE, mage.cards.c.CursedMirror.class)); cards.add(new SetCardInfo("Cursed Wombat", 181, Rarity.UNCOMMON, mage.cards.c.CursedWombat.class)); diff --git a/Mage/src/main/java/mage/abilities/keyword/EmergeAbility.java b/Mage/src/main/java/mage/abilities/keyword/EmergeAbility.java index 54d1c457e7a..3c06cccbd34 100644 --- a/Mage/src/main/java/mage/abilities/keyword/EmergeAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/EmergeAbility.java @@ -13,7 +13,6 @@ import mage.constants.Outcome; import mage.constants.SpellAbilityType; import mage.constants.Zone; import mage.filter.FilterPermanent; -import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.permanent.CanBeSacrificedPredicate; import mage.game.Game; @@ -33,17 +32,29 @@ public class EmergeAbility extends SpellAbility { public static final String EMERGE_ACTIVATION_CREATURE_REFERENCE = "emergeActivationMOR"; private static final FilterPermanent SAC_FILTER = new FilterControlledCreaturePermanent(); + static { SAC_FILTER.add(CanBeSacrificedPredicate.instance); } - public EmergeAbility(Card card, String emergeString) { + private final String emergeFromText; + private final FilterPermanent filter; + + public EmergeAbility(Card card, String emergeManaString) { + this(card, emergeManaString, SAC_FILTER, ""); + } + + public EmergeAbility(Card card, String emergeManaString, FilterPermanent filter, String emergeFromText) { super(card.getSpellAbility()); - this.emergeCost = new ManaCostsImpl<>(emergeString); + + this.filter = filter; + this.emergeFromText = emergeFromText; + + this.emergeCost = new ManaCostsImpl<>(emergeManaString); this.newId(); // Set newId because cards spell ability is copied and needs own id this.setCardName(card.getName() + " with emerge"); - zone = Zone.HAND; - spellAbilityType = SpellAbilityType.BASE_ALTERNATE; + this.zone = Zone.HAND; + this.spellAbilityType = SpellAbilityType.BASE_ALTERNATE; this.clearManaCosts(); this.clearManaCostsToPay(); @@ -52,9 +63,11 @@ public class EmergeAbility extends SpellAbility { this.setRuleAtTheTop(true); } - protected EmergeAbility(final EmergeAbility ability) { + private EmergeAbility(final EmergeAbility ability) { super(ability); this.emergeCost = ability.emergeCost.copy(); + this.filter = ability.filter; + this.emergeFromText = ability.emergeFromText; } @Override @@ -63,7 +76,7 @@ public class EmergeAbility extends SpellAbility { Player controller = game.getPlayer(this.getControllerId()); if (controller != null) { for (Permanent creature : game.getBattlefield().getActivePermanents( - SAC_FILTER, this.getControllerId(), this, game)) { + filter, this.getControllerId(), this, game)) { ManaCost costToPay = CardUtil.reduceCost(emergeCost.copy(), creature.getManaValue()); if (costToPay.canPay(this, this, this.getControllerId(), game)) { return new ActivationStatus(new ApprovingObject(this, game)); @@ -98,7 +111,7 @@ public class EmergeAbility extends SpellAbility { public boolean activate(Game game, boolean noMana) { Player controller = game.getPlayer(this.getControllerId()); if (controller != null) { - TargetSacrifice target = new TargetSacrifice(StaticFilters.FILTER_PERMANENT_A_CREATURE); + TargetSacrifice target = new TargetSacrifice(filter); target.withChooseHint("to sacrifice for emerge"); if (controller.choose(Outcome.Sacrifice, target, this, game)) { Permanent creature = game.getPermanent(target.getFirstTarget()); @@ -131,6 +144,14 @@ public class EmergeAbility extends SpellAbility { @Override public String getRule() { - return "Emerge " + emergeCost.getText() + " (You may cast this spell by sacrificing a creature and paying the emerge cost reduced by that creature's mana value.)"; + String text = "Emerge "; + if (!emergeFromText.isEmpty()) { + text += emergeFromText + " "; + } + text += emergeCost.getText(); + if (emergeFromText.isEmpty()) { + text += " (You may cast this spell by sacrificing a creature and paying the emerge cost reduced by that creature's mana value.)"; + } + return text; } }