From d159c45ff00120849febe9e644d25bc660223532 Mon Sep 17 00:00:00 2001 From: Susucre <34709007+Susucre@users.noreply.github.com> Date: Sun, 19 Nov 2023 18:27:35 +0100 Subject: [PATCH] [LCI] Implement Brass's Tunnel Grinder // Tecutlan the Searing Rift --- .../src/mage/cards/b/BrasssTunnelGrinder.java | 97 +++++++++++++++++++ .../mage/cards/t/TecutlanTheSearingRift.java | 92 ++++++++++++++++++ .../src/mage/sets/TheLostCavernsOfIxalan.java | 2 + .../main/java/mage/counters/CounterType.java | 1 + 4 files changed, 192 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/b/BrasssTunnelGrinder.java create mode 100644 Mage.Sets/src/mage/cards/t/TecutlanTheSearingRift.java diff --git a/Mage.Sets/src/mage/cards/b/BrasssTunnelGrinder.java b/Mage.Sets/src/mage/cards/b/BrasssTunnelGrinder.java new file mode 100644 index 00000000000..30463be4cb5 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BrasssTunnelGrinder.java @@ -0,0 +1,97 @@ +package mage.cards.b; + +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.condition.common.DescendedThisTurnCondition; +import mage.abilities.condition.common.SourceHasCounterCondition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.dynamicvalue.common.DescendedThisTurnCount; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.RemoveAllCountersSourceEffect; +import mage.abilities.effects.common.TransformSourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.TransformAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SuperType; +import mage.constants.TargetController; +import mage.counters.CounterType; +import mage.game.Game; +import mage.players.Player; +import mage.watchers.common.DescendedWatcher; + +import java.util.UUID; + +/** + * @author Susucr + */ +public final class BrasssTunnelGrinder extends CardImpl { + + public BrasssTunnelGrinder(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}{R}"); + this.secondSideCardClazz = mage.cards.t.TecutlanTheSearingRift.class; + + this.supertype.add(SuperType.LEGENDARY); + + // When Brass's Tunnel-Grinder enters the battlefield, discard any number of cards, then draw that many cards plus one. + this.addAbility(new EntersBattlefieldTriggeredAbility(new BrasssTunnelGrinderEffect())); + + // At the beginning of your end step, if you descended this turn, put a bore counter on Brass's Tunnel-Grinder. Then if there are three or more bore counters on it, remove those counters and transform it. + this.addAbility(new TransformAbility()); + Ability ability = new BeginningOfEndStepTriggeredAbility( + new AddCountersSourceEffect(CounterType.BORE.createInstance()), + TargetController.YOU, DescendedThisTurnCondition.instance, false + ); + + ConditionalOneShotEffect secondCheck = new ConditionalOneShotEffect( + new RemoveAllCountersSourceEffect(CounterType.BORE), + new SourceHasCounterCondition(CounterType.BORE, 3, Integer.MAX_VALUE), + "Then if there are three or more bore counters on it, remove those counters and transform it" + ); + secondCheck.addEffect(new TransformSourceEffect()); + ability.addEffect(secondCheck); + ability.addHint(DescendedThisTurnCount.getHint()); + this.addAbility(ability, new DescendedWatcher()); + } + + private BrasssTunnelGrinder(final BrasssTunnelGrinder card) { + super(card); + } + + @Override + public BrasssTunnelGrinder copy() { + return new BrasssTunnelGrinder(this); + } +} + +class BrasssTunnelGrinderEffect extends OneShotEffect { + + BrasssTunnelGrinderEffect() { + super(Outcome.DrawCard); + staticText = "discard any number of cards, then draw that many cards plus one"; + } + + private BrasssTunnelGrinderEffect(final BrasssTunnelGrinderEffect effect) { + super(effect); + } + + @Override + public BrasssTunnelGrinderEffect copy() { + return new BrasssTunnelGrinderEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + + int dicarded = player.discard(0, Integer.MAX_VALUE, false, source, game).size(); + player.drawCards(1 + dicarded, source, game); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/t/TecutlanTheSearingRift.java b/Mage.Sets/src/mage/cards/t/TecutlanTheSearingRift.java new file mode 100644 index 00000000000..f9874232e46 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TecutlanTheSearingRift.java @@ -0,0 +1,92 @@ +package mage.cards.t; + +import mage.abilities.Ability; +import mage.abilities.common.CastSpellPaidBySourceTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.keyword.DiscoverEffect; +import mage.abilities.mana.RedManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterSpell; +import mage.filter.predicate.mageobject.PermanentPredicate; +import mage.game.Game; +import mage.game.stack.Spell; +import mage.players.Player; + +import java.util.UUID; + +/** + * @author Susucr + */ +public final class TecutlanTheSearingRift extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("a permanent spell"); + + static { + filter.add(PermanentPredicate.instance); + } + + public TecutlanTheSearingRift(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.CAVE); + + // (Transforms from Brass's Tunnel-Grinder.) + this.nightCard = true; + + // {T}: Add {R}. + this.addAbility(new RedManaAbility()); + + // Whenever you cast a permanent spell using mana produced by Tecutlan, the Searing Rift, discover X, where X is that spell's mana value. + this.addAbility(new CastSpellPaidBySourceTriggeredAbility( + new TecutlanTheSearingRiftEffect(), + filter, true + )); + } + + private TecutlanTheSearingRift(final TecutlanTheSearingRift card) { + super(card); + } + + @Override + public TecutlanTheSearingRift copy() { + return new TecutlanTheSearingRift(this); + } +} + +class TecutlanTheSearingRiftEffect extends OneShotEffect { + + TecutlanTheSearingRiftEffect() { + super(Outcome.Benefit); + staticText = "discover X, where X is that spell's mana value"; + } + + private TecutlanTheSearingRiftEffect(final TecutlanTheSearingRiftEffect effect) { + super(effect); + } + + @Override + public TecutlanTheSearingRiftEffect copy() { + return new TecutlanTheSearingRiftEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + + Spell spell = game.getSpellOrLKIStack(getTargetPointer().getFirst(game, source)); + int mv = spell == null ? 0 : Math.max(0, spell.getManaValue()); + + DiscoverEffect.doDiscover(controller, mv, game, source); + return true; + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java b/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java index bbcf61d6fde..ea734550b29 100644 --- a/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java +++ b/Mage.Sets/src/mage/sets/TheLostCavernsOfIxalan.java @@ -68,6 +68,7 @@ public final class TheLostCavernsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Brackish Blunder", 46, Rarity.COMMON, mage.cards.b.BrackishBlunder.class)); cards.add(new SetCardInfo("Braided Net", 47, Rarity.RARE, mage.cards.b.BraidedNet.class)); cards.add(new SetCardInfo("Braided Quipu", 47, Rarity.RARE, mage.cards.b.BraidedQuipu.class)); + cards.add(new SetCardInfo("Brass's Tunnel-Grinder", 135, Rarity.RARE, mage.cards.b.BrasssTunnelGrinder.class)); cards.add(new SetCardInfo("Brazen Blademaster", 136, Rarity.COMMON, mage.cards.b.BrazenBlademaster.class)); cards.add(new SetCardInfo("Breeches, Eager Pillager", 137, Rarity.RARE, mage.cards.b.BreechesEagerPillager.class)); cards.add(new SetCardInfo("Bringer of the Last Gift", 94, Rarity.RARE, mage.cards.b.BringerOfTheLastGift.class)); @@ -311,6 +312,7 @@ public final class TheLostCavernsOfIxalan extends ExpansionSet { cards.add(new SetCardInfo("Synapse Necromage", 125, Rarity.UNCOMMON, mage.cards.s.SynapseNecromage.class)); cards.add(new SetCardInfo("Tarrian's Soulcleaver", 264, Rarity.RARE, mage.cards.t.TarriansSoulcleaver.class)); cards.add(new SetCardInfo("Tectonic Hazard", 169, Rarity.COMMON, mage.cards.t.TectonicHazard.class)); + cards.add(new SetCardInfo("Tecutlan, the Searing Rift", 135, Rarity.RARE, mage.cards.t.TecutlanTheSearingRift.class)); cards.add(new SetCardInfo("Temple of Civilization", 26, Rarity.MYTHIC, mage.cards.t.TempleOfCivilization.class)); cards.add(new SetCardInfo("Temple of Cultivation", 204, Rarity.MYTHIC, mage.cards.t.TempleOfCultivation.class)); cards.add(new SetCardInfo("Temple of Cyclical Time", 67, Rarity.MYTHIC, mage.cards.t.TempleOfCyclicalTime.class)); diff --git a/Mage/src/main/java/mage/counters/CounterType.java b/Mage/src/main/java/mage/counters/CounterType.java index 12ffa77128c..b96ae1e0c2b 100644 --- a/Mage/src/main/java/mage/counters/CounterType.java +++ b/Mage/src/main/java/mage/counters/CounterType.java @@ -27,6 +27,7 @@ public enum CounterType { BLOOD("blood"), BLOODLINE("bloodline"), BOOK("book"), + BORE("bore"), BOUNTY("bounty"), BRIBERY("bribery"), BRICK("brick"),