From 1a205ff193e282aba27c966591c706319481af8d Mon Sep 17 00:00:00 2001 From: Susucre <34709007+Susucre@users.noreply.github.com> Date: Thu, 26 Oct 2023 12:22:18 +0200 Subject: [PATCH] [LCI] Implement Jadelight Spelunker --- .../src/mage/cards/d/DeadeyeTracker.java | 7 +-- .../src/mage/cards/j/JadelightRanger.java | 11 ++-- .../src/mage/cards/j/JadelightSpelunker.java | 44 +++++++++++++++ .../src/mage/sets/TheLostCavernsOfIxalan.java | 1 + .../effects/keyword/ExploreSourceEffect.java | 56 ++++++++++++------- .../effects/keyword/ExploreTargetEffect.java | 4 +- 6 files changed, 94 insertions(+), 29 deletions(-) create mode 100644 Mage.Sets/src/mage/cards/j/JadelightSpelunker.java diff --git a/Mage.Sets/src/mage/cards/d/DeadeyeTracker.java b/Mage.Sets/src/mage/cards/d/DeadeyeTracker.java index c9175b6764b..613413f41ae 100644 --- a/Mage.Sets/src/mage/cards/d/DeadeyeTracker.java +++ b/Mage.Sets/src/mage/cards/d/DeadeyeTracker.java @@ -1,7 +1,6 @@ package mage.cards.d; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -18,8 +17,9 @@ import mage.constants.Zone; import mage.filter.FilterCard; import mage.target.common.TargetCardInOpponentsGraveyard; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class DeadeyeTracker extends CardImpl { @@ -35,8 +35,7 @@ public final class DeadeyeTracker extends CardImpl { // {1}{B}, {T}: Exile two target cards from an opponent's graveyard. Deadeye Tracker explores. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ExileTargetEffect(), new TapSourceCost()); ability.addCost(new ManaCostsImpl<>("{1}{B}")); - Effect effect = new ExploreSourceEffect(); - effect.setText("{this} explores"); + Effect effect = new ExploreSourceEffect(true, "{this}"); ability.addEffect(effect); ability.addTarget(new TargetCardInOpponentsGraveyard(2, 2, new FilterCard("cards from an opponent's graveyard"), true)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/j/JadelightRanger.java b/Mage.Sets/src/mage/cards/j/JadelightRanger.java index 2caf4dfcdb9..fd0164d1f3e 100644 --- a/Mage.Sets/src/mage/cards/j/JadelightRanger.java +++ b/Mage.Sets/src/mage/cards/j/JadelightRanger.java @@ -1,7 +1,6 @@ package mage.cards.j; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.keyword.ExploreSourceEffect; import mage.cards.CardImpl; @@ -26,9 +25,13 @@ public final class JadelightRanger extends CardImpl { this.toughness = new MageInt(1); // When Jadelight Ranger enters the battlefield, it explores, then it explores again. - Ability ability = new EntersBattlefieldTriggeredAbility(new ExploreSourceEffect(false, "it"), false); - ability.addEffect(new ExploreSourceEffect().setText(", then it explores again. (Reveal the top card of your library. Put that card into your hand if it's a land. Otherwise, put a +1/+1 counter on this creature, then put the card back or put it into your graveyard. Then repeat this process.)")); - this.addAbility(ability); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new ExploreSourceEffect(2, false, "it") + .setText("it explores, then it explores again. (Reveal the top card of your library. " + + "Put that card into your hand if it's a land. Otherwise, put a +1/+1 counter on this creature, " + + "then put the card back or put it into your graveyard. Then repeat this process.)"), + false + )); } private JadelightRanger(final JadelightRanger card) { diff --git a/Mage.Sets/src/mage/cards/j/JadelightSpelunker.java b/Mage.Sets/src/mage/cards/j/JadelightSpelunker.java new file mode 100644 index 00000000000..68b1044c4cf --- /dev/null +++ b/Mage.Sets/src/mage/cards/j/JadelightSpelunker.java @@ -0,0 +1,44 @@ +package mage.cards.j; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.dynamicvalue.common.ManacostVariableValue; +import mage.abilities.effects.keyword.ExploreSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author Susucr + */ +public final class JadelightSpelunker extends CardImpl { + + public JadelightSpelunker(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{X}{G}"); + + this.subtype.add(SubType.MERFOLK); + this.subtype.add(SubType.SCOUT); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // When Jadelight Spelunker enters the battlefield, it explores X times. + this.addAbility(new EntersBattlefieldTriggeredAbility( + new ExploreSourceEffect(ManacostVariableValue.ETB, false, "{it}") + .setText("it explores X times. (To have it explore, reveal the top card of your library. " + + "Put that card into your hand if it’s a land. Otherwise, put a +1/+1 counter on that creature, " + + "then put the card back or put it into your graveyard.)") + )); + } + + private JadelightSpelunker(final JadelightSpelunker card) { + super(card); + } + + @Override + public JadelightSpelunker copy() { + return new JadelightSpelunker(this); + } +} diff --git a/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java b/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java index 27af935a58e..3995d3373a6 100644 --- a/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java +++ b/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java @@ -41,6 +41,7 @@ public final class TheLostCavernsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Huatli, Poet of Unity", 189, Rarity.MYTHIC, mage.cards.h.HuatliPoetOfUnity.class)); cards.add(new SetCardInfo("Island", 395, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Itlimoc, Cradle of the Sun", 188, Rarity.RARE, mage.cards.i.ItlimocCradleOfTheSun.class)); + cards.add(new SetCardInfo("Jadelight Spelunker", 196, Rarity.RARE, mage.cards.j.JadelightSpelunker.class)); cards.add(new SetCardInfo("Kellan, Daring Traveler", 231, Rarity.RARE, mage.cards.k.KellanDaringTraveler.class)); cards.add(new SetCardInfo("Miner's Guidewing", 24, Rarity.COMMON, mage.cards.m.MinersGuidewing.class)); cards.add(new SetCardInfo("Mountain", 399, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); diff --git a/Mage/src/main/java/mage/abilities/effects/keyword/ExploreSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/keyword/ExploreSourceEffect.java index 4077d6f15a1..29fcbb73595 100644 --- a/Mage/src/main/java/mage/abilities/effects/keyword/ExploreSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/keyword/ExploreSourceEffect.java @@ -1,6 +1,8 @@ package mage.abilities.effects.keyword; import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.cards.CardsImpl; @@ -19,6 +21,8 @@ import java.util.UUID; */ public class ExploreSourceEffect extends OneShotEffect { + private final DynamicValue amount; + private static final String REMINDER_TEXT = ". (Reveal the top card of your library. " + "Put that card into your hand if it's a land. Otherwise, put a +1/+1 counter on " + "this creature, then put the card back or put it into your graveyard.)"; @@ -28,13 +32,24 @@ public class ExploreSourceEffect extends OneShotEffect { } public ExploreSourceEffect(boolean showAbilityHint, String explorerText) { + this(1, showAbilityHint, explorerText); + } + + public ExploreSourceEffect(int amount, boolean showAbilityHint, String explorerText) { + this(StaticValue.get(amount), showAbilityHint, explorerText); + } + + public ExploreSourceEffect(DynamicValue amount, boolean showAbilityHint, String explorerText) { super(Outcome.Benefit); + + this.amount = amount; // triggered ability text gen will replace {this} with "it" where applicable - staticText = "{this} explores" + (showAbilityHint ? REMINDER_TEXT : ""); + staticText = explorerText + " explores" + (showAbilityHint ? REMINDER_TEXT : ""); } protected ExploreSourceEffect(final ExploreSourceEffect effect) { super(effect); + this.amount = effect.amount; } @Override @@ -44,33 +59,36 @@ public class ExploreSourceEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - return explorePermanent(game, source.getSourceId(), source); + return explorePermanent(game, source.getSourceId(), source, this.amount.calculate(game, source, this)); } - public static boolean explorePermanent(Game game, UUID permanentId, Ability source) { + public static boolean explorePermanent(Game game, UUID permanentId, Ability source, int amount) { Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanentOrLKIBattlefield(permanentId); - if (controller == null || permanent == null) { + if (controller == null || permanent == null || amount <= 0) { return false; } - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.EXPLORED, permanentId, source, permanent.getControllerId())); - Card card = controller.getLibrary().getFromTop(game); - if (card != null) { - controller.revealCards("Explored card", new CardsImpl(card), game); - if (card.isLand(game)) { - controller.moveCards(card, Zone.HAND, source, game); - } else { - addCounter(game, permanent, source); - if (controller.chooseUse(Outcome.Neutral, "Put " + card.getLogName() + " in your graveyard?", source, game)) { - controller.moveCards(card, Zone.GRAVEYARD, source, game); + + for (int i = 0; i < amount; ++i) { + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.EXPLORED, permanentId, source, permanent.getControllerId())); + Card card = controller.getLibrary().getFromTop(game); + if (card != null) { + controller.revealCards("Explored card", new CardsImpl(card), game); + if (card.isLand(game)) { + controller.moveCards(card, Zone.HAND, source, game); } else { - game.informPlayers(controller.getLogName() + " leaves " + card.getLogName() + " on top of their library."); + addCounter(game, permanent, source); + if (controller.chooseUse(Outcome.Neutral, "Put " + card.getLogName() + " in your graveyard?", source, game)) { + controller.moveCards(card, Zone.GRAVEYARD, source, game); + } else { + game.informPlayers(controller.getLogName() + " leaves " + card.getLogName() + " on top of their library."); + } } + } else { + // If no card is revealed, most likely because that player's library is empty, + // the exploring creature receives a +1/+1 counter. + addCounter(game, permanent, source); } - } else { - // If no card is revealed, most likely because that player's library is empty, - // the exploring creature receives a +1/+1 counter. - addCounter(game, permanent, source); } return true; } diff --git a/Mage/src/main/java/mage/abilities/effects/keyword/ExploreTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/keyword/ExploreTargetEffect.java index 6138a6e2c8d..d8baf9087af 100644 --- a/Mage/src/main/java/mage/abilities/effects/keyword/ExploreTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/keyword/ExploreTargetEffect.java @@ -38,7 +38,7 @@ public class ExploreTargetEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - return ExploreSourceEffect.explorePermanent(game, getTargetPointer().getFirst(game, source), source); + return ExploreSourceEffect.explorePermanent(game, getTargetPointer().getFirst(game, source), source, 1); } @Override @@ -47,7 +47,7 @@ public class ExploreTargetEffect extends OneShotEffect { return staticText; } return getTargetPointer().describeTargets(mode.getTargets(), "it") - + " explores" + (withReminderText ? REMINDER_TEXT : "") ; + + " explores" + (withReminderText ? REMINDER_TEXT : ""); } }