[BLB] Implement Eluge the Shoreless Sea; expand SpellsCostReductionControllerEffect (#12607)

* Implement Eluge, the Shoreless Sea (missing mana cost reduction clause)

* implement ability to convert colored to generic costs in SpellsCostReductionControllerEffect

* fix text generation on SpellsCostReductionControllerEffect

* remove unnecessary setText() calls on SpellsCostReductionControllerEffect

* make logfile from master run

* Fix plurality detection

* Eliminate unnecessary setText() calls in other cards

* Delete logfile

* remove redundant type cast

* Add parameter documentation
This commit is contained in:
jimga150 2024-07-30 00:38:21 -04:00 committed by GitHub
parent 5043430481
commit 32042687fb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 284 additions and 64 deletions

View file

@ -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());
}

View file

@ -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}"));

View file

@ -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);

View file

@ -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());
}

View file

@ -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);

View file

@ -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<Controllable> {
instance;
@Override
public boolean apply(ObjectSourcePlayer<Controllable> 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<UUID, Integer> 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);
}
}

View file

@ -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) {

View file

@ -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.

View file

@ -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));
}

View file

@ -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());
}

View file

@ -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.

View file

@ -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}"));

View file

@ -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) {

View file

@ -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.

View file

@ -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) {

View file

@ -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}")));

View file

@ -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"));

View file

@ -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));

View file

@ -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);

View file

@ -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(

View file

@ -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));

View file

@ -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<ManaCost> 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<ManaCost> 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<ManaCost> manaCostsToReduce) {
this(filter, manaCostsToReduce, StaticValue.get(1));
}
public SpellsCostReductionControllerEffect(FilterCard filter, ManaCosts<ManaCost> manaCostsToReduce, DynamicValue amount) {
this(filter, manaCostsToReduce, amount, false);
}
public SpellsCostReductionControllerEffect(FilterCard filter, ManaCosts<ManaCost> 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<ManaCost> 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(" (<i>or {1}</i>)");
}
} 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);