[ECC/ECL] Implement Mass of Mysteries, Springleaf Parade, Wickersmith's Tools. Add supporting tokens (#14173)

* [ECC] Add Mass of Mysteries

* [ECC] Add Springleaf Parade

* Add in Tokens from Lorwyn Eclipsed Commander

* [ECC] Implement Wickersmith's Tools

* Clean up Scarecrow Token
This commit is contained in:
Muz 2026-01-09 14:55:30 -06:00 committed by GitHub
parent 062de4b210
commit 23c6b42ee0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 270 additions and 0 deletions

View file

@ -2857,6 +2857,21 @@ public class ScryfallImageSupportTokens {
put("TLE/Marit Lage", "https://api.scryfall.com/cards/ttle/1/?format=image");
put("TLE/Soldier", "https://api.scryfall.com/cards/ttle/2?format=image");
// ECL
put("ECL/Shapeshifter", "https://api.scryfall.com/cards/tecl/1/?format=image");
// ECC
put("ECC/Elemental/1", "https://api.scryfall.com/cards/tecc/2?format=image");
put("ECC/Elemental/2", "https://api.scryfall.com/cards/tecc/9?format=image");
put("ECC/Elemental/3", "https://api.scryfall.com/cards/tecc/10?format=image");
put("ECC/Elf Warrior", "https://api.scryfall.com/cards/tecc/4?format=image");
put("ECC/Plant", "https://api.scryfall.com/cards/tecc/5?format=image");
put("ECC/Rhino Warrior", "https://api.scryfall.com/cards/tecc/6?format=image");
put("ECC/Saproling", "https://api.scryfall.com/cards/tecc/7?format=image");
put("ECC/Scarecrow", "https://api.scryfall.com/cards/tecc/11?format=image");
put("ECC/Snake", "https://api.scryfall.com/cards/tecc/8?format=image");
put("ECC/Zombie", "https://api.scryfall.com/cards/tecc/3?format=image");
// TMT
put("TMT/Mutagen", "https://api.scryfall.com/cards/ttmt/9?format=image");

View file

@ -0,0 +1,68 @@
package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.target.TargetPermanent;
import mage.abilities.Ability;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.abilities.keyword.MyriadAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.abilities.triggers.BeginningOfCombatTriggeredAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
/**
*
* @author muz
*/
public final class MassOfMysteries extends CardImpl {
private static final FilterPermanent filter
= new FilterControlledPermanent(SubType.ELEMENTAL, "another target Elemental you control");
static {
filter.add(AnotherPredicate.instance);
}
public MassOfMysteries(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}{U}{B}{R}{G}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.ELEMENTAL);
this.power = new MageInt(5);
this.toughness = new MageInt(5);
// First strike
this.addAbility(FirstStrikeAbility.getInstance());
// Vigilance
this.addAbility(VigilanceAbility.getInstance());
// Trample
this.addAbility(TrampleAbility.getInstance());
// At the beginning of combat on your turn, another target Elemental you control gains Myriad until end of turn.
Ability ability = new BeginningOfCombatTriggeredAbility(
new GainAbilityTargetEffect(new MyriadAbility())
);
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability);
}
private MassOfMysteries(final MassOfMysteries card) {
super(card);
}
@Override
public MassOfMysteries copy() {
return new MassOfMysteries(this);
}
}

View file

@ -0,0 +1,47 @@
package mage.cards.s;
import java.util.UUID;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.GetXValue;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.mana.AnyColorManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.filter.StaticFilters;
import mage.game.permanent.token.ShapeshifterColorlessToken;
/**
*
* @author muz
*/
public final class SpringleafParade extends CardImpl {
public SpringleafParade(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{X}{G}{G}");
// When this enchantment enters, create X 1/1 colorless Shapeshifter creature tokens with changeling.
this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new ShapeshifterColorlessToken(), GetXValue.instance)
.setText("create X 1/1 colorless Shapeshifter creature tokens with changeling.")
));
// Creature tokens you control have "{T}: Add one mana of any color."
this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect(
new AnyColorManaAbility(), Duration.WhileOnBattlefield, StaticFilters.FILTER_CREATURE_TOKENS)
));
}
private SpringleafParade(final SpringleafParade card) {
super(card);
}
@Override
public SpringleafParade copy() {
return new SpringleafParade(this);
}
}

View file

