From 0e5a366ae681b2982e8447096cd545d9b2fd63ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Krist=C3=B3f?= <20043803+balazskristof@users.noreply.github.com> Date: Fri, 16 May 2025 01:09:12 +0200 Subject: [PATCH] [FIC] Implement Blue Mage's Cane (#13629) --- Mage.Sets/src/mage/cards/b/BlueMagesCane.java | 108 ++++++++++++++++++ .../src/mage/sets/FinalFantasyCommander.java | 2 + 2 files changed, 110 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/b/BlueMagesCane.java diff --git a/Mage.Sets/src/mage/cards/b/BlueMagesCane.java b/Mage.Sets/src/mage/cards/b/BlueMagesCane.java new file mode 100644 index 00000000000..ebebb243889 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BlueMagesCane.java @@ -0,0 +1,108 @@ +package mage.cards.b; + +import java.util.UUID; + +import mage.ApprovingObject; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.AddCardSubtypeAttachedEffect; +import mage.abilities.effects.common.continuous.BoostEquippedEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EquipAbility; +import mage.cards.Card; +import mage.constants.*; +import mage.abilities.keyword.JobSelectAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.filter.common.FilterInstantOrSorceryCard; +import mage.filter.predicate.card.DefendingPlayerOwnsCardPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInGraveyard; +import mage.util.CardUtil; + +/** + * @author balazskristof + */ +public final class BlueMagesCane extends CardImpl { + + private static final FilterInstantOrSorceryCard filter = new FilterInstantOrSorceryCard( + "instant or sorcery card from defending player's graveyard" + ); + + static { + filter.add(DefendingPlayerOwnsCardPredicate.instance); + } + + public BlueMagesCane(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{U}"); + + this.subtype.add(SubType.EQUIPMENT); + + // Job select + this.addAbility(new JobSelectAbility()); + + // Equipped creature gets +0/+2, is a Wizard in addition to its other types, and has "Whenever this creature attacks, exile up to one target instant or sorcery card from defending player's graveyard. If you do, copy it. You may cast the copy by paying {3} rather than paying its mana cost." + Ability ability = new SimpleStaticAbility(new BoostEquippedEffect(0, 2)); + ability.addEffect(new AddCardSubtypeAttachedEffect(SubType.WIZARD, AttachmentType.EQUIPMENT) + .setText(", is a Wizard in addition to its other types") + ); + Ability attackAbility = new AttacksTriggeredAbility(new BlueMagesCaneEffect()); + attackAbility.addTarget(new TargetCardInGraveyard(0, 1, filter)); + ability.addEffect(new GainAbilityAttachedEffect(attackAbility, AttachmentType.EQUIPMENT) + .setText("and has \"Whenever this creature attacks, exile up to one target instant or sorcery card from defending player's graveyard. " + + "If you do, copy it. You may cast the copy by paying {3} rather than paying its mana cost.\"") + ); + this.addAbility(ability); + + // Spirit of the Whalaqee -- Equip {2} + this.addAbility(new EquipAbility(2).withFlavorWord("Spirit of the Whalaqee")); + } + + private BlueMagesCane(final BlueMagesCane card) { + super(card); + } + + @Override + public BlueMagesCane copy() { + return new BlueMagesCane(this); + } +} + +class BlueMagesCaneEffect extends OneShotEffect { + + BlueMagesCaneEffect() { + super(Outcome.Benefit); + staticText = "exile up to one target instant or sorcery card from defending player's graveyard. " + + "If you do, copy it. You may cast the copy by paying {3} rather than paying its mana cost."; + } + + private BlueMagesCaneEffect(final BlueMagesCaneEffect effect) { + super(effect); + } + + @Override + public BlueMagesCaneEffect copy() { + return new BlueMagesCaneEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Card card = game.getCard(getTargetPointer().getFirst(game, source)); + if (controller == null || card == null) { + return false; + } + controller.moveCards(card, Zone.EXILED, source, game); + Card copiedCard = game.copyCard(card, source, source.getControllerId()); + if (!controller.chooseUse(Outcome.Benefit, "Cast " + copiedCard.getName() + " by paying {3}?", source, game)) { + return false; + } + CardUtil.castSingle(controller, source, game, copiedCard, new ManaCostsImpl<>("{3}")); + return true; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/FinalFantasyCommander.java b/Mage.Sets/src/mage/sets/FinalFantasyCommander.java index 638ee75de1d..c6c72fb2510 100644 --- a/Mage.Sets/src/mage/sets/FinalFantasyCommander.java +++ b/Mage.Sets/src/mage/sets/FinalFantasyCommander.java @@ -57,6 +57,8 @@ public final class FinalFantasyCommander extends ExpansionSet { cards.add(new SetCardInfo("Bedevil", 319, Rarity.RARE, mage.cards.b.Bedevil.class)); cards.add(new SetCardInfo("Behemoth Sledge", 320, Rarity.UNCOMMON, mage.cards.b.BehemothSledge.class)); cards.add(new SetCardInfo("Big Score", 290, Rarity.COMMON, mage.cards.b.BigScore.class)); + cards.add(new SetCardInfo("Blue Mage's Cane", 112, Rarity.RARE, mage.cards.b.BlueMagesCane.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Blue Mage's Cane", 35, Rarity.RARE, mage.cards.b.BlueMagesCane.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Bonders' Enclave", 376, Rarity.RARE, mage.cards.b.BondersEnclave.class)); cards.add(new SetCardInfo("Bred for the Hunt", 321, Rarity.UNCOMMON, mage.cards.b.BredForTheHunt.class)); cards.add(new SetCardInfo("Bronze Guardian", 234, Rarity.RARE, mage.cards.b.BronzeGuardian.class));