implement [PIP] Thrill-Kill Disciple

This commit is contained in:
Susucre 2024-05-01 18:34:30 +02:00
parent 2c6bb21a9c
commit a60f01a99f
4 changed files with 122 additions and 9 deletions

View file

@ -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<Cost> 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);
}
}

View file

@ -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));

View file

@ -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);
}
}

View file

@ -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<Cost> wrapSingleCost(Cost cost) {
Costs<Cost> costs = new CostsImpl<>();
costs.add(cost);
return costs;
}
public SquadAbility(Cost cost) {
this(wrapSingleCost(cost));
}
public SquadAbility(Costs<Cost> 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<Cost> 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()+" <i>(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.)</i>";
return "Squad " + cost.getText() + " <i>(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.)</i>";
}
}
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 <i>(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);
}