diff --git a/Mage.Sets/src/mage/cards/a/AcolyteOfBahamut.java b/Mage.Sets/src/mage/cards/a/AcolyteOfBahamut.java index 4565b1ffc0f..2dbae2bc4c9 100644 --- a/Mage.Sets/src/mage/cards/a/AcolyteOfBahamut.java +++ b/Mage.Sets/src/mage/cards/a/AcolyteOfBahamut.java @@ -25,7 +25,7 @@ import java.util.UUID; */ public final class AcolyteOfBahamut extends CardImpl { - private static final FilterCard filter = new FilterCard(); + private static final FilterCard filter = new FilterCard("the first Dragon spell you cast each turn"); static { filter.add(SubType.DRAGON.getPredicate()); @@ -40,10 +40,9 @@ public final class AcolyteOfBahamut extends CardImpl { // Commander creatures you own have "The first Dragon spell you cast each turn costs {2} less to cast." this.addAbility(new SimpleStaticAbility(new GainAbilityAllEffect( - new SimpleStaticAbility( - new SpellsCostReductionControllerEffect(filter, 2) - .setText("the first Dragon spell you cast each turn costs {2} less to cast") - ), Duration.WhileOnBattlefield, StaticFilters.FILTER_CREATURES_OWNED_COMMANDER + new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 2)), + Duration.WhileOnBattlefield, + StaticFilters.FILTER_CREATURES_OWNED_COMMANDER ).withForceQuotes()), new AcolyteOfBahamutWatcher()); } diff --git a/Mage.Sets/src/mage/cards/a/ArtificerClass.java b/Mage.Sets/src/mage/cards/a/ArtificerClass.java index 6295c31b0e3..d0f983b67fd 100644 --- a/Mage.Sets/src/mage/cards/a/ArtificerClass.java +++ b/Mage.Sets/src/mage/cards/a/ArtificerClass.java @@ -34,7 +34,7 @@ import java.util.UUID; */ public final class ArtificerClass extends CardImpl { - private static final FilterCard filter = new FilterArtifactCard(); + private static final FilterCard filter = new FilterArtifactCard("the first artifact spell you cast each turn"); static { filter.add(ArtificerClassPredicate.instance); @@ -49,10 +49,10 @@ public final class ArtificerClass extends CardImpl { this.addAbility(new ClassReminderAbility()); // The first artifact spell you cast each turn costs {1} less to cast. - this.addAbility(new SimpleStaticAbility( - new SpellsCostReductionControllerEffect(filter, 1) - .setText("the first artifact spell you cast each turn costs {1} less to cast") - ), new ArtificerClassWatcher()); + this.addAbility( + new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1)), + new ArtificerClassWatcher() + ); // {1}{U}: Level 2 this.addAbility(new ClassLevelAbility(2, "{1}{U}")); diff --git a/Mage.Sets/src/mage/cards/b/BalladOfTheBlackFlag.java b/Mage.Sets/src/mage/cards/b/BalladOfTheBlackFlag.java index 2c4ac2bcee3..d69b79191a1 100644 --- a/Mage.Sets/src/mage/cards/b/BalladOfTheBlackFlag.java +++ b/Mage.Sets/src/mage/cards/b/BalladOfTheBlackFlag.java @@ -18,7 +18,7 @@ import java.util.UUID; */ public final class BalladOfTheBlackFlag extends CardImpl { - private static final FilterCard filter = new FilterHistoricCard(); + private static final FilterCard filter = new FilterHistoricCard("historic spells you cast this turn"); public BalladOfTheBlackFlag(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}{U}"); @@ -38,7 +38,6 @@ public final class BalladOfTheBlackFlag extends CardImpl { sagaAbility.addChapterEffect( this, SagaChapter.CHAPTER_IV, new SpellsCostReductionControllerEffect(filter, 2) - .setText("historic spells you cast this turn cost {2} less to cast") ); this.addAbility(sagaAbility); diff --git a/Mage.Sets/src/mage/cards/c/ConduitOfRuin.java b/Mage.Sets/src/mage/cards/c/ConduitOfRuin.java index 34d54983a0a..7e8ce759195 100644 --- a/Mage.Sets/src/mage/cards/c/ConduitOfRuin.java +++ b/Mage.Sets/src/mage/cards/c/ConduitOfRuin.java @@ -36,7 +36,7 @@ import mage.watchers.Watcher; public final class ConduitOfRuin extends CardImpl { private static final FilterCreatureCard filter = new FilterCreatureCard("a colorless creature card with mana value 7 or greater"); - private static final FilterCreatureCard filterCost = new FilterCreatureCard("The first creature spell"); + private static final FilterCreatureCard filterCost = new FilterCreatureCard("the first creature spell you cast each turn"); static { filter.add(ColorlessPredicate.instance); @@ -56,7 +56,6 @@ public final class ConduitOfRuin extends CardImpl { // The first creature spell you cast each turn costs {2} less to cast. Effect effect = new SpellsCostReductionControllerEffect(filterCost, 2); - effect.setText("The first creature spell you cast each turn costs {2} less to cast."); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect), new ConduitOfRuinWatcher()); } diff --git a/Mage.Sets/src/mage/cards/c/CunningNightbonder.java b/Mage.Sets/src/mage/cards/c/CunningNightbonder.java index ce35b6af8fd..6b7e8f9a46b 100644 --- a/Mage.Sets/src/mage/cards/c/CunningNightbonder.java +++ b/Mage.Sets/src/mage/cards/c/CunningNightbonder.java @@ -23,7 +23,7 @@ import java.util.UUID; */ public final class CunningNightbonder extends CardImpl { - private static final FilterCard filter = new FilterCard(); + private static final FilterCard filter = new FilterCard("spells with flash"); private static final FilterSpell filter2 = new FilterSpell(); private static final Predicate predicate = new AbilityPredicate(FlashAbility.class); @@ -44,8 +44,7 @@ public final class CunningNightbonder extends CardImpl { this.addAbility(FlashAbility.getInstance()); // Spells you cast with flash cost {1} less to cast and can't be countered. - Ability ability = new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1) - .setText("spells with flash you cast cost {1} less to cast")); + Ability ability = new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1)); ability.addEffect(new CantBeCounteredControlledEffect(filter2, Duration.WhileOnBattlefield) .setText("and can't be countered")); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/e/ElugeTheShorelessSea.java b/Mage.Sets/src/mage/cards/e/ElugeTheShorelessSea.java new file mode 100644 index 00000000000..977ffa25e05 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/ElugeTheShorelessSea.java @@ -0,0 +1,176 @@ +package mage.cards.e; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BecomesBasicLandTargetEffect; +import mage.abilities.effects.common.continuous.SetBasePowerToughnessSourceEffect; +import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.cards.Card; +import mage.constants.*; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.counters.CounterType; +import mage.filter.FilterCard; +import mage.filter.common.FilterControlledLandPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.common.FilterInstantOrSorceryCard; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.game.Controllable; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.stack.Spell; +import mage.target.common.TargetLandPermanent; +import mage.util.CardUtil; +import mage.watchers.Watcher; + +/** + * + * @author jimga150 + */ +public final class ElugeTheShorelessSea extends CardImpl { + + private static final FilterControlledPermanent islandFilter = new FilterControlledPermanent("Islands you control"); + private static final FilterCard spellFilter = new FilterInstantOrSorceryCard("the first instant or sorcery spell you cast each turn"); + private static final FilterControlledLandPermanent floodLandFilter = new FilterControlledLandPermanent("land you control with a flood counter on it."); + + static { + islandFilter.add(SubType.ISLAND.getPredicate()); + } + + static { + spellFilter.add(ElugeTheShorelessSeaPredicate.instance); + } + + static { + floodLandFilter.add(CounterType.FLOOD.getPredicate()); + } + + public ElugeTheShorelessSea(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{U}{U}"); + + this.supertype.add(SuperType.LEGENDARY); + this.subtype.add(SubType.ELEMENTAL); + this.subtype.add(SubType.FISH); + this.power = new MageInt(0); + this.toughness = new MageInt(0); + + // Eluge's power and toughness are each equal to the number of Islands you control. + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetBasePowerToughnessSourceEffect(new PermanentsOnBattlefieldCount(islandFilter)))); + + // Whenever Eluge enters or attacks, put a flood counter on target land. It's an Island in addition to its other + // types for as long as it has a flood counter on it. + // Based on Xolatoyac, the Smiling Flood + Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility(new AddCountersTargetEffect(CounterType.FLOOD.createInstance())); + ability.addEffect(new ElugeTheShorelessSeaEffect()); + ability.addTarget(new TargetLandPermanent()); + this.addAbility(ability); + + // The first instant or sorcery spell you cast each turn costs {U} (or {1}) less to cast for each land you + // control with a flood counter on it. + Effect effect = new SpellsCostReductionControllerEffect(spellFilter, new ManaCostsImpl<>("{U}"), new PermanentsOnBattlefieldCount(floodLandFilter), true); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect), + new ElugeTheShorelessSeaWatcher()); + } + + private ElugeTheShorelessSea(final ElugeTheShorelessSea card) { + super(card); + } + + @Override + public ElugeTheShorelessSea copy() { + return new ElugeTheShorelessSea(this); + } +} + +enum ElugeTheShorelessSeaPredicate implements ObjectSourcePlayerPredicate { + instance; + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + if (input.getObject() instanceof Card && + ((Card) input.getObject()).isInstantOrSorcery(game)) { + ElugeTheShorelessSeaWatcher watcher = game.getState().getWatcher(ElugeTheShorelessSeaWatcher.class); + return watcher != null && + watcher.getInstantOrSorcerySpellsCastThisTurn(input.getPlayerId()) == 0; + } + return false; + } + + @Override + public String toString() { + return "The first instant or sorcery spell you cast each turn"; + } +} + +// Based on XolatoyacTheSmilingFloodEffect +class ElugeTheShorelessSeaEffect extends BecomesBasicLandTargetEffect { + + ElugeTheShorelessSeaEffect() { + super(Duration.Custom, false, false, SubType.ISLAND); + staticText = "It's an land is an Island in addition to its other types for as long as it has a flood counter on it"; + } + + private ElugeTheShorelessSeaEffect(final ElugeTheShorelessSeaEffect effect) { + super(effect); + } + + @Override + public ElugeTheShorelessSeaEffect copy() { + return new ElugeTheShorelessSeaEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent land = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + if (land == null || land.getCounters(game).getCount(CounterType.FLOOD) < 1) { + discard(); + return false; + } + return super.apply(game, source); + } +} + +// Based on MelekReforgedResearcherWatcher +class ElugeTheShorelessSeaWatcher extends Watcher { + + private final Map playerInstantOrSorcerySpells = new HashMap<>(); + + ElugeTheShorelessSeaWatcher() { + super(WatcherScope.GAME); + } + + @Override + public void watch (GameEvent event, Game game) { + if (event.getType() != GameEvent.EventType.SPELL_CAST) { + return; + } + + Spell spell = game.getSpell(event.getTargetId()); + if (spell == null || !spell.isInstantOrSorcery(game)) { + return; + } + playerInstantOrSorcerySpells.put(event.getPlayerId(), + getInstantOrSorcerySpellsCastThisTurn(event.getPlayerId()) + 1); + } + + @Override + public void reset() { + playerInstantOrSorcerySpells.clear(); + super.reset(); + } + + public int getInstantOrSorcerySpellsCastThisTurn(UUID playerId) { + return playerInstantOrSorcerySpells.getOrDefault(playerId, 0); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/g/GoblinAnarchomancer.java b/Mage.Sets/src/mage/cards/g/GoblinAnarchomancer.java index 9786d11815d..8a83f3a6a77 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinAnarchomancer.java +++ b/Mage.Sets/src/mage/cards/g/GoblinAnarchomancer.java @@ -19,7 +19,7 @@ import java.util.UUID; */ public final class GoblinAnarchomancer extends CardImpl { - private static final FilterCard filter = new FilterCard(); + private static final FilterCard filter = new FilterCard("each spell you cast that's red or green"); static { filter.add(Predicates.or( @@ -37,8 +37,7 @@ public final class GoblinAnarchomancer extends CardImpl { this.toughness = new MageInt(2); // Each spell you cast that's red or green costs {1} less to cast. - this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1) - .setText("each spell you cast that's red or green costs {1} less to cast"))); + this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1))); } private GoblinAnarchomancer(final GoblinAnarchomancer card) { diff --git a/Mage.Sets/src/mage/cards/g/GoreclawTerrorOfQalSisma.java b/Mage.Sets/src/mage/cards/g/GoreclawTerrorOfQalSisma.java index a51016bd73c..586d0ab7683 100644 --- a/Mage.Sets/src/mage/cards/g/GoreclawTerrorOfQalSisma.java +++ b/Mage.Sets/src/mage/cards/g/GoreclawTerrorOfQalSisma.java @@ -28,7 +28,7 @@ import mage.filter.predicate.mageobject.PowerPredicate; */ public final class GoreclawTerrorOfQalSisma extends CardImpl { - private static final FilterCard filter = new FilterCreatureCard(); + private static final FilterCard filter = new FilterCreatureCard("Creature spells you cast with power 4 or greater"); private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent(); static { @@ -48,7 +48,6 @@ public final class GoreclawTerrorOfQalSisma extends CardImpl { this.addAbility(new SimpleStaticAbility( Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(filter, 2) - .setText("Creature spells you cast with power 4 or greater cost {2} less to cast") )); // Whenever Goreclaw, Terror of Qal Sisma attacks, each creature you control with power 4 or greater gets +1/+1 and gains trample until end of turn. diff --git a/Mage.Sets/src/mage/cards/k/KrosanDrover.java b/Mage.Sets/src/mage/cards/k/KrosanDrover.java index f92153a8238..b6d3819f0c0 100644 --- a/Mage.Sets/src/mage/cards/k/KrosanDrover.java +++ b/Mage.Sets/src/mage/cards/k/KrosanDrover.java @@ -21,7 +21,7 @@ import mage.filter.predicate.mageobject.ManaValuePredicate; */ public final class KrosanDrover extends CardImpl { - private static final FilterCard filter = new FilterCard("Creature spells with mana value 6 or greater"); + private static final FilterCard filter = new FilterCard("Creature spells you cast with mana value 6 or greater"); static { filter.add(CardType.CREATURE.getPredicate()); @@ -36,7 +36,6 @@ public final class KrosanDrover extends CardImpl { // Creature spells you cast with converted mana cost 6 or greater cost {2} less to cast. Effect effect = new SpellsCostReductionControllerEffect(filter, 2); - effect.setText("Creature spells you cast with mana value 6 or greater cost {2} less to cast."); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); } diff --git a/Mage.Sets/src/mage/cards/m/MelekReforgedResearcher.java b/Mage.Sets/src/mage/cards/m/MelekReforgedResearcher.java index 096a59ff44f..6dc069b4072 100644 --- a/Mage.Sets/src/mage/cards/m/MelekReforgedResearcher.java +++ b/Mage.Sets/src/mage/cards/m/MelekReforgedResearcher.java @@ -34,7 +34,7 @@ import mage.watchers.Watcher; */ public final class MelekReforgedResearcher extends CardImpl { - private static final FilterCard filter = new FilterInstantOrSorceryCard("the first instant or sorcery spell"); + private static final FilterCard filter = new FilterInstantOrSorceryCard("The first instant or sorcery spell you cast each turn"); static { filter.add(MelekReforgedResearcherPredicate.instance); @@ -57,7 +57,6 @@ public final class MelekReforgedResearcher extends CardImpl { // The first instant or sorcery spell you cast each turn costs {3} less to cast. Effect effect = new SpellsCostReductionControllerEffect(filter, 3); - effect.setText("The first instant or sorcery spell you cast each turn costs {3} less to cast"); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect), new MelekReforgedResearcherWatcher()); } diff --git a/Mage.Sets/src/mage/cards/m/MistformWarchief.java b/Mage.Sets/src/mage/cards/m/MistformWarchief.java index 6a5fc06e793..cc44cbb14e5 100644 --- a/Mage.Sets/src/mage/cards/m/MistformWarchief.java +++ b/Mage.Sets/src/mage/cards/m/MistformWarchief.java @@ -25,7 +25,7 @@ import java.util.UUID; */ public final class MistformWarchief extends CardImpl { - private static final FilterCard filter = new FilterCard(); + private static final FilterCard filter = new FilterCard("Creature spells you cast that share a creature type with {this}"); static { filter.add(new MistformWarchiefPredicate()); @@ -41,7 +41,6 @@ public final class MistformWarchief extends CardImpl { // Creature spells you cast that share a creature type with Mistform Warchief cost {1} less to cast. this.addAbility(new SimpleStaticAbility( new SpellsCostReductionControllerEffect(filter, 1) - .setText("Creature spells you cast that share a creature type with {this} cost {1} less to cast") )); // {tap}: Mistform Warchief becomes the creature type of your choice until end of turn. diff --git a/Mage.Sets/src/mage/cards/s/SageOfTheBeyond.java b/Mage.Sets/src/mage/cards/s/SageOfTheBeyond.java index a30c497f268..ae7feb6269a 100644 --- a/Mage.Sets/src/mage/cards/s/SageOfTheBeyond.java +++ b/Mage.Sets/src/mage/cards/s/SageOfTheBeyond.java @@ -19,7 +19,7 @@ import java.util.UUID; */ public final class SageOfTheBeyond extends CardImpl { - private static final FilterCard filter = new FilterCard(); + private static final FilterCard filter = new FilterCard("Spells you cast from anywhere other than your hand"); static { filter.add(SpellCastFromAnywhereOtherThanHand.instance); @@ -37,8 +37,7 @@ public final class SageOfTheBeyond extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Spells you cast from anywhere other than your hand cost {2} less to cast. - this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 2) - .setText("Spells you cast from anywhere other than your hand cost {2} less to cast."))); + this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 2))); // Foretell {4}{U} this.addAbility(new ForetellAbility(this, "{4}{U}")); diff --git a/Mage.Sets/src/mage/cards/s/SavvyTrader.java b/Mage.Sets/src/mage/cards/s/SavvyTrader.java index 49a7ef374c6..e96c5421a59 100644 --- a/Mage.Sets/src/mage/cards/s/SavvyTrader.java +++ b/Mage.Sets/src/mage/cards/s/SavvyTrader.java @@ -32,7 +32,7 @@ import java.util.UUID; */ public final class SavvyTrader extends CardImpl { - private static final FilterCard filter = new FilterCard(); + private static final FilterCard filter = new FilterCard("Spells you cast from anywhere other than your hand"); static { filter.add(SpellCastFromAnywhereOtherThanHand.instance); @@ -52,8 +52,7 @@ public final class SavvyTrader extends CardImpl { this.addAbility(ability); // Spells you cast from anywhere other than your hand cost {1} less to cast. - this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1) - .setText("Spells you cast from anywhere other than your hand cost {1} less to cast."))); + this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1))); } private SavvyTrader(final SavvyTrader card) { diff --git a/Mage.Sets/src/mage/cards/s/ShadowInTheWarp.java b/Mage.Sets/src/mage/cards/s/ShadowInTheWarp.java index a26ce1aacdb..f237f78721f 100644 --- a/Mage.Sets/src/mage/cards/s/ShadowInTheWarp.java +++ b/Mage.Sets/src/mage/cards/s/ShadowInTheWarp.java @@ -31,7 +31,7 @@ import java.util.UUID; */ public final class ShadowInTheWarp extends CardImpl { - private static final FilterCreatureCard filterCost = new FilterCreatureCard("The first creature spell"); + private static final FilterCreatureCard filterCost = new FilterCreatureCard("The first creature spell you cast each turn"); static { filterCost.add(new FirstCastCreatureSpellPredicate()); @@ -42,7 +42,6 @@ public final class ShadowInTheWarp extends CardImpl { // The first creature spell you cast each turn costs {2} less to cast. Effect effect = new SpellsCostReductionControllerEffect(filterCost, 2); - effect.setText("The first creature spell you cast each turn costs {2} less to cast."); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect), new ShadowInTheWarpWatcher()); // Whenever an opponent casts their first noncreature spell each turn, Shadow in the Warp deals 2 damage to that player. diff --git a/Mage.Sets/src/mage/cards/s/SpectacleMage.java b/Mage.Sets/src/mage/cards/s/SpectacleMage.java index debd1d8371d..b93b389533e 100644 --- a/Mage.Sets/src/mage/cards/s/SpectacleMage.java +++ b/Mage.Sets/src/mage/cards/s/SpectacleMage.java @@ -20,7 +20,7 @@ import java.util.UUID; */ public final class SpectacleMage extends CardImpl { - private static final FilterCard filter = new FilterInstantOrSorceryCard(); + private static final FilterCard filter = new FilterInstantOrSorceryCard("instant and sorcery spells you cast with mana value 5 or greater"); static { filter.add(new ManaValuePredicate(ComparisonType.MORE_THAN, 4)); @@ -38,8 +38,7 @@ public final class SpectacleMage extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Instant and sorcery spells you cast with mana value 5 or greater cost {1} less to cast. - this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1) - .setText("instant and sorcery spells you cast with mana value 5 or greater cost {1} less to cast"))); + this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1))); } private SpectacleMage(final SpectacleMage card) { diff --git a/Mage.Sets/src/mage/cards/s/SpellbindingSoprano.java b/Mage.Sets/src/mage/cards/s/SpellbindingSoprano.java index 27fb4bbab25..eeb463455fa 100644 --- a/Mage.Sets/src/mage/cards/s/SpellbindingSoprano.java +++ b/Mage.Sets/src/mage/cards/s/SpellbindingSoprano.java @@ -20,7 +20,7 @@ import java.util.UUID; */ public final class SpellbindingSoprano extends CardImpl { - private static final FilterCard filter = new FilterCard("instant and sorcery spells"); + private static final FilterCard filter = new FilterCard("instant and sorcery spells you cast this turn"); static { filter.add(Predicates.or( @@ -38,8 +38,7 @@ public final class SpellbindingSoprano extends CardImpl { this.toughness = new MageInt(2); // Whenever Spellbinding Soprano attacks, instant and sorcery spells you cast this turn cost {1} less to cast. - this.addAbility(new AttacksTriggeredAbility(new SpellsCostReductionControllerEffect(filter, 1).setDuration(Duration.EndOfTurn) - .setText("instant and sorcery spells you cast this turn cost {1} less to cast"))); + this.addAbility(new AttacksTriggeredAbility(new SpellsCostReductionControllerEffect(filter, 1).setDuration(Duration.EndOfTurn))); // Encore {3}{R} this.addAbility(new EncoreAbility(new ManaCostsImpl<>("{3}{R}"))); diff --git a/Mage.Sets/src/mage/cards/t/ThryxTheSuddenStorm.java b/Mage.Sets/src/mage/cards/t/ThryxTheSuddenStorm.java index 94bca9e1783..d93b05c56a2 100644 --- a/Mage.Sets/src/mage/cards/t/ThryxTheSuddenStorm.java +++ b/Mage.Sets/src/mage/cards/t/ThryxTheSuddenStorm.java @@ -21,7 +21,7 @@ import mage.filter.predicate.mageobject.ManaValuePredicate; */ public final class ThryxTheSuddenStorm extends CardImpl { - private static final FilterCard filter = new FilterCard(); + private static final FilterCard filter = new FilterCard("spells you cast with mana value 5 or greater"); private static final FilterSpell filter2 = new FilterSpell(); static { @@ -46,8 +46,7 @@ public final class ThryxTheSuddenStorm extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Spells you cast with converted mana cost 5 or greater cost {1} less to cast and can't be countered. - Ability ability = new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1) - .setText("spells you cast with mana value 5 or greater cost {1} less to cast")); + Ability ability = new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1)); ability.addEffect(new CantBeCounteredControlledEffect( filter2, null, Duration.WhileOnBattlefield ).setText("and can't be countered")); diff --git a/Mage.Sets/src/mage/cards/u/UginTheIneffable.java b/Mage.Sets/src/mage/cards/u/UginTheIneffable.java index 8e74e9d19cf..e9f702d82d0 100644 --- a/Mage.Sets/src/mage/cards/u/UginTheIneffable.java +++ b/Mage.Sets/src/mage/cards/u/UginTheIneffable.java @@ -41,7 +41,7 @@ import java.util.UUID; */ public final class UginTheIneffable extends CardImpl { - private static final FilterCard filter = new FilterCard(); + private static final FilterCard filter = new FilterCard("Colorless spells you cast"); private static final FilterPermanent filter2 = new FilterPermanent("permanent that's one or more colors"); static { @@ -57,9 +57,7 @@ public final class UginTheIneffable extends CardImpl { this.setStartingLoyalty(4); // Colorless spells you cast cost {2} less to cast. - this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect( - filter, 2 - ).setText("Colorless spells you cast cost {2} less to cast."))); + this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 2))); // +1: Exile the top card of your library face down and look at it. Create a 2/2 colorless Spirit creature token. When that token leaves the battlefield, put the exiled card into your hand. this.addAbility(new LoyaltyAbility(new UginTheIneffableEffect(), 1)); diff --git a/Mage.Sets/src/mage/cards/u/UrzaPlaneswalker.java b/Mage.Sets/src/mage/cards/u/UrzaPlaneswalker.java index eb71af52fd7..7bb8a3753be 100644 --- a/Mage.Sets/src/mage/cards/u/UrzaPlaneswalker.java +++ b/Mage.Sets/src/mage/cards/u/UrzaPlaneswalker.java @@ -28,7 +28,7 @@ import java.util.UUID; */ public final class UrzaPlaneswalker extends MeldCard { - private static final FilterCard filter = new FilterCard("artifact, instant, and sorcery spells"); + private static final FilterCard filter = new FilterCard("Artifact, instant, and sorcery spells you cast this turn"); private static final FilterPermanent filter2 = new FilterPermanent("artifacts and planeswalkers"); static { @@ -58,9 +58,8 @@ public final class UrzaPlaneswalker extends MeldCard { this.addAbility(new SimpleStaticAbility(new UrzaPlaneswalkerEffect())); // +2: Artifact, instant, and sorcery spells you cast this turn cost {2} less to cast. You gain 2 life. - Ability ability = new LoyaltyAbility(new SpellsCostReductionControllerEffect(filter, 2) - .setDuration(Duration.EndOfTurn) - .setText("artifact, instant, and sorcery spells you cast this turn cost {2} less to cast"), 2); + Ability ability = new LoyaltyAbility( + new SpellsCostReductionControllerEffect(filter, 2).setDuration(Duration.EndOfTurn), 2); ability.addEffect(new GainLifeEffect(2)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/v/VineGecko.java b/Mage.Sets/src/mage/cards/v/VineGecko.java index e4ebe9681ab..25b2d398340 100644 --- a/Mage.Sets/src/mage/cards/v/VineGecko.java +++ b/Mage.Sets/src/mage/cards/v/VineGecko.java @@ -32,7 +32,7 @@ import java.util.UUID; */ public final class VineGecko extends CardImpl { - private static final FilterCard filter = new FilterCard(); + private static final FilterCard filter = new FilterCard("The first kicked spell you cast each turn"); static { filter.add(VineGeckoPredicate.instance); @@ -47,8 +47,10 @@ public final class VineGecko extends CardImpl { this.toughness = new MageInt(2); // The first kicked spell you cast each turn costs {1} less to cast. - this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1) - .setText("the first kicked spell you cast each turn costs {1} less to cast")), new VineGeckoWatcher()); + this.addAbility(new SimpleStaticAbility( + new SpellsCostReductionControllerEffect(filter, 1)), + new VineGeckoWatcher() + ); // Whenever you cast a kicked spell, put a +1/+1 counter on Vine Gecko. this.addAbility(new SpellCastControllerTriggeredAbility( diff --git a/Mage.Sets/src/mage/sets/Bloomburrow.java b/Mage.Sets/src/mage/sets/Bloomburrow.java index cdc534e4dce..e689a327ca0 100644 --- a/Mage.Sets/src/mage/sets/Bloomburrow.java +++ b/Mage.Sets/src/mage/sets/Bloomburrow.java @@ -77,6 +77,7 @@ public final class Bloomburrow extends ExpansionSet { cards.add(new SetCardInfo("Druid of the Spade", 170, Rarity.COMMON, mage.cards.d.DruidOfTheSpade.class)); cards.add(new SetCardInfo("Early Winter", 93, Rarity.COMMON, mage.cards.e.EarlyWinter.class)); cards.add(new SetCardInfo("Eddymurk Crab", 48, Rarity.UNCOMMON, mage.cards.e.EddymurkCrab.class)); + cards.add(new SetCardInfo("Eluge, the Shoreless Sea", 49, Rarity.MYTHIC, mage.cards.e.ElugeTheShorelessSea.class)); cards.add(new SetCardInfo("Emberheart Challenger", 133, Rarity.RARE, mage.cards.e.EmberheartChallenger.class)); cards.add(new SetCardInfo("Essence Channeler", 12, Rarity.RARE, mage.cards.e.EssenceChanneler.class)); cards.add(new SetCardInfo("Fabled Passage", 252, Rarity.RARE, mage.cards.f.FabledPassage.class)); diff --git a/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostReductionControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostReductionControllerEffect.java index 317d61f6f89..bbf2d7fb93a 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostReductionControllerEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/cost/SpellsCostReductionControllerEffect.java @@ -6,6 +6,7 @@ import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCosts; +import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.StaticValue; import mage.cards.Card; @@ -28,19 +29,40 @@ import java.util.Set; */ public class SpellsCostReductionControllerEffect extends CostModificationEffectImpl { + // Which spells to apply cost reduction to private final FilterCard filter; + + // Number of times to apply cost reduction + // When just reducing colorless mana, (constructors without a ManaCosts argument) + // this is the amount of colorless mana to reduce by private final DynamicValue amount; + + // adds "up to" sliding scale for mana reduction (only available for generic mana cost reduction) private final boolean upTo; + private ManaCosts manaCostsToReduce = null; + // true when colored mana can also reduce generic mana if no more mana of that color remains in the cost + // See CardUtil.adjustCost + private final boolean convertToGeneric; + public SpellsCostReductionControllerEffect(FilterCard filter, ManaCosts manaCostsToReduce) { + this(filter, manaCostsToReduce, StaticValue.get(1)); + } + + public SpellsCostReductionControllerEffect(FilterCard filter, ManaCosts manaCostsToReduce, DynamicValue amount) { + this(filter, manaCostsToReduce, amount, false); + } + + public SpellsCostReductionControllerEffect(FilterCard filter, ManaCosts manaCostsToReduce, DynamicValue amount, boolean convertToGeneric) { super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST); this.filter = filter; - this.amount = StaticValue.get(0); + this.amount = amount; this.manaCostsToReduce = manaCostsToReduce; this.upTo = false; - this.staticText = filter.getMessage() + " you cast cost " + manaCostsToReduce.getText() + - " less to cast. This effect reduces only the amount of colored mana you pay."; + this.convertToGeneric = convertToGeneric; + + createStaticText(); } public SpellsCostReductionControllerEffect(FilterCard filter, int amount) { @@ -60,9 +82,9 @@ public class SpellsCostReductionControllerEffect extends CostModificationEffectI this.filter = filter; this.amount = amount; this.upTo = upTo; - this.staticText = (filter.getMessage().contains("you cast") ? filter.getMessage() - : filter.getMessage() + " you cast") - + " cost " + (upTo ? "up to " : "") + '{' + amount + "} less to cast"; + this.convertToGeneric = false; + + createStaticText(); } protected SpellsCostReductionControllerEffect(final SpellsCostReductionControllerEffect effect) { @@ -71,14 +93,20 @@ public class SpellsCostReductionControllerEffect extends CostModificationEffectI this.amount = effect.amount; this.manaCostsToReduce = effect.manaCostsToReduce; this.upTo = effect.upTo; + this.convertToGeneric = effect.convertToGeneric; + this.staticText = effect.staticText; } @Override public boolean apply(Game game, Ability source, Ability abilityToModify) { + int reductionAmount = this.amount.calculate(game, source, this); if (manaCostsToReduce != null) { - CardUtil.adjustCost((SpellAbility) abilityToModify, manaCostsToReduce, false); + ManaCosts calculatedManaCostsToReduce = new ManaCostsImpl<>();; + for (int i = 0; i < reductionAmount; i++) { + calculatedManaCostsToReduce.add(this.manaCostsToReduce.copy()); + } + CardUtil.adjustCost(abilityToModify, calculatedManaCostsToReduce, convertToGeneric); } else { - int reductionAmount = this.amount.calculate(game, source, this); if (upTo) { Mana mana = abilityToModify.getManaCostsToPay().getMana(); int reduceMax = mana.getGeneric(); @@ -131,6 +159,37 @@ public class SpellsCostReductionControllerEffect extends CostModificationEffectI return false; } + private void createStaticText(){ + StringBuilder sb = new StringBuilder(filter.getMessage()); + if (!sb.toString().contains("you cast")){ + sb.append(" you cast"); + } + if (sb.toString().toLowerCase().contains("spells")){ + sb.append(" cost "); + } else { + sb.append(" costs "); + } + if (upTo){ + sb.append("up to "); + } + if (manaCostsToReduce != null) { + sb.append(manaCostsToReduce.getText()); + if (convertToGeneric){ + sb.append(" (or {1})"); + } + } else { + sb.append("{").append(amount).append("}"); + } + sb.append(" less to cast"); + if (!(amount instanceof StaticValue)){ + sb.append(" for each ").append(amount.getMessage()); + } + if (!convertToGeneric && manaCostsToReduce != null){ + sb.append(". This effect reduces only the amount of colored mana you pay"); + } + staticText = sb.toString(); + } + @Override public SpellsCostReductionControllerEffect copy() { return new SpellsCostReductionControllerEffect(this);