[SPM] Implement Peter Parker / Amazing Spider-Man

This commit is contained in:
jmlundeen 2025-08-30 22:37:14 -05:00
parent 7b9a72f758
commit 86cd18beb9
3 changed files with 247 additions and 0 deletions

View file

@ -0,0 +1,130 @@
package mage.cards.p;
import mage.abilities.Ability;
import mage.abilities.common.ActivateAsSorceryActivatedAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.keyword.ReachAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.abilities.keyword.WebSlingingAbility;
import mage.cards.Card;
import mage.cards.CardSetInfo;
import mage.cards.ModalDoubleFacedCard;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ColorlessPredicate;
import mage.game.Game;
import mage.game.permanent.token.Spider21Token;
import mage.game.stack.Spell;
import mage.players.Player;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
/**
*
* @author Jmlundeen
*/
public final class PeterParker extends ModalDoubleFacedCard {
public PeterParker(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo,
new SuperType[]{SuperType.LEGENDARY},new CardType[]{CardType.CREATURE}, new SubType[]{SubType.HUMAN, SubType.SCIENTIST, SubType.HERO}, "{1}{W}",
"Amazing Spider-Man",
new SuperType[]{SuperType.LEGENDARY}, new CardType[]{CardType.CREATURE}, new SubType[]{SubType.SPIDER, SubType.HUMAN, SubType.HERO}, "{1}{G}{W}{U}");
this.getLeftHalfCard().setPT(0, 1);
this.getRightHalfCard().setPT(4, 4);
// When Peter Parker enters, create a 2/1 green Spider creature token with reach.
this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new Spider21Token())));
// {1}{G}{W}{U}: Transform Peter Parker. Activate only as a sorcery.
this.getLeftHalfCard().addAbility(new ActivateAsSorceryActivatedAbility(
new TransformSourceEffect(), new ManaCostsImpl<>("{1}{G}{W}{U}")
));
// Amazing Spider-Man
// Vigilance
this.getRightHalfCard().addAbility(VigilanceAbility.getInstance());
// Reach
this.getRightHalfCard().addAbility(ReachAbility.getInstance());
// Each legendary spell you cast that's one or more colors has web-slinging {G}{W}{U}.
this.getRightHalfCard().addAbility(new SimpleStaticAbility(new AmazingSpiderManEffect()));
}
private PeterParker(final PeterParker card) {
super(card);
}
@Override
public PeterParker copy() {
return new PeterParker(this);
}
}
class AmazingSpiderManEffect extends ContinuousEffectImpl {
static final FilterCard filter = new FilterCard("legendary spell that's one or more colors");
static {
filter.add(Predicates.not(ColorlessPredicate.instance));
filter.add(SuperType.LEGENDARY.getPredicate());
}
AmazingSpiderManEffect() {
super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
staticText = "Each legendary spell you cast that's one or more colors has web-slinging {G}{W}{U}";
}
private AmazingSpiderManEffect(final AmazingSpiderManEffect effect) {
super(effect) ;
}
@Override
public AmazingSpiderManEffect copy() {
return new AmazingSpiderManEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
Set<Card> cardsToGainAbility = new HashSet<>();
cardsToGainAbility.addAll(controller.getHand().getCards(filter, game));
cardsToGainAbility.addAll(controller.getGraveyard().getCards(filter, game));
controller.getLibrary().getCards(game).stream()
.filter(c -> filter.match(c, game))
.forEach(cardsToGainAbility::add);
game.getExile().getAllCardsByRange(game, controller.getId()).stream()
.filter(c -> filter.match(c, game))
.forEach(cardsToGainAbility::add);
game.getCommanderCardsFromCommandZone(controller, CommanderCardType.ANY).stream()
.filter(c -> filter.match(c, game))
.forEach(cardsToGainAbility::add);
game.getStack().stream()
.filter(Spell.class::isInstance)
.filter(s -> s.isControlledBy(controller.getId()))
.filter(s -> filter.match((Spell) s, game))
.map(s -> game.getCard(s.getSourceId()))
.filter(Objects::nonNull)
.forEach(cardsToGainAbility::add);
for (Card card : cardsToGainAbility) {
Ability ability = new WebSlingingAbility(card, "{G}{W}{U}");
ability.setSourceId(card.getId());
ability.setControllerId(card.getControllerOrOwnerId());
game.getState().addOtherAbility(card, ability);
}
return true;
}
}

View file

