mirror of
https://github.com/magefree/mage.git
synced 2025-12-22 03:22:00 -08:00
implement [PIP] Craig Boone, Novac Guard
This commit is contained in:
parent
eb8e2fa5b9
commit
24dbba7b43
3 changed files with 260 additions and 0 deletions
114
Mage.Sets/src/mage/cards/c/CraigBooneNovacGuard.java
Normal file
114
Mage.Sets/src/mage/cards/c/CraigBooneNovacGuard.java
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AttacksWithCreaturesTriggeredAbility;
|
||||
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
|
||||
import mage.abilities.costs.common.PutCountersSourceCost;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.abilities.effects.common.DoWhenCostPaid;
|
||||
import mage.abilities.keyword.LifelinkAbility;
|
||||
import mage.abilities.keyword.ReachAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class CraigBooneNovacGuard extends CardImpl {
|
||||
|
||||
public CraigBooneNovacGuard(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{W}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.SOLDIER);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// Reach
|
||||
this.addAbility(ReachAbility.getInstance());
|
||||
|
||||
// Lifelink
|
||||
this.addAbility(LifelinkAbility.getInstance());
|
||||
|
||||
// One for My Baby -- Whenever you attack with two or more creatures, put two quest counters on Craig Boone, Novac Guard. When you do, Craig Boone deals damage equal to the number of quest counters on it to up to one target creature unless that creature's controller has Craig Boone deal that much damage to them.
|
||||
ReflexiveTriggeredAbility reflexive = new ReflexiveTriggeredAbility(new CraigBooneNovacGuardEffect(), false);
|
||||
reflexive.addTarget(new TargetCreaturePermanent(0, 1));
|
||||
this.addAbility(new AttacksWithCreaturesTriggeredAbility(
|
||||
new DoWhenCostPaid(
|
||||
reflexive,
|
||||
new PutCountersSourceCost(CounterType.QUEST.createInstance(2)),
|
||||
"", false
|
||||
), 2
|
||||
).withFlavorWord("One for my Baby"));
|
||||
}
|
||||
|
||||
private CraigBooneNovacGuard(final CraigBooneNovacGuard card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CraigBooneNovacGuard copy() {
|
||||
return new CraigBooneNovacGuard(this);
|
||||
}
|
||||
}
|
||||
|
||||
class CraigBooneNovacGuardEffect extends OneShotEffect {
|
||||
|
||||
CraigBooneNovacGuardEffect() {
|
||||
super(Outcome.Damage);
|
||||
staticText = "{this} deals damage equal to the number of quest counters on it "
|
||||
+ "to up to one target creature unless that creature's controller "
|
||||
+ "has {this} deal that much damage to them";
|
||||
}
|
||||
|
||||
private CraigBooneNovacGuardEffect(final CraigBooneNovacGuardEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CraigBooneNovacGuardEffect copy() {
|
||||
return new CraigBooneNovacGuardEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent targetPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
Permanent sourcePermanent = source.getSourcePermanentOrLKI(game);
|
||||
if (sourcePermanent == null || targetPermanent == null) {
|
||||
return false;
|
||||
}
|
||||
int amount = sourcePermanent.getCounters(game).getCount(CounterType.QUEST);
|
||||
Player playerChoosing = game.getPlayer(targetPermanent.getControllerId());
|
||||
if (playerChoosing != null && playerChoosing.chooseUse(
|
||||
Outcome.Neutral,
|
||||
"have " + amount + " damage be dealt to you instead of " + targetPermanent.getLogName() + "?",
|
||||
source,
|
||||
game)
|
||||
) {
|
||||
new DamageTargetEffect(amount)
|
||||
.setTargetPointer(new FixedTarget(playerChoosing.getId()))
|
||||
.apply(game, source);
|
||||
return true;
|
||||
}
|
||||
new DamageTargetEffect(amount)
|
||||
.setTargetPointer(getTargetPointer().copy())
|
||||
.apply(game, source);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -92,6 +92,7 @@ public final class Fallout extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Contagion Clasp", 229, Rarity.UNCOMMON, mage.cards.c.ContagionClasp.class));
|
||||
cards.add(new SetCardInfo("Contaminated Drink", 99, Rarity.UNCOMMON, mage.cards.c.ContaminatedDrink.class));
|
||||
cards.add(new SetCardInfo("Corpsejack Menace", 214, Rarity.UNCOMMON, mage.cards.c.CorpsejackMenace.class));
|
||||
cards.add(new SetCardInfo("Craig Boone, Novac Guard", 100, Rarity.UNCOMMON, mage.cards.c.CraigBooneNovacGuard.class));
|
||||
cards.add(new SetCardInfo("Crimson Caravaneer", 56, Rarity.UNCOMMON, mage.cards.c.CrimsonCaravaneer.class));
|
||||
cards.add(new SetCardInfo("Crucible of Worlds", 357, Rarity.MYTHIC, mage.cards.c.CrucibleOfWorlds.class));
|
||||
cards.add(new SetCardInfo("Crush Contraband", 158, Rarity.UNCOMMON, mage.cards.c.CrushContraband.class));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,145 @@
|
|||
package org.mage.test.cards.single.pip;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.player.TestPlayer;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public class CraigBooneNovacGuardTest extends CardTestPlayerBase {
|
||||
|
||||
/**
|
||||
* {@link mage.cards.c.CraigBooneNovacGuard Craig Boone, Novac Guard} {1}{R}{W}
|
||||
* Legendary Creature — Human Soldier
|
||||
* Reach, lifelink
|
||||
* One for My Baby — Whenever you attack with two or more creatures, put two quest counters on Craig Boone, Novac Guard. When you do, Craig Boone deals damage equal to the number of quest counters on it to up to one target creature unless that creature’s controller has Craig Boone deal that much damage to them.
|
||||
* 3/3
|
||||
*/
|
||||
private static final String craig = "Craig Boone, Novac Guard";
|
||||
|
||||
@Test
|
||||
public void test_Trigger_Simple_DamageCreature() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, craig);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Indomitable Ancients");
|
||||
|
||||
attack(1, playerA, "Memnite", playerB);
|
||||
attack(1, playerA, "Elite Vanguard", playerB);
|
||||
|
||||
addTarget(playerA, "Indomitable Ancients");
|
||||
setChoice(playerB, false); // choose to not have damage dealt to them
|
||||
|
||||
setStopAt(1, PhaseStep.END_COMBAT);
|
||||
execute();
|
||||
|
||||
assertDamageReceived(playerB, "Indomitable Ancients", 2);
|
||||
assertLife(playerA, 20 + 2);
|
||||
assertLife(playerB, 20 - 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Trigger_Simple_DamagePlayer() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, craig);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Indomitable Ancients");
|
||||
|
||||
attack(1, playerA, "Memnite", playerB);
|
||||
attack(1, playerA, "Elite Vanguard", playerB);
|
||||
|
||||
addTarget(playerA, "Indomitable Ancients");
|
||||
setChoice(playerB, true); // choose to not have damage dealt to them
|
||||
|
||||
setStopAt(1, PhaseStep.END_COMBAT);
|
||||
execute();
|
||||
|
||||
assertDamageReceived(playerB, "Indomitable Ancients", 0);
|
||||
assertLife(playerA, 20 + 2);
|
||||
assertLife(playerB, 20 - 3 - 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Trigger_Simple_NoTarget_NoDamage() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, craig);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Indomitable Ancients");
|
||||
|
||||
attack(1, playerA, "Memnite", playerB);
|
||||
attack(1, playerA, "Elite Vanguard", playerB);
|
||||
|
||||
addTarget(playerA, TestPlayer.TARGET_SKIP);
|
||||
// No one has a choice to make
|
||||
|
||||
setStopAt(1, PhaseStep.END_COMBAT);
|
||||
execute();
|
||||
|
||||
assertDamageReceived(playerB, "Indomitable Ancients", 0);
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 20 - 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Trigger_DiesBeforeResolve() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, craig);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Indomitable Ancients");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
|
||||
addCard(Zone.HAND, playerB, "Doom Blade");
|
||||
|
||||
attack(1, playerA, "Memnite", playerB);
|
||||
attack(1, playerA, "Elite Vanguard", playerB);
|
||||
|
||||
castSpell(1, PhaseStep.DECLARE_ATTACKERS, playerB, "Doom Blade", craig);
|
||||
// The attack trigger is there, but since counters can not be put on Craig, no Reflexive Trigger
|
||||
|
||||
setStopAt(1, PhaseStep.END_COMBAT);
|
||||
execute();
|
||||
|
||||
assertDamageReceived(playerB, "Indomitable Ancients", 0);
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 20 - 3);
|
||||
assertGraveyardCount(playerA, craig, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Trigger_DiesBeforeReflexiveResolve() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, craig);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Indomitable Ancients");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
|
||||
addCard(Zone.HAND, playerB, "Doom Blade");
|
||||
|
||||
attack(1, playerA, "Memnite", playerB);
|
||||
attack(1, playerA, "Elite Vanguard", playerB);
|
||||
|
||||
waitStackResolved(1, PhaseStep.DECLARE_ATTACKERS, playerB, true);
|
||||
addTarget(playerA, "Indomitable Ancients");
|
||||
setChoice(playerB, true); // choose to not have damage dealt to them
|
||||
castSpell(1, PhaseStep.DECLARE_ATTACKERS, playerB, "Doom Blade", craig);
|
||||
|
||||
setStopAt(1, PhaseStep.END_COMBAT);
|
||||
execute();
|
||||
|
||||
assertDamageReceived(playerB, "Indomitable Ancients", 0);
|
||||
assertLife(playerA, 20 + 2);
|
||||
assertLife(playerB, 20 - 3 - 2); // Still took 2 Damage when the reflexive trigger
|
||||
assertGraveyardCount(playerA, craig, 1);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue