From f00e86c47a4c978c032678361aefc3d6fcffa2ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Krist=C3=B3f?= <20043803+balazskristof@users.noreply.github.com> Date: Sat, 15 Mar 2025 02:30:36 +0100 Subject: [PATCH] [TDM] Implement Rally the Monastery (#13447) --- .../src/mage/cards/r/RallyTheMonastery.java | 103 ++++++++++++++++++ .../src/mage/sets/TarkirDragonstorm.java | 1 + Utils/mtg-cards-data.txt | 1 + 3 files changed, 105 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/r/RallyTheMonastery.java diff --git a/Mage.Sets/src/mage/cards/r/RallyTheMonastery.java b/Mage.Sets/src/mage/cards/r/RallyTheMonastery.java new file mode 100644 index 00000000000..335b01cee14 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RallyTheMonastery.java @@ -0,0 +1,103 @@ +package mage.cards.r; + +import java.util.List; +import java.util.Objects; +import java.util.UUID; + +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect; +import mage.abilities.hint.ConditionHint; +import mage.abilities.hint.Hint; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; +import mage.game.Game; +import mage.game.permanent.token.BirdToken; +import mage.game.permanent.token.MonasteryMentorToken; +import mage.game.stack.Spell; +import mage.target.TargetPermanent; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.watchers.common.SpellsCastWatcher; + +/** + * @author balazskristof + */ +public final class RallyTheMonastery extends CardImpl { + + private static final Hint hint = new ConditionHint( + RallyTheMonasteryCondition.instance, "You've cast a spell this turn" + ); + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with power 4 or greater"); + + static { + filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3)); + } + + public RallyTheMonastery(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{W}"); + + // This spell costs {2} less to cast if you've cast another spell this turn. + this.addAbility(new SimpleStaticAbility( + Zone.ALL, + new SpellCostReductionSourceEffect(2, RallyTheMonasteryCondition.instance).setCanWorksOnStackOnly(true) + ).setRuleAtTheTop(true).addHint(hint)); + + // Choose one — + this.getSpellAbility().getModes().setMinModes(1); + this.getSpellAbility().getModes().setMaxModes(1); + // • Create two 1/1 white Monk creature tokens with prowess. + this.getSpellAbility().addEffect(new CreateTokenEffect(new MonasteryMentorToken(), 2)); + // • Up to two target creatures you control each get +2/+2 until end of turn. + Mode mode = new Mode(new BoostTargetEffect(2, 2)); + mode.addTarget(new TargetControlledCreaturePermanent(0, 2, StaticFilters.FILTER_CONTROLLED_CREATURES, false)); + this.getSpellAbility().getModes().addMode(mode); + // • Destroy target creature with power 4 or greater. + Mode mode2 = new Mode(new DestroyTargetEffect()); + mode2.addTarget(new TargetPermanent(filter)); + this.getSpellAbility().getModes().addMode(mode2); + } + + private RallyTheMonastery(final RallyTheMonastery card) { + super(card); + } + + @Override + public RallyTheMonastery copy() { + return new RallyTheMonastery(this); + } +} + +enum RallyTheMonasteryCondition implements Condition { + instance; + + @Override + public boolean apply(Game game, Ability source) { + SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class); + if (watcher == null) { + return false; + } + List spells = watcher.getSpellsCastThisTurn(source.getControllerId()); + return spells != null && spells + .stream() + .filter(Objects::nonNull) + .anyMatch(spell -> !spell.getSourceId().equals(source.getSourceId())); + } + + @Override + public String toString() { + return "you've cast another spell this turn"; + } +} + diff --git a/Mage.Sets/src/mage/sets/TarkirDragonstorm.java b/Mage.Sets/src/mage/sets/TarkirDragonstorm.java index 4346ffbc666..853dbf7dc8a 100644 --- a/Mage.Sets/src/mage/sets/TarkirDragonstorm.java +++ b/Mage.Sets/src/mage/sets/TarkirDragonstorm.java @@ -24,6 +24,7 @@ public final class TarkirDragonstorm extends ExpansionSet { cards.add(new SetCardInfo("Inevitable Defeat", 194, Rarity.RARE, mage.cards.i.InevitableDefeat.class)); cards.add(new SetCardInfo("Mox Jasper", 246, Rarity.MYTHIC, mage.cards.m.MoxJasper.class)); cards.add(new SetCardInfo("Narset, Jeskai Waymaster", 209, Rarity.RARE, mage.cards.n.NarsetJeskaiWaymaster.class)); + cards.add(new SetCardInfo("Rally the Monastery", 19, Rarity.UNCOMMON, mage.cards.r.RallyTheMonastery.class)); cards.add(new SetCardInfo("Shiko, Paragon of the Way", 223, Rarity.MYTHIC, mage.cards.s.ShikoParagonOfTheWay.class)); cards.add(new SetCardInfo("Skirmish Rhino", 224, Rarity.UNCOMMON, mage.cards.s.SkirmishRhino.class)); cards.add(new SetCardInfo("Smile at Death", 24, Rarity.MYTHIC, mage.cards.s.SmileAtDeath.class)); diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index d585e63d623..705fd64ef1a 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -57197,6 +57197,7 @@ Chaos, the Endless|Final Fantasy|221|U||Legendary Creature - Demon|5|5|Flying$Wh Sin, Spira's Punishment|Final Fantasy|242|R|{4}{B}{G}{U}|Legendary Creature - Leviathan Avatar|7|7|Flying$Whenever Sin enters or attacks, exile a permanent card from your graveyard at random, then create a tapped token that's a copy of that card. If the exiled card is a land card, repeat this process.| Cloud, Planet's Champion|Final Fantasy|552|M|{3}{R}{W}|Legendary Creature - Human Soldier Mercenary|4|4|During your turn, as long as Cloud is equipped, it has double strike and indestructible.$Equip abilities you activate that target Cloud cost {2} less to activate.| Sephiroth, Planet's Heir|Final Fantasy|553|M|{4}{U}{B}|Legendary Creature - Human Avatar Soldier|4|4|Vigilance$When Sephiroth enters, creatures your opponents control get -2/-2 until end of turn.$Whenever a creature an opponent controls dies, put a +1/+1 counter on Sephiroth.| +Rally the Monastery|Tarkir: Dragonstorm|19|U|{3}{W}|Instant|||This spell costs {2} less to cast if you've cast another spell this turn.$Choose one —$• Create two 1/1 white Monk creature tokens with prowess.$• Up to two target creatures you control each get +2/+2 until end of turn.$• Destroy target creature with power 4 or greater.| Smile at Death|Tarkir: Dragonstorm|24|M|{3}{W}{W}|Enchantment|||At the beginning of your upkeep, return up to two target creature cards with power 2 or less from your graveyard to the battlefield. Put a +1/+1 counter on each of those creatures.| Sarkhan, Dragon Ascendant|Tarkir: Dragonstorm|118|R|{1}{R}|Legendary Creature - Human Druid|2|2|When Sarkhan enters, you may behold a Dragon. If you do, create a Treasure token.$Whenever a Dragon you control enters, put a +1/+1 counter on Sarkhan. Until end of turn, Sarkhan becomes a Dragon in addition to its other types and gains flying.| Stormscale Scion|Tarkir: Dragonstorm|123|M|{4}{R}{R}|Creature - Dragon|4|4|Flying$Other Dragons you control get +1/+1.$Storm|