From 84e1b44845c1ce6aff6431815b2ab39c124610dc Mon Sep 17 00:00:00 2001 From: Susucre <34709007+Susucre@users.noreply.github.com> Date: Thu, 27 Jul 2023 06:24:28 +0200 Subject: [PATCH] [CMM] Implement Leori, Sparktouched Hunter (#10669) --- .../mage/cards/l/LeoriSparktouchedHunter.java | 160 ++++++++++++++++++ Mage.Sets/src/mage/sets/CommanderMasters.java | 1 + .../mage/choices/ChoicePlaneswalkerType.java | 43 +++++ 3 files changed, 204 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/l/LeoriSparktouchedHunter.java create mode 100644 Mage/src/main/java/mage/choices/ChoicePlaneswalkerType.java diff --git a/Mage.Sets/src/mage/cards/l/LeoriSparktouchedHunter.java b/Mage.Sets/src/mage/cards/l/LeoriSparktouchedHunter.java new file mode 100644 index 00000000000..29c355cb436 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LeoriSparktouchedHunter.java @@ -0,0 +1,160 @@ +package mage.cards.l; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CopyStackObjectEffect; +import mage.abilities.hint.StaticHint; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.abilities.mana.ActivatedManaAbilityImpl; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.choices.Choice; +import mage.choices.ChoicePlaneswalkerType; +import mage.constants.*; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.stack.StackAbility; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author Susucr + */ +public final class LeoriSparktouchedHunter extends CardImpl { + + public LeoriSparktouchedHunter(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}{R}{W}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.ELEMENTAL); + this.subtype.add(SubType.CAT); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Whenever Leori, Sparktouched Hunter deals combat damage to a player, choose a planeswalker type. Until end of turn, whenever you activate an ability of a planeswalker of that type, copy that ability. You may choose new targets for the copies. + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility( + new LeoriSparktouchedHunterEffect(), + false + )); + } + + private LeoriSparktouchedHunter(final LeoriSparktouchedHunter card) { + super(card); + } + + @Override + public LeoriSparktouchedHunter copy() { + return new LeoriSparktouchedHunter(this); + } +} + + +class LeoriSparktouchedHunterEffect extends OneShotEffect { + + LeoriSparktouchedHunterEffect() { + super(Outcome.Benefit); + this.staticText = "choose a planeswalker type. Until end of turn, whenever you activate an ability " + + "of a planeswalker of that type, copy that ability. You may choose new targets for the copies."; + } + + private LeoriSparktouchedHunterEffect(final LeoriSparktouchedHunterEffect effect) { + super(effect); + } + + @Override + public LeoriSparktouchedHunterEffect copy() { + return new LeoriSparktouchedHunterEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + + Choice choice = new ChoicePlaneswalkerType(game.getObject(source)); + if (!controller.choose(outcome, choice, game)) { + return false; + } + + SubType subType = SubType.fromString(choice.getChoice()); + if (subType == null) { + return false; + } + + game.informPlayers(controller.getLogName() + " has chosen " + subType); + + game.addDelayedTriggeredAbility( + new LeoriSparktouchedHunterTriggeredAbility(subType), + source + ); + + return true; + } +} + + +class LeoriSparktouchedHunterTriggeredAbility extends DelayedTriggeredAbility { + + private final SubType subType; + + LeoriSparktouchedHunterTriggeredAbility(SubType subType) { + super(new CopyStackObjectEffect(), Duration.EndOfTurn, false); + this.subType = subType; + this.addHint(new StaticHint("Chosen Subtype: " + subType)); + } + + private LeoriSparktouchedHunterTriggeredAbility(final LeoriSparktouchedHunterTriggeredAbility ability) { + super(ability); + this.subType = ability.subType; + } + + @Override + public LeoriSparktouchedHunterTriggeredAbility copy() { + return new LeoriSparktouchedHunterTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ACTIVATED_ABILITY; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (!isControlledBy(event.getPlayerId())) { + return false; + } + + StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(event.getSourceId()); + if (stackAbility == null + || stackAbility.getStackAbility() instanceof ActivatedManaAbilityImpl) { + return false; + } + + Permanent permanent = game.getPermanentOrLKIBattlefield(stackAbility.getSourceId()); + if (permanent == null || !permanent.isPlaneswalker(game) || !permanent.hasSubtype(subType, game)) { + return false; + } + this.getEffects().setValue("stackObject", stackAbility); + return true; + } + + @Override + public String getRule() { + return "Whenever you activate an ability of a planeswalker of the chosen type, copy that ability. " + + "You may choose new targets for the copies."; + } +} diff --git a/Mage.Sets/src/mage/sets/CommanderMasters.java b/Mage.Sets/src/mage/sets/CommanderMasters.java index 0cfa94c64c9..c4bddd1cda6 100644 --- a/Mage.Sets/src/mage/sets/CommanderMasters.java +++ b/Mage.Sets/src/mage/sets/CommanderMasters.java @@ -352,6 +352,7 @@ public final class CommanderMasters extends ExpansionSet { cards.add(new SetCardInfo("Lavabelly Sliver", 927, Rarity.UNCOMMON, mage.cards.l.LavabellySliver.class)); cards.add(new SetCardInfo("Lazotep Sliver", 733, Rarity.RARE, mage.cards.l.LazotepSliver.class)); cards.add(new SetCardInfo("Legion Vanguard", 170, Rarity.COMMON, mage.cards.l.LegionVanguard.class)); + cards.add(new SetCardInfo("Leori, Sparktouched Hunter", 709, Rarity.MYTHIC, mage.cards.l.LeoriSparktouchedHunter.class)); cards.add(new SetCardInfo("Letter of Acceptance", 397, Rarity.COMMON, mage.cards.l.LetterOfAcceptance.class)); cards.add(new SetCardInfo("Lifeblood Hydra", 303, Rarity.RARE, mage.cards.l.LifebloodHydra.class)); cards.add(new SetCardInfo("Lightning Greaves", 398, Rarity.UNCOMMON, mage.cards.l.LightningGreaves.class)); diff --git a/Mage/src/main/java/mage/choices/ChoicePlaneswalkerType.java b/Mage/src/main/java/mage/choices/ChoicePlaneswalkerType.java new file mode 100644 index 00000000000..d779f394b71 --- /dev/null +++ b/Mage/src/main/java/mage/choices/ChoicePlaneswalkerType.java @@ -0,0 +1,43 @@ +package mage.choices; + +import mage.MageObject; +import mage.constants.SubType; + +import java.util.LinkedHashSet; +import java.util.stream.Collectors; + +public class ChoicePlaneswalkerType extends ChoiceImpl { + + private static final String DEFAULT_MESSAGE = "Choose a planeswalker type"; + + public ChoicePlaneswalkerType() { + this(true, DEFAULT_MESSAGE, null); + } + + public ChoicePlaneswalkerType(MageObject source) { + this(true, DEFAULT_MESSAGE, source); + } + + public ChoicePlaneswalkerType(String chooseMessage, MageObject source) { + this(true, chooseMessage, source); + } + + public ChoicePlaneswalkerType(boolean required, String chooseMessage, MageObject source) { + super(required); + this.setChoices(SubType.getPlaneswalkerTypes().stream().map(SubType::toString).collect(Collectors.toCollection(LinkedHashSet::new))); + this.setMessage(chooseMessage); + if (source != null) { + this.setSubMessage(source.getIdName()); + } + this.setSearchEnabled(true); + } + + public ChoicePlaneswalkerType(final ChoicePlaneswalkerType choice) { + super(choice); + } + + @Override + public ChoicePlaneswalkerType copy() { + return new ChoicePlaneswalkerType(this); + } +}