implement [LCI] Market Gnome

This commit is contained in:
xenohedron 2023-11-09 21:38:28 -05:00
parent a5922457ad
commit 933d694b08
5 changed files with 191 additions and 8 deletions

View file

@ -0,0 +1,81 @@
package mage.cards.m;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.GainLifeEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import java.util.UUID;
/**
* @author xenohedron
*/
public final class MarketGnome extends CardImpl {
public MarketGnome(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{W}");
this.subtype.add(SubType.GNOME);
this.power = new MageInt(0);
this.toughness = new MageInt(3);
// When Market Gnome dies, you gain 1 life and draw a card.
Ability ability = new DiesSourceTriggeredAbility(new GainLifeEffect(1));
ability.addEffect(new DrawCardSourceControllerEffect(1).concatBy("and"));
this.addAbility(ability);
// When Market Gnome is exiled from the battlefield while you're activating a craft ability, you gain 1 life and draw a card.
this.addAbility(new MarketGnomeTriggeredAbility());
}
private MarketGnome(final MarketGnome card) {
super(card);
}
@Override
public MarketGnome copy() {
return new MarketGnome(this);
}
}
class MarketGnomeTriggeredAbility extends TriggeredAbilityImpl {
MarketGnomeTriggeredAbility() {
super(Zone.BATTLEFIELD, new GainLifeEffect(1));
this.addEffect(new DrawCardSourceControllerEffect(1).concatBy("and"));
setTriggerPhrase("When {this} is exiled from the battlefield while you're activating a craft ability, ");
// setLeavesTheBattlefieldTrigger(true); // not needed as special event is fired prior to the actual exiling
}
private MarketGnomeTriggeredAbility(final MarketGnomeTriggeredAbility ability) {
super(ability);
}
@Override
public MarketGnomeTriggeredAbility copy() {
return new MarketGnomeTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.EXILED_WHILE_CRAFTING;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId());
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(getSourceId());
return permanent != null && sourcePermanent != null && permanent.getId().equals(sourcePermanent.getId());
}
}

View file