@ -82,6 +82,9 @@ public final class MarvelsSpiderMan extends ExpansionSet {
cards.add(new SetCardInfo("Origin of Spider-Man", 218, Rarity.RARE, mage.cards.o.OriginOfSpiderMan.class, FULL_ART_USE_VARIOUS));
cards.add(new SetCardInfo("Origin of Spider-Man", 9, Rarity.RARE, mage.cards.o.OriginOfSpiderMan.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Oscorp Research Team", 40, Rarity.COMMON, mage.cards.o.OscorpResearchTeam.class));
cards.add(new SetCardInfo("Peter Parker", 10, Rarity.MYTHIC, mage.cards.p.PeterParker.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Peter Parker", 208, Rarity.MYTHIC, mage.cards.p.PeterParker.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Peter Parker", 232, Rarity.MYTHIC, mage.cards.p.PeterParker.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Pictures of Spider-Man", 109, Rarity.UNCOMMON, mage.cards.p.PicturesOfSpiderMan.class));
cards.add(new SetCardInfo("Plains", 189, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Plains", 194, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS));

View file

@ -0,0 +1,114 @@
package org.mage.test.cards.single.spm;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.TapAllEffect;
import mage.constants.PhaseStep;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import org.junit.Ignore;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author Jmlundeen
*/
public class PeterParkerTest extends CardTestPlayerBase {
/*
Peter Parker
{1}{W}
Legendary Creature - Human Scientist Hero
When Peter Parker enters, create a 2/1 green Spider creature token with reach.
{1}{G}{W}{U}: Transform Peter Parker. Activate only as a sorcery.
Amazing Spider-Man
{1}{G}{W}{U}
Legendary Creature - Spider Human Hero
Vigilance, reach
Each legendary spell you cast that's one or more colors has web-slinging {G}{W}{U}.
4/4
*/
private static final String peterParker = "Peter Parker";
/*
Absolute Virtue
{6}{W}{U}
Legendary Creature - Avatar Warrior
This spell can't be countered.
Flying
You have protection from each of your opponents.
8/8
*/
private static final String absoluteVirtue = "Absolute Virtue";
/*
Adelbert Steiner
{1}{W}
Legendary Creature - Human Knight
Lifelink
Adelbert Steiner gets +1/+1 for each Equipment you control.
2/1
*/
private static final String adelbertSteiner = "Adelbert Steiner";
/*
Chainer, Nightmare Adept
{2}{B}{R}
Legendary Creature - Human Minion
Discard a card: You may cast a creature card from your graveyard this turn. Activate this ability only once each turn.
Whenever a nontoken creature enters the battlefield under your control, if you didn't cast it from your hand, it gains haste until your next turn.
3/2
*/
private static final String chainerNightmareAdept = "Chainer, Nightmare Adept";
/*
Balduvian Bears
{1}{G}
Creature - Bear
2/2
*/
private static final String balduvianBears = "Balduvian Bears";
@Test
@Ignore("Enable after MDFC rework")
public void testAmazingSpiderMan() {
setStrictChooseMode(true);
addCustomCardWithAbility("tap all creatures", playerA, new SimpleActivatedAbility(
new TapAllEffect(new FilterCreaturePermanent(SubType.BEAR, "bears")),
new ManaCostsImpl<>("")
));
addCard(Zone.BATTLEFIELD, playerA, peterParker);
addCard(Zone.BATTLEFIELD, playerA, chainerNightmareAdept);
addCard(Zone.BATTLEFIELD, playerA, balduvianBears,2);
addCard(Zone.HAND, playerA, adelbertSteiner, 2);
addCard(Zone.GRAVEYARD, playerA, absoluteVirtue);
addCard(Zone.BATTLEFIELD, playerA, "Tropical Island", 6);
addCard(Zone.BATTLEFIELD, playerA, "Tundra", 6);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "tap all"); // tap bears, addCard command isn't working to set tapped
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, adelbertSteiner + " with Web-slinging", true);
setChoice(playerA, balduvianBears); // return to hand
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Discard a card");
setChoice(playerA, adelbertSteiner); // discard
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
checkPlayableAbility("Bear does not have web-slinging", 1, PhaseStep.PRECOMBAT_MAIN, playerA,
"Cast " + balduvianBears + " with Web-slinging", false);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, absoluteVirtue + " with Web-slinging");
setChoice(playerA, balduvianBears); // return to hand
setStopAt(1, PhaseStep.END_TURN);
execute();
}
}