@ -0,0 +1,89 @@
package mage.cards.w;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.common.CountersSourceCount;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.mana.AnyColorManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.ScarecrowToken;
/**
*
* @author muz
*/
public final class WickersmithsTools extends CardImpl {
public WickersmithsTools(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
// Whenever one or more -1/-1 counters are put on a creature, put a charge counter on this artifact.
this.addAbility(new WickersmithsToolsTriggeredAbility());
// {T}: Add one mana of any color.
this.addAbility(new AnyColorManaAbility());
// {5}, {T}, Sacrifice this artifact: Create X tapped 2/2 colorless Scarecrow artifact creature tokens, where X is the number of charge counters on this artifact.
Ability ability = new SimpleActivatedAbility(new CreateTokenEffect(new ScarecrowToken(), new CountersSourceCount(CounterType.CHARGE)), new ManaCostsImpl<>("{5}"));
ability.addCost(new TapSourceCost());
ability.addCost(new SacrificeSourceCost());
this.addAbility(ability);
}
private WickersmithsTools(final WickersmithsTools card) {
super(card);
}
@Override
public WickersmithsTools copy() {
return new WickersmithsTools(this);
}
}
class WickersmithsToolsTriggeredAbility extends TriggeredAbilityImpl {
WickersmithsToolsTriggeredAbility() {
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.CHARGE.createInstance()));
setTriggerPhrase("Whenever one or more -1/-1 counters are put on a creature, ");
}
private WickersmithsToolsTriggeredAbility(final WickersmithsToolsTriggeredAbility ability) {
super(ability);
}
@Override
public WickersmithsToolsTriggeredAbility copy() {
return new WickersmithsToolsTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.COUNTERS_ADDED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId());
if (permanent == null
|| !permanent.isCreature(game)
|| !event.getData().equals(CounterType.M1M1.getName())
|| event.getAmount() < 1) {
return false;
}
return true;
}
}

View file

