From 4c8f60e3a253240e6e344d6516d754ca770d3e60 Mon Sep 17 00:00:00 2001 From: ssk97 Date: Mon, 29 Jul 2024 21:40:38 -0700 Subject: [PATCH] [PIP] Rampaging Yao Guai, Wild Wasteland, Synth Infiltrator, Paladin Elizabeth Taggerdy (#12613) * Rampaging Yao Guai * Wild Wasteland * Synth Infiltrator * Paladin Elizabeth Taggerdy * Fix not including target count if name contains X value * Fix missing {this} --- .../cards/p/PaladinElizabethTaggerdy.java | 99 +++++++++++++++++ .../src/mage/cards/r/RampagingYaoGuai.java | 105 ++++++++++++++++++ .../src/mage/cards/s/SynthInfiltrator.java | 61 ++++++++++ Mage.Sets/src/mage/cards/w/WildWasteland.java | 40 +++++++ Mage.Sets/src/mage/sets/Fallout.java | 4 + .../src/main/java/mage/target/TargetImpl.java | 2 +- 6 files changed, 310 insertions(+), 1 deletion(-) create mode 100644 Mage.Sets/src/mage/cards/p/PaladinElizabethTaggerdy.java create mode 100644 Mage.Sets/src/mage/cards/r/RampagingYaoGuai.java create mode 100644 Mage.Sets/src/mage/cards/s/SynthInfiltrator.java create mode 100644 Mage.Sets/src/mage/cards/w/WildWasteland.java diff --git a/Mage.Sets/src/mage/cards/p/PaladinElizabethTaggerdy.java b/Mage.Sets/src/mage/cards/p/PaladinElizabethTaggerdy.java new file mode 100644 index 00000000000..44f5e78d200 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PaladinElizabethTaggerdy.java @@ -0,0 +1,99 @@ +package mage.cards.p; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.keyword.BattalionAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.card.ManaValueLessThanOrEqualToSourcePowerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCardInHand; + +import java.util.UUID; + +/** + * + * @author notgreat + */ +public final class PaladinElizabethTaggerdy extends CardImpl { + public PaladinElizabethTaggerdy(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{W}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.KNIGHT); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Battalion -- Whenever Paladin Elizabeth Taggerdy and at least two other creatures attack, draw a card, then you may put a creature card with mana value X or less from your hand onto the battlefield tapped and attacking, where X is Paladin Elizabeth Taggerdy's power. + Ability ability = new BattalionAbility(new DrawCardSourceControllerEffect(1)); + ability.addEffect(new PaladinElizabethTaggerdyEffect().concatBy(", then")); + this.addAbility(ability); + + } + + private PaladinElizabethTaggerdy(final PaladinElizabethTaggerdy card) { + super(card); + } + + @Override + public PaladinElizabethTaggerdy copy() { + return new PaladinElizabethTaggerdy(this); + } +} + +//Based on Preeminent Captain +class PaladinElizabethTaggerdyEffect extends OneShotEffect { + + private static final FilterCard filter = new FilterCreatureCard("a creature card with mana value less than or equal to {this}'s power"); + + static { + filter.add(ManaValueLessThanOrEqualToSourcePowerPredicate.instance); + } + + public PaladinElizabethTaggerdyEffect() { + super(Outcome.PutCreatureInPlay); + this.staticText = "you may put a creature card with mana value X or less from your hand onto the battlefield tapped and attacking, where X is {this}'s power"; + } + + private PaladinElizabethTaggerdyEffect(final PaladinElizabethTaggerdyEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + TargetCardInHand target = new TargetCardInHand(filter); + if (controller != null && target.canChoose(controller.getId(), source, game) + && target.choose(outcome, controller.getId(), source.getSourceId(), source, game)) { + if (!target.getTargets().isEmpty()) { + UUID cardId = target.getFirstTarget(); + Card card = controller.getHand().get(cardId, game); + if (card != null) { + if (controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, true, null)) { + Permanent permanent = game.getPermanent(card.getId()); + if (permanent != null) { + game.getCombat().addAttackingCreature(permanent.getId(), game); + } + } + } + } + return true; + } + return false; + } + + @Override + public PaladinElizabethTaggerdyEffect copy() { + return new PaladinElizabethTaggerdyEffect(this); + } + +} diff --git a/Mage.Sets/src/mage/cards/r/RampagingYaoGuai.java b/Mage.Sets/src/mage/cards/r/RampagingYaoGuai.java new file mode 100644 index 00000000000..2386956b8ac --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RampagingYaoGuai.java @@ -0,0 +1,105 @@ +package mage.cards.r; + +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.dynamicvalue.common.GetXValue; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterArtifactOrEnchantmentPermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; + +import java.util.Objects; +import java.util.UUID; + +/** + * @author notgreat + */ +public final class RampagingYaoGuai extends CardImpl { + + public RampagingYaoGuai(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{X}{G}{G}{G}"); + + this.subtype.add(SubType.BEAR); + this.subtype.add(SubType.MUTANT); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // Rampaging Yao Guai enters the battlefield with X +1/+1 counters on it. + this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.P1P1.createInstance()))); + + // When Rampaging Yao Guai enters the battlefield, destroy any number of target artifacts and/or enchantments with total mana value X or less. + Ability ability = new EntersBattlefieldTriggeredAbility(new DestroyTargetEffect()); + ability.addTarget(new RampagingYaoGuaiTarget()); + this.addAbility(ability); + } + + private RampagingYaoGuai(final RampagingYaoGuai card) { + super(card); + } + + @Override + public RampagingYaoGuai copy() { + return new RampagingYaoGuai(this); + } +} + +//Based on Kairi, The Swirling Sky +class RampagingYaoGuaiTarget extends TargetPermanent { + + private static final FilterPermanent filter + = new FilterArtifactOrEnchantmentPermanent("artifacts and/or enchantments with total mana value X or less"); + + RampagingYaoGuaiTarget() { + super(0, Integer.MAX_VALUE, filter, false); + } + + private RampagingYaoGuaiTarget(final RampagingYaoGuaiTarget target) { + super(target); + } + + @Override + public RampagingYaoGuaiTarget copy() { + return new RampagingYaoGuaiTarget(this); + } + + @Override + public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) { + if (!super.canTarget(controllerId, id, source, game)) { + return false; + } + Permanent permanent = game.getPermanent(id); + if (permanent == null) { + return false; + } + int added = 0; // We need to prevent the target to be counted twice on revalidation. + if (!this.getTargets().contains(id)) { + added = permanent.getManaValue();// fresh target, adding its MV + } + return added + + this.getTargets() + .stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .mapToInt(MageObject::getManaValue) + .sum() <= GetXValue.instance.calculate(game, source, null); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/SynthInfiltrator.java b/Mage.Sets/src/mage/cards/s/SynthInfiltrator.java new file mode 100644 index 00000000000..7af3c8dfa0f --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SynthInfiltrator.java @@ -0,0 +1,61 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.EntersBattlefieldEffect; +import mage.abilities.effects.common.CopyPermanentEffect; +import mage.abilities.keyword.ImproviseAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.util.functions.CopyApplier; + +import java.util.UUID; + +/** + * @author notgreat + */ +public final class SynthInfiltrator extends CardImpl { + + public SynthInfiltrator(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}{U}{U}"); + + this.subtype.add(SubType.SYNTH); + this.power = new MageInt(0); + this.toughness = new MageInt(0); + + // Improvise + this.addAbility(new ImproviseAbility()); + + // You may have Synth Infiltrator enter the battlefield as a copy of any creature on the battlefield, except it's a Synth artifact creature in addition to its other types. + CopyApplier synthInfiltratorCopyApplier = new CopyApplier() { + @Override + public boolean apply(Game game, MageObject blueprint, Ability source, UUID copyToObjectId) { + blueprint.addCardType(CardType.ARTIFACT); + blueprint.addCardType(CardType.CREATURE); + blueprint.addSubType(SubType.SYNTH); + return true; + } + }; + Effect effect = new CopyPermanentEffect(StaticFilters.FILTER_PERMANENT_CREATURE, synthInfiltratorCopyApplier); + effect.setText("You may have {this} enter the battlefield as a copy of any creature on the battlefield, except it's a Synth artifact creature in addition to its other types"); + Ability ability = new SimpleStaticAbility(Zone.ALL, new EntersBattlefieldEffect(effect, "", true)); + this.addAbility(ability); + } + + private SynthInfiltrator(final SynthInfiltrator card) { + super(card); + } + + @Override + public SynthInfiltrator copy() { + return new SynthInfiltrator(this); + } +} diff --git a/Mage.Sets/src/mage/cards/w/WildWasteland.java b/Mage.Sets/src/mage/cards/w/WildWasteland.java new file mode 100644 index 00000000000..d97aed84fb6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WildWasteland.java @@ -0,0 +1,40 @@ +package mage.cards.w; + +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.ExileTopXMayPlayUntilEffect; +import mage.abilities.effects.common.SkipDrawStepEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.TargetController; + +import java.util.UUID; + +/** + * @author notgreat + */ +public final class WildWasteland extends CardImpl { + + public WildWasteland(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); + + + // Skip your draw step. + this.addAbility(new SimpleStaticAbility(new SkipDrawStepEffect())); + + // At the beginning of your upkeep, exile the top two cards of your library. You may play those cards this turn. + this.addAbility(new BeginningOfUpkeepTriggeredAbility( + new ExileTopXMayPlayUntilEffect(2, Duration.EndOfTurn), TargetController.YOU, false)); + } + + private WildWasteland(final WildWasteland card) { + super(card); + } + + @Override + public WildWasteland copy() { + return new WildWasteland(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Fallout.java b/Mage.Sets/src/mage/sets/Fallout.java index 494fd58ac68..88c37da9175 100644 --- a/Mage.Sets/src/mage/sets/Fallout.java +++ b/Mage.Sets/src/mage/sets/Fallout.java @@ -253,6 +253,7 @@ public final class Fallout extends ExpansionSet { cards.add(new SetCardInfo("Overseer of Vault 76", 547, Rarity.RARE, mage.cards.o.OverseerOfVault76.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Overseer of Vault 76", 896, Rarity.RARE, mage.cards.o.OverseerOfVault76.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Paladin Danse, Steel Maverick", 20, Rarity.UNCOMMON, mage.cards.p.PaladinDanseSteelMaverick.class)); + cards.add(new SetCardInfo("Paladin Elizabeth Taggerdy", 114, Rarity.RARE, mage.cards.p.PaladinElizabethTaggerdy.class)); cards.add(new SetCardInfo("Panharmonicon", 237, Rarity.RARE, mage.cards.p.Panharmonicon.class)); cards.add(new SetCardInfo("Path of Ancestry", 279, Rarity.COMMON, mage.cards.p.PathOfAncestry.class)); cards.add(new SetCardInfo("Path to Exile", 169, Rarity.UNCOMMON, mage.cards.p.PathToExile.class)); @@ -276,6 +277,7 @@ public final class Fallout extends ExpansionSet { cards.add(new SetCardInfo("Puresteel Paladin", 170, Rarity.RARE, mage.cards.p.PuresteelPaladin.class)); cards.add(new SetCardInfo("Putrefy", 219, Rarity.UNCOMMON, mage.cards.p.Putrefy.class)); cards.add(new SetCardInfo("Radstorm", 37, Rarity.RARE, mage.cards.r.Radstorm.class)); + cards.add(new SetCardInfo("Rampaging Yao Guai", 82, Rarity.RARE, mage.cards.r.RampagingYaoGuai.class)); cards.add(new SetCardInfo("Rampant Growth", 204, Rarity.COMMON, mage.cards.r.RampantGrowth.class)); cards.add(new SetCardInfo("Rancor", 205, Rarity.UNCOMMON, mage.cards.r.Rancor.class)); cards.add(new SetCardInfo("Raul, Trouble Shooter", 115, Rarity.UNCOMMON, mage.cards.r.RaulTroubleShooter.class)); @@ -340,6 +342,7 @@ public final class Fallout extends ExpansionSet { cards.add(new SetCardInfo("Swiftfoot Boots", 242, Rarity.UNCOMMON, mage.cards.s.SwiftfootBoots.class)); cards.add(new SetCardInfo("Swords to Plowshares", 173, Rarity.UNCOMMON, mage.cards.s.SwordsToPlowshares.class)); cards.add(new SetCardInfo("Synth Eradicator", 67, Rarity.RARE, mage.cards.s.SynthEradicator.class)); + cards.add(new SetCardInfo("Synth Infiltrator", 40, Rarity.RARE, mage.cards.s.SynthInfiltrator.class)); cards.add(new SetCardInfo("T-45 Power Armor", 145, Rarity.RARE, mage.cards.t.T45PowerArmor.class)); cards.add(new SetCardInfo("Tainted Field", 298, Rarity.UNCOMMON, mage.cards.t.TaintedField.class)); cards.add(new SetCardInfo("Tainted Isle", 299, Rarity.UNCOMMON, mage.cards.t.TaintedIsle.class)); @@ -418,6 +421,7 @@ public final class Fallout extends ExpansionSet { cards.add(new SetCardInfo("Whirler Rogue", 181, Rarity.UNCOMMON, mage.cards.w.WhirlerRogue.class)); cards.add(new SetCardInfo("White Glove Gourmand", 124, Rarity.UNCOMMON, mage.cards.w.WhiteGloveGourmand.class)); cards.add(new SetCardInfo("Wild Growth", 208, Rarity.COMMON, mage.cards.w.WildGrowth.class)); + cards.add(new SetCardInfo("Wild Wasteland", 71, Rarity.RARE, mage.cards.w.WildWasteland.class)); cards.add(new SetCardInfo("Windbrisk Heights", 315, Rarity.RARE, mage.cards.w.WindbriskHeights.class)); cards.add(new SetCardInfo("Winding Constrictor", 223, Rarity.UNCOMMON, mage.cards.w.WindingConstrictor.class)); cards.add(new SetCardInfo("Woodland Cemetery", 316, Rarity.RARE, mage.cards.w.WoodlandCemetery.class)); diff --git a/Mage/src/main/java/mage/target/TargetImpl.java b/Mage/src/main/java/mage/target/TargetImpl.java index 5e885ffb8cf..5dec6908b1e 100644 --- a/Mage/src/main/java/mage/target/TargetImpl.java +++ b/Mage/src/main/java/mage/target/TargetImpl.java @@ -106,7 +106,7 @@ public abstract class TargetImpl implements Target { if (min > 0 && max == Integer.MAX_VALUE) { sb.append(CardUtil.numberToText(min)); sb.append(" or more "); - } else if (!getTargetName().contains("X") && (min != 1 || max != 1)) { + } else if (!getTargetName().startsWith("X ") && (min != 1 || max != 1)) { if (min < max && max != Integer.MAX_VALUE) { if (min == 1 && max == 2) { sb.append("one or ");