diff --git a/Mage.Sets/src/mage/cards/t/ThrillKillDisciple.java b/Mage.Sets/src/mage/cards/t/ThrillKillDisciple.java new file mode 100644 index 00000000000..6555b653d29 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/ThrillKillDisciple.java @@ -0,0 +1,51 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.abilities.common.DiesSourceTriggeredAbility; +import mage.abilities.costs.Cost; +import mage.abilities.costs.Costs; +import mage.abilities.costs.CostsImpl; +import mage.abilities.costs.common.DiscardCardCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.keyword.SquadAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.game.permanent.token.JunkToken; + +import java.util.UUID; + +/** + * @author Susucr + */ +public final class ThrillKillDisciple extends CardImpl { + + public ThrillKillDisciple(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); + + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.MERCENARY); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // Squad--{1}, Discard a card. + Costs costs = new CostsImpl<>(); + costs.add(new ManaCostsImpl<>("{1}")); + costs.add(new DiscardCardCost()); + this.addAbility(new SquadAbility(costs)); + + // When Thrill-Kill Disciple dies, create a Junk token. + this.addAbility(new DiesSourceTriggeredAbility(new CreateTokenEffect(new JunkToken()))); + } + + private ThrillKillDisciple(final ThrillKillDisciple card) { + super(card); + } + + @Override + public ThrillKillDisciple copy() { + return new ThrillKillDisciple(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Fallout.java b/Mage.Sets/src/mage/sets/Fallout.java index 47d3901089c..acdf643613b 100644 --- a/Mage.Sets/src/mage/sets/Fallout.java +++ b/Mage.Sets/src/mage/sets/Fallout.java @@ -339,6 +339,7 @@ public final class Fallout extends ExpansionSet { cards.add(new SetCardInfo("The Wise Mothman", 4, Rarity.MYTHIC, mage.cards.t.TheWiseMothman.class)); cards.add(new SetCardInfo("Thirst for Knowledge", 180, Rarity.UNCOMMON, mage.cards.t.ThirstForKnowledge.class)); cards.add(new SetCardInfo("Thought Vessel", 251, Rarity.COMMON, mage.cards.t.ThoughtVessel.class)); + cards.add(new SetCardInfo("Thrill-Kill Disciple", 68, Rarity.RARE, mage.cards.t.ThrillKillDisciple.class)); cards.add(new SetCardInfo("Tireless Tracker", 207, Rarity.RARE, mage.cards.t.TirelessTracker.class)); cards.add(new SetCardInfo("Treasure Vault", 314, Rarity.RARE, mage.cards.t.TreasureVault.class)); cards.add(new SetCardInfo("Unexpected Windfall", 193, Rarity.COMMON, mage.cards.u.UnexpectedWindfall.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/pip/ThrillKillDiscipleTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/pip/ThrillKillDiscipleTest.java new file mode 100644 index 00000000000..5b7cd65424a --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/pip/ThrillKillDiscipleTest.java @@ -0,0 +1,43 @@ +package org.mage.test.cards.single.pip; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class ThrillKillDiscipleTest extends CardTestPlayerBase { + + /** + * {@link mage.cards.t.ThrillKillDisciple Thrill-Kill Disciple} {2}{R} + * Creature — Human Mercenary + * Squad—{1}, Discard a card. (As an additional cost to cast this spell, you may pay its squad cost any number of times. When this creature enters the battlefield, create that many tokens that are copies of it.) + * When Thrill-Kill Disciple dies, create a Junk token. + * 3/2 + */ + private static final String disciple = "Thrill-Kill Disciple"; + + @Test + public void test_SquadWithCombinedCost() { + setStrictChooseMode(true); + + addCard(Zone.HAND, playerA, disciple); + addCard(Zone.HAND, playerA, "Taiga", 2); // For discard + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, disciple); + setChoice(playerA, true); // yes to Squad first time + setChoice(playerA, true); // yes to Squad second time + setChoice(playerA, false); // no to Squad first time + setChoice(playerA, "Taiga", 2); // Chosen to be discarded + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA, "Taiga", 2); + assertPermanentCount(playerA, disciple, 3); + assertTappedCount("Mountain", true, 5); + } +} diff --git a/Mage/src/main/java/mage/abilities/keyword/SquadAbility.java b/Mage/src/main/java/mage/abilities/keyword/SquadAbility.java index 8c0a232a9e6..6abac80a6ca 100644 --- a/Mage/src/main/java/mage/abilities/keyword/SquadAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/SquadAbility.java @@ -25,7 +25,17 @@ public class SquadAbility extends StaticAbility implements OptionalAdditionalSou protected static final String SQUAD_REMINDER = "You may pay an additional " + "{cost} any number of times as you cast this spell."; + private static Costs wrapSingleCost(Cost cost) { + Costs costs = new CostsImpl<>(); + costs.add(cost); + return costs; + } + public SquadAbility(Cost cost) { + this(wrapSingleCost(cost)); + } + + public SquadAbility(Costs cost) { super(Zone.STACK, null); setSquadCost(cost); addSubAbility(new SquadTriggerAbility()); @@ -36,14 +46,19 @@ public class SquadAbility extends StaticAbility implements OptionalAdditionalSou this.cost = ability.cost.copy(); } + @Override + public void addCost(Cost cost) { + throw new IllegalArgumentException("Wrong code usage: costs for Squad should be set all at once."); + } + @Override public SquadAbility copy() { return new SquadAbility(this); } - private void setSquadCost(Cost cost) { - OptionalAdditionalCost newCost = new OptionalAdditionalCostImpl( - SQUAD_KEYWORD, SQUAD_REMINDER, cost); + private void setSquadCost(Costs costs) { + OptionalAdditionalCost newCost = + new OptionalAdditionalCostImpl(SQUAD_KEYWORD, SQUAD_REMINDER, costs); newCost.setRepeatable(true); newCost.setCostType(VariableCostType.ADDITIONAL); this.cost = newCost; @@ -83,7 +98,7 @@ public class SquadAbility extends StaticAbility implements OptionalAdditionalSou again = false; } } - ability.setCostsTag(SQUAD_ACTIVATION_VALUE_KEY,cost.getActivateCount()); + ability.setCostsTag(SQUAD_ACTIVATION_VALUE_KEY, cost.getActivateCount()); } @Override @@ -96,11 +111,12 @@ public class SquadAbility extends StaticAbility implements OptionalAdditionalSou @Override public String getRule() { - return "Squad "+cost.getText()+" (As an additional cost to cast this spell, you may pay "+ - cost.getText()+"any number of times. When this creature enters the battlefield, "+ - "create that many tokens that are copies of it.)"; + return "Squad " + cost.getText() + " (As an additional cost to cast this spell, you may pay " + + cost.getText() + "any number of times. When this creature enters the battlefield, " + + "create that many tokens that are copies of it.)"; } } + class SquadTriggerAbility extends EntersBattlefieldTriggeredAbility { public SquadTriggerAbility() { super(new SquadEffectETB()); @@ -110,6 +126,7 @@ class SquadTriggerAbility extends EntersBattlefieldTriggeredAbility { private SquadTriggerAbility(final SquadTriggerAbility ability) { super(ability); } + @Override public SquadTriggerAbility copy() { return new SquadTriggerAbility(this); @@ -117,9 +134,10 @@ class SquadTriggerAbility extends EntersBattlefieldTriggeredAbility { @Override public boolean checkInterveningIfClause(Game game) { - int squadCount = CardUtil.getSourceCostsTag(game, this, SquadAbility.SQUAD_ACTIVATION_VALUE_KEY,0); + int squadCount = CardUtil.getSourceCostsTag(game, this, SquadAbility.SQUAD_ACTIVATION_VALUE_KEY, 0); return (squadCount > 0); } + @Override public String getRule() { return "Squad (When this creature enters the battlefield, if its squad cost was paid, " @@ -144,7 +162,7 @@ class SquadEffectETB extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - int squadCount = CardUtil.getSourceCostsTag(game, source, SquadAbility.SQUAD_ACTIVATION_VALUE_KEY,0); + int squadCount = CardUtil.getSourceCostsTag(game, source, SquadAbility.SQUAD_ACTIVATION_VALUE_KEY, 0); CreateTokenCopySourceEffect effect = new CreateTokenCopySourceEffect(squadCount); return effect.apply(game, source); }