From f339ec09041b3e1408e706d7f9b249c68f353790 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 30 Mar 2023 19:40:36 -0400 Subject: [PATCH] [MOM] Implement Boon-Bringer Valkyrie --- .../src/mage/cards/b/BoonBringerValkyrie.java | 50 +++++++++ .../src/mage/sets/MarchOfTheMachine.java | 1 + .../mage/abilities/keyword/BackupAbility.java | 105 ++++++++++++++++++ Utils/keywords.txt | 1 + Utils/mtg-cards-data.txt | 2 +- 5 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 Mage.Sets/src/mage/cards/b/BoonBringerValkyrie.java create mode 100644 Mage/src/main/java/mage/abilities/keyword/BackupAbility.java diff --git a/Mage.Sets/src/mage/cards/b/BoonBringerValkyrie.java b/Mage.Sets/src/mage/cards/b/BoonBringerValkyrie.java new file mode 100644 index 0000000000..ef96780c89 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BoonBringerValkyrie.java @@ -0,0 +1,50 @@ +package mage.cards.b; + +import mage.MageInt; +import mage.abilities.keyword.BackupAbility; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.LifelinkAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BoonBringerValkyrie extends CardImpl { + + public BoonBringerValkyrie(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); + + this.subtype.add(SubType.ANGEL); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Backup 1 + BackupAbility backupAbility = new BackupAbility(this, 1); + this.addAbility(backupAbility); + + // Flying + backupAbility.addAbility(FlyingAbility.getInstance()); + + // First strike + backupAbility.addAbility(FirstStrikeAbility.getInstance()); + + // Lifelink + backupAbility.addAbility(LifelinkAbility.getInstance()); + } + + private BoonBringerValkyrie(final BoonBringerValkyrie card) { + super(card); + } + + @Override + public BoonBringerValkyrie copy() { + return new BoonBringerValkyrie(this); + } +} diff --git a/Mage.Sets/src/mage/sets/MarchOfTheMachine.java b/Mage.Sets/src/mage/sets/MarchOfTheMachine.java index 2bb3d011cb..da49208a50 100644 --- a/Mage.Sets/src/mage/sets/MarchOfTheMachine.java +++ b/Mage.Sets/src/mage/sets/MarchOfTheMachine.java @@ -23,6 +23,7 @@ public final class MarchOfTheMachine extends ExpansionSet { cards.add(new SetCardInfo("Alabaster Host Sanctifier", 4, Rarity.COMMON, mage.cards.a.AlabasterHostSanctifier.class)); cards.add(new SetCardInfo("Bloodfell Caves", 267, Rarity.COMMON, mage.cards.b.BloodfellCaves.class)); cards.add(new SetCardInfo("Blossoming Sands", 268, Rarity.COMMON, mage.cards.b.BlossomingSands.class)); + cards.add(new SetCardInfo("Boon-Bringer Valkyrie", 9, Rarity.RARE, mage.cards.b.BoonBringerValkyrie.class)); cards.add(new SetCardInfo("Chandra, Hope's Beacon", 134, Rarity.MYTHIC, mage.cards.c.ChandraHopesBeacon.class)); cards.add(new SetCardInfo("Dismal Backwater", 269, Rarity.COMMON, mage.cards.d.DismalBackwater.class)); cards.add(new SetCardInfo("Elspeth's Smite", 13, Rarity.UNCOMMON, mage.cards.e.ElspethsSmite.class)); diff --git a/Mage/src/main/java/mage/abilities/keyword/BackupAbility.java b/Mage/src/main/java/mage/abilities/keyword/BackupAbility.java new file mode 100644 index 0000000000..7983065c7f --- /dev/null +++ b/Mage/src/main/java/mage/abilities/keyword/BackupAbility.java @@ -0,0 +1,105 @@ +package mage.abilities.keyword; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.cards.Card; +import mage.constants.Outcome; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; +import mage.watchers.Watcher; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author TheElk801 + */ +public class BackupAbility extends EntersBattlefieldTriggeredAbility { + + private final Card card; + private final int amount; + private final List abilitiesToAdd = new ArrayList<>(); + + public BackupAbility(Card card, int amount) { + super(null, true); + this.addEffect(new BackupEffect(amount, abilitiesToAdd)); + this.card = card; + this.amount = amount; + this.addTarget(new TargetCreaturePermanent()); + } + + public BackupAbility(final BackupAbility ability) { + super(ability); + this.amount = ability.amount; + this.card = ability.card; + this.abilitiesToAdd.addAll(ability.abilitiesToAdd); + } + + @Override + public BackupAbility copy() { + return new BackupAbility(this); + } + + @Override + public String getRule() { + return "Backup " + amount + " (When this creature enters the battlefield, " + + "put a +1/+1 counter on target creature. If that's another creature, " + + "it gains the following abilit" + (abilitiesToAdd.size() > 1 ? "ies" : "y") + " until end of turn.)"; + } + + public void addAbility(Ability ability) { + addAbility(ability, null); + } + + public void addAbility(Ability ability, Watcher watcher) { + if (watcher != null) { + ability.addWatcher(watcher); + } + card.addAbility(ability); + abilitiesToAdd.add(ability); + } +} + +class BackupEffect extends OneShotEffect { + + private final int amount; + private final List abilitiesToAdd = new ArrayList<>(); + + public BackupEffect(int amount, List abilitiesToAdd) { + super(Outcome.Detriment); + this.amount = amount; + this.abilitiesToAdd.addAll(abilitiesToAdd); + } + + public BackupEffect(final BackupEffect effect) { + super(effect); + this.amount = effect.amount; + this.abilitiesToAdd.addAll(effect.abilitiesToAdd); + } + + @Override + public BackupEffect copy() { + return new BackupEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (permanent == null) { + return false; + } + permanent.addCounters(CounterType.P1P1.createInstance(amount), source, game); + if (permanent.getId().equals(source.getSourceId())) { + return true; + } + for (Ability ability : abilitiesToAdd) { + game.addEffect(new GainAbilityTargetEffect(ability).setTargetPointer(new FixedTarget(permanent, game)), source); + } + return true; + } +} diff --git a/Utils/keywords.txt b/Utils/keywords.txt index 3ed888417d..bddf298a58 100644 --- a/Utils/keywords.txt +++ b/Utils/keywords.txt @@ -3,6 +3,7 @@ Afterlife|number| Annihilator|number| Ascend|new| Assist|new| +Backup|card, number| Basic landcycling|cost| Battle cry|new| Bestow|card, manaString| diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index f434a96716..826720481b 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -48072,7 +48072,7 @@ Invasion of Ravnica|March of the Machine|1|M|{5}|Battle - Siege|4|(As a Siege en Guildpact Paragon|March of the Machine|1|M||Artifact Creature - Construct|5|5|Whenever you cast a spell that's exactly two colors, look at the top six cards of your library. You may reveal a card that's exactly two colors from among them and put it into your hand. Put the rest on the bottom of your library in a random order.| Alabaster Host Sanctifier|March of the Machine|4|C|{1}{W}|Creature - Phyrexian Cleric|2|2|Lifelink| Archangel Elspeth|March of the Machine|6|M|{2}{W}{W}|Legendary Planeswalker - Elspeth|4|+1: Create a 1/1 white Soldier creature token with lifelink.$-2: Put two +1/+1 counters on target creature. It becomes an Angel in addition to its other types and gains flying.$-6: Return all nonland permanent cards with mana value 3 or less from your graveyard to the battlefield.| -Boon Bringer Valkyrie|March of the Machine|9|R|{3}{W}{W}|Creature - Angel Warrior|4|4|Backup 1$Flying, first strike, lifelink| +Boon-Bringer Valkyrie|March of the Machine|9|R|{3}{W}{W}|Creature - Angel Warrior|4|4|Backup 1$Flying, first strike, lifelink| Elesh Norn|March of the Machine|12|M|{2}{W}{W}|Legendary Creature - Phyrexian Praetor|3|5|Vigilance$Whenever a source an opponent controls deals damage to you or a permanent you control, that source's controller loses 2 life unless they pay {1}.${2}{W}, Sacrifice three other creatures: Exile Elesh Norn, then return it to the battlefield transformed under its owner's control. Activate only as a sorcery.| The Argent Etchings|March of the Machine|12|M||Enchantment - Saga|||(As this Saga enters and after your draw step, add a lore counter.)$I -- Incubate 2 five times, then transform all Incubator tokens you control.$II -- Creatures you control get +1/+1 and gain double strike until end of turn.$III -- Destroy all other permanents except for artifacts, lands, and Phyrexians. Exile The Argent Etchings, then return it to the battlefield.| Elspeth's Smite|March of the Machine|13|U|{W}|Instant|||Elspeth's Smite deals 3 damage to target attacking or blocking creature. If that creature would die this turn, exile it instead.|