@ -203,6 +203,7 @@ public final class TheLostCavernsOfIxalan extends ExpansionSet {
cards.add(new SetCardInfo("Malcolm, Alluring Scoundrel", 63, Rarity.RARE, mage.cards.m.MalcolmAlluringScoundrel.class));
cards.add(new SetCardInfo("Malicious Eclipse", 111, Rarity.UNCOMMON, mage.cards.m.MaliciousEclipse.class));
cards.add(new SetCardInfo("Marauding Brinefang", 64, Rarity.COMMON, mage.cards.m.MaraudingBrinefang.class));
cards.add(new SetCardInfo("Market Gnome", 22, Rarity.UNCOMMON, mage.cards.m.MarketGnome.class));
cards.add(new SetCardInfo("Master's Guide-Mural", 233, Rarity.UNCOMMON, mage.cards.m.MastersGuideMural.class));
cards.add(new SetCardInfo("Master's Manufactory", 233, Rarity.UNCOMMON, mage.cards.m.MastersManufactory.class));
cards.add(new SetCardInfo("Mastercraft Raptor", 164, Rarity.UNCOMMON, mage.cards.m.MastercraftRaptor.class));

View file

@ -11,9 +11,9 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
*/
public class CraftTest extends CardTestPlayerBase {
private static final String sawblades = "Spring-Loaded Sawblades";
private static final String chariot = "Bladewheel Chariot";
private static final String relic = "Darksteel Relic";
private static final String sawblades = "Spring-Loaded Sawblades"; // Craft with artifact {3}{W}
private static final String chariot = "Bladewheel Chariot"; // back side Vehicle
private static final String relic = "Darksteel Relic"; // Artifact {0} Indestructible
@Test
public void testExilePermanent() {
@ -55,11 +55,13 @@ public class CraftTest extends CardTestPlayerBase {
assertExileCount(playerA, relic, 1);
}
private static final String standard = "Sunbird Standard";
private static final String effigy = "Sunbird Effigy";
private static final String thoctar = "Woolly Thoctar";
private static final String watchwolf = "Watchwolf";
private static final String yearling = "Cerodon Yearling";
private static final String standard = "Sunbird Standard"; // Craft with one or more {5}
private static final String effigy = "Sunbird Effigy"; // back side artifact creature
// Sunbird Effigys power and toughness are each equal to the number of colors among the exiled cards used to craft it.
// {T}: For each color among the exiled cards used to craft Sunbird Effigy, add one mana of that color.
private static final String thoctar = "Woolly Thoctar"; // RGW 5/4
private static final String watchwolf = "Watchwolf"; // GW 3/3
private static final String yearling = "Cerodon Yearling"; // RW 2/2 Vigilance Haste
@Test
public void testEffigy() {
@ -109,4 +111,94 @@ public class CraftTest extends CardTestPlayerBase {
assertPermanentCount(playerA, thoctar, 1);
assertPowerToughness(playerA, effigy, 3, 3);
}
private static final String gnome = "Market Gnome";
// When Market Gnome is exiled from the battlefield while youre activating a craft ability, you gain 1 life and draw a card.
@Test
public void testMarketGnomeExilePermanent() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
addCard(Zone.BATTLEFIELD, playerA, sawblades);
addCard(Zone.BATTLEFIELD, playerA, gnome);
addTarget(playerA, gnome);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Craft");
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, sawblades, 0);
assertPermanentCount(playerA, chariot, 1);
assertPermanentCount(playerA, gnome, 0);
assertExileCount(playerA, gnome, 1);
assertLife(playerA, 21);
assertHandCount(playerA, 1);
}
@Test
public void testMarketGnomeExileCard() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
addCard(Zone.BATTLEFIELD, playerA, sawblades);
addCard(Zone.GRAVEYARD, playerA, gnome);
addTarget(playerA, gnome);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Craft");
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, sawblades, 0);
assertPermanentCount(playerA, chariot, 1);
assertGraveyardCount(playerA, gnome, 0);
assertExileCount(playerA, gnome, 1);
assertLife(playerA, 20);
assertHandCount(playerA, 0);
}
@Test
public void testMarketGnomeExiledExileOther() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
addCard(Zone.BATTLEFIELD, playerA, sawblades);
addCard(Zone.BATTLEFIELD, playerA, relic);
addCard(Zone.EXILED, playerA, gnome);
addTarget(playerA, relic);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Craft");
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, sawblades, 0);
assertPermanentCount(playerA, chariot, 1);
assertPermanentCount(playerA, relic, 0);
assertExileCount(playerA, relic, 1);
assertLife(playerA, 20);
assertHandCount(playerA, 0);
}
@Test
public void testMarketGnomeBattlefieldExileOther() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
addCard(Zone.BATTLEFIELD, playerA, sawblades);
addCard(Zone.BATTLEFIELD, playerA, relic);
addCard(Zone.BATTLEFIELD, playerA, gnome);
addTarget(playerA, relic);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Craft");
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerA, sawblades, 0);
assertPermanentCount(playerA, chariot, 1);
assertPermanentCount(playerA, relic, 0);
assertExileCount(playerA, relic, 1);
assertLife(playerA, 20);
assertHandCount(playerA, 0);
}
}

View file

@ -18,6 +18,7 @@ import mage.filter.common.FilterOwnedCard;
import mage.filter.predicate.Predicate;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCardInGraveyardBattlefieldOrStack;
@ -131,6 +132,8 @@ class CraftCost extends CostImpl {
.map(uuid -> {
Permanent permanent = game.getPermanent(uuid);
if (permanent != null) {
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.EXILED_WHILE_CRAFTING,
permanent.getId(), source, player.getId()));
return permanent;
}
return game.getCard(uuid);

View file

@ -540,6 +540,12 @@ public class GameEvent implements Serializable {
flag not used for this event
*/
DISCOVERED,
/* Exiled while crafting (see Market Gnome)
targetId the permanent exiled
sourceId of the craft ability
playerId the player crafting
*/
EXILED_WHILE_CRAFTING,
//custom events
CUSTOM_EVENT
}