From 3d94ce84d4c3c45e9bf024a4ab03115b36a7bd5c Mon Sep 17 00:00:00 2001 From: theelk801 Date: Tue, 30 Jan 2024 11:24:06 -0500 Subject: [PATCH] [MKM] Implement Tenth District Hero --- .../src/mage/cards/t/TenthDistrictHero.java | 139 ++++++++++++++++++ .../src/mage/sets/MurdersAtKarlovManor.java | 1 + .../single/mkm/TenthDistrictHeroTest.java | 112 ++++++++++++++ 3 files changed, 252 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/TenthDistrictHero.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/mkm/TenthDistrictHeroTest.java diff --git a/Mage.Sets/src/mage/cards/t/TenthDistrictHero.java b/Mage.Sets/src/mage/cards/t/TenthDistrictHero.java new file mode 100644 index 00000000000..a5e4a8a6205 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TenthDistrictHero.java @@ -0,0 +1,139 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.CollectEvidenceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.continuous.AddCardSubTypeSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.effects.common.continuous.SetBasePowerToughnessSourceEffect; +import mage.abilities.keyword.IndestructibleAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class TenthDistrictHero extends CardImpl { + + public TenthDistrictHero(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); + + this.subtype.add(SubType.HUMAN); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // {1}{W}, Collect evidence 2: Tenth District Hero becomes a Human Detective with base power and toughness 4/4 and gains vigilance. + Ability ability = new SimpleActivatedAbility(new AddCardSubTypeSourceEffect( + Duration.Custom, SubType.HUMAN, SubType.DETECTIVE + ), new ManaCostsImpl<>("{1}{W}")); + ability.addCost(new CollectEvidenceCost(2)); + ability.addEffect(new SetBasePowerToughnessSourceEffect( + 4, 4, Duration.Custom + ).setText("with base power and toughness 4/4")); + ability.addEffect(new GainAbilitySourceEffect( + VigilanceAbility.getInstance(), Duration.Custom + ).setText("and gains vigilance")); + this.addAbility(ability); + + // {2}{W}, Collect evidence 4: If Tenth District Hero is a Detective, it becomes a legendary creature named Mileva, the Stalwart, it has base power and toughness 5/5, and it gains "Other creatures you control have indestructible." + ability = new SimpleActivatedAbility(new TenthDistrictHeroEffect(), new ManaCostsImpl<>("{2}{W}")); + ability.addCost(new CollectEvidenceCost(4)); + this.addAbility(ability); + } + + private TenthDistrictHero(final TenthDistrictHero card) { + super(card); + } + + @Override + public TenthDistrictHero copy() { + return new TenthDistrictHero(this); + } +} + +class TenthDistrictHeroEffect extends ContinuousEffectImpl { + + TenthDistrictHeroEffect() { + super(Duration.Custom, Outcome.Benefit); + staticText = "if {this} is a Detective, it becomes a legendary creature " + + "named Mileva, the Stalwart, it has base power and toughness 5/5, " + + "and it gains \"Other creatures you control have indestructible.\""; + } + + private TenthDistrictHeroEffect(final TenthDistrictHeroEffect effect) { + super(effect); + } + + @Override + public TenthDistrictHeroEffect copy() { + return new TenthDistrictHeroEffect(this); + } + + @Override + public void init(Ability source, Game game) { + Permanent permanent = source.getSourcePermanentIfItStillExists(game); + if (permanent == null || !permanent.hasSubtype(SubType.DETECTIVE, game)) { + discard(); + } + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + Permanent permanent = source.getSourcePermanentIfItStillExists(game); + if (permanent == null) { + discard(); + return false; + } + switch (layer) { + case TextChangingEffects_3: + permanent.setName("Mileva, the Stalwart"); + return true; + case TypeChangingEffects_4: + permanent.addSuperType(game, SuperType.LEGENDARY); + permanent.addCardType(game, CardType.CREATURE); + return true; + case AbilityAddingRemovingEffects_6: + permanent.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect( + IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield, + StaticFilters.FILTER_PERMANENT_CREATURES, true + )), source.getSourceId(), game); + return true; + case PTChangingEffects_7: + if (sublayer == SubLayer.SetPT_7b) { + permanent.getPower().setModifiedBaseValue(5); + permanent.getToughness().setModifiedBaseValue(5); + return true; + } + } + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean hasLayer(Layer layer) { + switch (layer) { + case TextChangingEffects_3: + case TypeChangingEffects_4: + case AbilityAddingRemovingEffects_6: + case PTChangingEffects_7: + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/MurdersAtKarlovManor.java b/Mage.Sets/src/mage/sets/MurdersAtKarlovManor.java index 75b0802a56c..8fd93634e05 100644 --- a/Mage.Sets/src/mage/sets/MurdersAtKarlovManor.java +++ b/Mage.Sets/src/mage/sets/MurdersAtKarlovManor.java @@ -199,6 +199,7 @@ public final class MurdersAtKarlovManor extends ExpansionSet { cards.add(new SetCardInfo("Surveillance Monitor", 73, Rarity.UNCOMMON, mage.cards.s.SurveillanceMonitor.class)); cards.add(new SetCardInfo("Suspicious Detonation", 145, Rarity.COMMON, mage.cards.s.SuspiciousDetonation.class)); cards.add(new SetCardInfo("Swamp", 274, Rarity.LAND, mage.cards.basiclands.Swamp.class, FULL_ART_BFZ_VARIOUS)); + cards.add(new SetCardInfo("Tenth District Hero", 34, Rarity.RARE, mage.cards.t.TenthDistrictHero.class)); cards.add(new SetCardInfo("Teysa, Opulent Oligarch", 234, Rarity.RARE, mage.cards.t.TeysaOpulentOligarch.class)); cards.add(new SetCardInfo("The Chase Is On", 116, Rarity.COMMON, mage.cards.t.TheChaseIsOn.class)); cards.add(new SetCardInfo("They Went This Way", 178, Rarity.COMMON, mage.cards.t.TheyWentThisWay.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/mkm/TenthDistrictHeroTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/mkm/TenthDistrictHeroTest.java new file mode 100644 index 00000000000..0a54b4ded33 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/mkm/TenthDistrictHeroTest.java @@ -0,0 +1,112 @@ +package org.mage.test.cards.single.mkm; + +import mage.abilities.keyword.VigilanceAbility; +import mage.constants.PhaseStep; +import mage.constants.SubType; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author TheElk801 + */ +public class TenthDistrictHeroTest extends CardTestPlayerBase { + + private static final String hero = "Tenth District Hero"; + private static final String giant = "Hill Giant"; + private static final String mileva = "Mileva, the Stalwart"; + + @Test + public void testFirstAblityOnly() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); + addCard(Zone.BATTLEFIELD, playerA, hero); + addCard(Zone.GRAVEYARD, playerA, giant); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}"); + setChoice(playerA, giant); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPowerToughness(playerA, hero, 4, 4); + assertSubtype(hero, SubType.HUMAN); + assertSubtype(hero, SubType.DETECTIVE); + assertAbility(playerA, hero, VigilanceAbility.getInstance(), true); + assertPermanentCount(playerA, mileva, 0); + } + + @Test + public void testSecondAblityOnly() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 3); + addCard(Zone.BATTLEFIELD, playerA, hero); + addCard(Zone.GRAVEYARD, playerA, giant); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}"); + setChoice(playerA, giant); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPowerToughness(playerA, hero, 2, 3); + assertSubtype(hero, SubType.HUMAN); + assertNotSubtype(hero, SubType.DETECTIVE); + assertAbility(playerA, hero, VigilanceAbility.getInstance(), false); + assertPermanentCount(playerA, hero, 1); + assertPermanentCount(playerA, mileva, 0); + } + + @Test + public void testBothAbilities() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2 + 3); + addCard(Zone.BATTLEFIELD, playerA, hero); + addCard(Zone.GRAVEYARD, playerA, giant, 1 + 1); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{1}"); + setChoice(playerA, giant); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{2}"); + setChoice(playerA, giant); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPowerToughness(playerA, mileva, 5, 5); + assertSubtype(mileva, SubType.HUMAN); + assertSubtype(mileva, SubType.DETECTIVE); + assertAbility(playerA, mileva, VigilanceAbility.getInstance(), true); + assertPermanentCount(playerA, mileva, 1); + assertPermanentCount(playerA, hero, 0); + } + + @Test + public void testBothAbilitiesReversed() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2 + 3); + addCard(Zone.BATTLEFIELD, playerA, hero); + addCard(Zone.GRAVEYARD, playerA, giant, 1 + 1); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{2}"); + setChoice(playerA, giant); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{1}"); + setChoice(playerA, giant); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPowerToughness(playerA, hero, 4, 4); + assertSubtype(hero, SubType.HUMAN); + assertSubtype(hero, SubType.DETECTIVE); + assertAbility(playerA, hero, VigilanceAbility.getInstance(), true); + assertPermanentCount(playerA, mileva, 0); + } +}