forked from External/mage
[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:
parent
5043430481
commit
32042687fb
22 changed files with 284 additions and 64 deletions
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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}"));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
176
Mage.Sets/src/mage/cards/e/ElugeTheShorelessSea.java
Normal file
176
Mage.Sets/src/mage/cards/e/ElugeTheShorelessSea.java
Normal 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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}"));
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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}")));
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue