[SPM] Implement Gwenom, Remorseless

This commit is contained in:
jmlundeen 2025-08-29 14:56:01 -05:00
parent d59136cc33
commit 3c6a18f24e
4 changed files with 186 additions and 1 deletions

View file

@ -0,0 +1,124 @@
package mage.cards.g;
import mage.MageIdentifier;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.costs.Costs;
import mage.abilities.costs.CostsImpl;
import mage.abilities.costs.common.PayLifeCost;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.common.AddContinuousEffectToGame;
import mage.abilities.effects.common.continuous.LookAtTopCardOfLibraryAnyTimeEffect;
import mage.abilities.keyword.DeathtouchAbility;
import mage.abilities.keyword.LifelinkAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
import mage.players.Player;
import java.util.UUID;
/**
*
* @author Jmlundeen
*/
public final class GwenomRemorseless extends CardImpl {
public GwenomRemorseless(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}");
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.SYMBIOTE);
this.subtype.add(SubType.SPIDER);
this.subtype.add(SubType.HERO);
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// Deathtouch
this.addAbility(DeathtouchAbility.getInstance());
// Lifelink
this.addAbility(LifelinkAbility.getInstance());
// Whenever Gwenom attacks, until end of turn you may look at the top card of your library any time and you may play cards from the top of your library. If you cast a spell this way, pay life equal to its mana value rather than pay its mana cost.
ContinuousEffect libraryAnyTimeEffect = new LookAtTopCardOfLibraryAnyTimeEffect(Duration.EndOfTurn);
libraryAnyTimeEffect.setText("until end of turn you may look at the top card of your library any time");
libraryAnyTimeEffect.concatBy(" ");
AsThoughEffectImpl playCardEffect = new GwenomRemorselessPlayTopCardEffect();
playCardEffect.concatBy("and");
this.addAbility(new AttacksTriggeredAbility(new AddContinuousEffectToGame(libraryAnyTimeEffect, playCardEffect))
.setIdentifier(MageIdentifier.GwenomRemorselessAlternateCast));
}
private GwenomRemorseless(final GwenomRemorseless card) {
super(card);
}
@Override
public GwenomRemorseless copy() {
return new GwenomRemorseless(this);
}
}
class GwenomRemorselessPlayTopCardEffect extends AsThoughEffectImpl {
GwenomRemorselessPlayTopCardEffect() {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE,
Duration.EndOfTurn, Outcome.AIDontUseIt); // AI will need help with this
staticText = "you may play cards from the top of your library. If you cast a spell this way, "
+ "pay life equal to its mana value rather than pay its mana cost.";
}
private GwenomRemorselessPlayTopCardEffect(final GwenomRemorselessPlayTopCardEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public GwenomRemorselessPlayTopCardEffect copy() {
return new GwenomRemorselessPlayTopCardEffect(this);
}
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
// current card's part
Card cardToCheck = game.getCard(objectId);
if (cardToCheck == null) {
return false;
}
// must be you
if (!affectedControllerId.equals(source.getControllerId())) {
return false;
}
// must be your card
Player player = game.getPlayer(cardToCheck.getOwnerId());
if (player == null || !player.getId().equals(affectedControllerId)) {
return false;
}
// must be from your library
Card topCard = player.getLibrary().getFromTop(game);
if (topCard == null || !topCard.getId().equals(cardToCheck.getMainCard().getId())) {
return false;
}
// allows to play/cast with alternative life cost
if (!cardToCheck.isLand(game)) {
PayLifeCost lifeCost = new PayLifeCost(cardToCheck.getSpellAbility().getManaCosts().manaValue());
Costs newCosts = new CostsImpl();
newCosts.add(lifeCost);
newCosts.addAll(cardToCheck.getSpellAbility().getCosts());
player.setCastSourceIdWithAlternateMana(cardToCheck.getId(), null, newCosts, MageIdentifier.GwenomRemorselessAlternateCast);
}
return true;
}
}

View file

@ -38,6 +38,7 @@ public final class MarvelsSpiderMan extends ExpansionSet {
cards.add(new SetCardInfo("Green Goblin, Revenant", 130, Rarity.UNCOMMON, mage.cards.g.GreenGoblinRevenant.class)); cards.add(new SetCardInfo("Green Goblin, Revenant", 130, Rarity.UNCOMMON, mage.cards.g.GreenGoblinRevenant.class));
cards.add(new SetCardInfo("Grow Extra Arms", 101, Rarity.COMMON, mage.cards.g.GrowExtraArms.class)); cards.add(new SetCardInfo("Grow Extra Arms", 101, Rarity.COMMON, mage.cards.g.GrowExtraArms.class));
cards.add(new SetCardInfo("Guy in the Chair", 102, Rarity.COMMON, mage.cards.g.GuyInTheChair.class)); cards.add(new SetCardInfo("Guy in the Chair", 102, Rarity.COMMON, mage.cards.g.GuyInTheChair.class));
cards.add(new SetCardInfo("Gwenom, Remorseless", 9998, Rarity.MYTHIC, mage.cards.g.GwenomRemorseless.class));
cards.add(new SetCardInfo("Iron Spider, Stark Upgrade", 166, Rarity.RARE, mage.cards.i.IronSpiderStarkUpgrade.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Iron Spider, Stark Upgrade", 166, Rarity.RARE, mage.cards.i.IronSpiderStarkUpgrade.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Iron Spider, Stark Upgrade", 279, Rarity.RARE, mage.cards.i.IronSpiderStarkUpgrade.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Iron Spider, Stark Upgrade", 279, Rarity.RARE, mage.cards.i.IronSpiderStarkUpgrade.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Island", 190, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS)); cards.add(new SetCardInfo("Island", 190, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS));

View file

@ -0,0 +1,59 @@
package org.mage.test.cards.single.spm;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author Jmlundeen
*/
public class GwenomRemorselessTest extends CardTestPlayerBase {
/*
Gwenom, Remorseless
{3}{B}{B}
Legendary Creature - Symbiote Spider Hero
Deathtouch, lifelink
Whenever Gwenom attacks, until end of turn you may look at the top card of your library any time and you may play cards from the top of your library. If you cast a spell this way, pay life equal to its mana value rather than pay its mana cost.
4/4
*/
private static final String gwenomRemorseless = "Gwenom, Remorseless";
/*
Bear Cub
{1}{G}
Creature - Bear
2/2
*/
private static final String bearCub = "Bear Cub";
@Test
public void testGwenomRemorseless() {
setStrictChooseMode(true);
skipInitShuffling();
addCard(Zone.BATTLEFIELD, playerA, gwenomRemorseless);
addCard(Zone.LIBRARY, playerA, "Island");
addCard(Zone.LIBRARY, playerA, bearCub, 2);
addCard(Zone.LIBRARY, playerA, "Forest");
attack(1, playerA, gwenomRemorseless);
playLand(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Forest");
waitStackResolved(1, PhaseStep.POSTCOMBAT_MAIN);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, bearCub);
// effect ends at end of turn
checkPlayableAbility("Can't play top card", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Play Island", false);
setStopAt(2, PhaseStep.PRECOMBAT_MAIN);
execute();
assertPermanentCount(playerA, bearCub, 1);
assertPermanentCount(playerA, gwenomRemorseless, 1);
assertPermanentCount(playerA, "Forest", 1);
assertLife(playerB, 20 - 4);
assertLife(playerA, 20 + 4 - 2);
}
}

View file

@ -85,7 +85,8 @@ public enum MageIdentifier {
WickerfolkIndomitableAlternateCast, WickerfolkIndomitableAlternateCast,
UriangerAugureltAlternateCast, UriangerAugureltAlternateCast,
ValgavothTerrorEaterAlternateCast, ValgavothTerrorEaterAlternateCast,
LightstallInquisitorAlternateCast; LightstallInquisitorAlternateCast,
GwenomRemorselessAlternateCast;
/** /**
* Additional text if there is need to differentiate two very similar effects * Additional text if there is need to differentiate two very similar effects