@ -105,6 +105,7 @@ public final class LorwynEclipsedCommander extends ExpansionSet {
cards.add(new SetCardInfo("Lamentation", 30, Rarity.RARE, mage.cards.l.Lamentation.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Liliana, Death Wielder", 78, Rarity.MYTHIC, mage.cards.l.LilianaDeathWielder.class));
cards.add(new SetCardInfo("Maelstrom Wanderer", 127, Rarity.RARE, mage.cards.m.MaelstromWanderer.class));
cards.add(new SetCardInfo("Mass of Mysteries", 3, Rarity.MYTHIC, mage.cards.m.MassOfMysteries.class));
cards.add(new SetCardInfo("Massacre Girl, Known Killer", 79, Rarity.MYTHIC, mage.cards.m.MassacreGirlKnownKiller.class));
cards.add(new SetCardInfo("Midnight Banshee", 80, Rarity.RARE, mage.cards.m.MidnightBanshee.class));
cards.add(new SetCardInfo("Muldrotha, the Gravetide", 128, Rarity.MYTHIC, mage.cards.m.MuldrothaTheGravetide.class));
@ -154,6 +155,7 @@ public final class LorwynEclipsedCommander extends ExpansionSet {
cards.add(new SetCardInfo("Sol Ring", 57, Rarity.UNCOMMON, mage.cards.s.SolRing.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Sol Ring", 58, Rarity.UNCOMMON, mage.cards.s.SolRing.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Soul Snuffers", 87, Rarity.UNCOMMON, mage.cards.s.SoulSnuffers.class));
cards.add(new SetCardInfo("Springleaf Parade", 19, Rarity.RARE, mage.cards.s.SpringleafParade.class));
cards.add(new SetCardInfo("Terminate", 134, Rarity.COMMON, mage.cards.t.Terminate.class));
cards.add(new SetCardInfo("Terramorphic Expanse", 169, Rarity.COMMON, mage.cards.t.TerramorphicExpanse.class));
cards.add(new SetCardInfo("The Reaper, King No More", 4, Rarity.MYTHIC, mage.cards.t.TheReaperKingNoMore.class));
@ -173,6 +175,8 @@ public final class LorwynEclipsedCommander extends ExpansionSet {
cards.add(new SetCardInfo("Village Pillagers", 34, Rarity.RARE, mage.cards.v.VillagePillagers.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Vraska, Betrayal's Sting", 88, Rarity.MYTHIC, mage.cards.v.VraskaBetrayalsSting.class));
cards.add(new SetCardInfo("Wickerbough Elder", 118, Rarity.COMMON, mage.cards.w.WickerboughElder.class));
cards.add(new SetCardInfo("Wickersmith's Tools", 21, Rarity.RARE, mage.cards.w.WickersmithsTools.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Wickersmith's Tools", 41, Rarity.RARE, mage.cards.w.WickersmithsTools.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Woodland Cemetery", 176, Rarity.RARE, mage.cards.w.WoodlandCemetery.class));
cards.add(new SetCardInfo("Yarok, the Desecrated", 136, Rarity.MYTHIC, mage.cards.y.YarokTheDesecrated.class));
}

View file

@ -274,6 +274,8 @@ public enum TokenRepository {
res.add(createXmageToken(XMAGE_IMAGE_NAME_COPY, 14, "https://api.scryfall.com/cards/tspm/1/en?format=image"));
res.add(createXmageToken(XMAGE_IMAGE_NAME_COPY, 15, "https://api.scryfall.com/cards/ttla/1/en?format=image"));
res.add(createXmageToken(XMAGE_IMAGE_NAME_COPY, 16, "https://api.scryfall.com/cards/ttla/2/en?format=image"));
res.add(createXmageToken(XMAGE_IMAGE_NAME_COPY, 17, "https://api.scryfall.com/cards/tecc/1/en?format=image"));
// City's Blessing
// https://scryfall.com/search?q=type%3Atoken+include%3Aextras+unique%3Aprints+City%27s+Blessing+&unique=cards&as=grid&order=name
@ -320,6 +322,7 @@ public enum TokenRepository {
res.add(createXmageToken(XMAGE_IMAGE_NAME_THE_MONARCH, 2, "https://api.scryfall.com/cards/tcn2/1/en?format=image"));
res.add(createXmageToken(XMAGE_IMAGE_NAME_THE_MONARCH, 3, "https://api.scryfall.com/cards/tltc/15/en?format=image"));
res.add(createXmageToken(XMAGE_IMAGE_NAME_THE_MONARCH, 4, "https://api.scryfall.com/cards/tfic/11/en?format=image"));
res.add(createXmageToken(XMAGE_IMAGE_NAME_THE_MONARCH, 5, "https://api.scryfall.com/cards/tecc/12/en?format=image"));
// Radiation (for trigger)
res.add(createXmageToken(XMAGE_IMAGE_NAME_RADIATION, 1, "https://api.scryfall.com/cards/tpip/22/en?format=image"));

View file

@ -0,0 +1,28 @@
package mage.game.permanent.token;
import mage.MageInt;
import mage.constants.CardType;
import mage.constants.SubType;
/**
* @author muz
*/
public final class ScarecrowToken extends TokenImpl {
public ScarecrowToken() {
super("Scarecrow Token", "2/2 colorless Scarecrow artifact creature token");
cardType.add(CardType.ARTIFACT);
cardType.add(CardType.CREATURE);
this.subtype.add(SubType.SCARECROW);
power = new MageInt(2);
toughness = new MageInt(2);
}
private ScarecrowToken(final ScarecrowToken token) {
super(token);
}
public ScarecrowToken copy() {
return new ScarecrowToken(this);
}
}

View file

@ -2911,7 +2911,23 @@
|Generate|TOK:TLE|Soldier|||SoldierRedToken|
# ECL
|Generate|TOK:ECL|Shapeshifter|||ShapeshifterColorlessToken|
|Generate|TOK:ECL|Goblin|||BlackAndRedGoblinToken|
|Generate|TOK:ECL|Treasure|||TreasureToken|
# ECC
# ECC
|Generate|TOK:ECC|Elemental|1||WhiteElementalToken|
|Generate|TOK:ECC|Elemental|2||OmnathElementalToken|
|Generate|TOK:ECC|Elemental|3||VoiceOfResurgenceToken|
|Generate|TOK:ECC|Elf Warrior|||ElfWarriorToken|
|Generate|TOK:ECC|Plant|||PlantToken|
|Generate|TOK:ECC|Rhino Warrior|||RhinoWarriorToken|
|Generate|TOK:ECC|Saproling|||SaprolingToken|
|Generate|TOK:ECC|Scarecrow|||ScarecrowToken|
|Generate|TOK:ECC|Snake|||DeathtouchSnakeToken|
|Generate|TOK:ECC|Zombie|||ZombieToken|
#TMT
|Generate|TOK:TMT|Mutagen|||MutagenToken|