mirror of
https://github.com/magefree/mage.git
synced 2025-12-22 11:32:00 -08:00
implement [BLB] Starseer Mentor
This commit is contained in:
parent
233d714e00
commit
3fdeb8c2fc
8 changed files with 421 additions and 152 deletions
|
|
@ -1,8 +1,8 @@
|
|||
package mage.cards.r;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.condition.common.YouLostLifeCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
|
|
@ -18,21 +18,22 @@ import mage.game.permanent.Permanent;
|
|||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.target.common.TargetOpponentsCreaturePermanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.watchers.common.PlayerLostLifeWatcher;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Styxo
|
||||
*/
|
||||
public final class RevengeStarWars extends CardImpl {
|
||||
|
||||
private static final Condition condition = new YouLostLifeCondition();
|
||||
|
||||
public RevengeStarWars(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}");
|
||||
|
||||
// Target creature you control gets +4/+0 until end of turn before it fights if you lost life this turn.
|
||||
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
|
||||
new RevengeEffect(),
|
||||
LostLifeCondition.instance,
|
||||
new RevengeEffect(), condition,
|
||||
"Target creature you control gets +4/+0 until end of turn before it fights if you lost life this turn"));
|
||||
|
||||
// Target creature you control fights target creature an opponent controls.
|
||||
|
|
@ -52,22 +53,6 @@ public final class RevengeStarWars extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
enum LostLifeCondition implements Condition {
|
||||
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
PlayerLostLifeWatcher watcher = game.getState().getWatcher(PlayerLostLifeWatcher.class);
|
||||
UUID player = source.getControllerId();
|
||||
if (watcher != null && player != null) {
|
||||
return watcher.getLifeLost(player) > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class RevengeEffect extends OneShotEffect {
|
||||
|
||||
RevengeEffect() {
|
||||
|
|
|
|||
96
Mage.Sets/src/mage/cards/s/StarseerMentor.java
Normal file
96
Mage.Sets/src/mage/cards/s/StarseerMentor.java
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.condition.OrCondition;
|
||||
import mage.abilities.condition.common.YouGainedLifeCondition;
|
||||
import mage.abilities.condition.common.YouLostLifeCondition;
|
||||
import mage.abilities.costs.OrCost;
|
||||
import mage.abilities.costs.common.DiscardCardCost;
|
||||
import mage.abilities.costs.common.SacrificeTargetCost;
|
||||
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
||||
import mage.abilities.effects.common.DoUnlessTargetPlayerOrTargetsControllerPaysEffect;
|
||||
import mage.abilities.effects.common.LoseLifeTargetEffect;
|
||||
import mage.abilities.hint.ConditionHint;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.VigilanceAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.TargetController;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.target.common.TargetOpponent;
|
||||
import mage.watchers.common.PlayerGainedLifeWatcher;
|
||||
import mage.watchers.common.PlayerLostLifeWatcher;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class StarseerMentor extends CardImpl {
|
||||
|
||||
private static final Condition condition =
|
||||
new OrCondition(
|
||||
"if you gained or lost life this turn",
|
||||
new YouGainedLifeCondition(),
|
||||
new YouLostLifeCondition()
|
||||
);
|
||||
private static final Hint hint = new ConditionHint(condition);
|
||||
|
||||
private static final FilterControlledPermanent filter = new FilterControlledPermanent("nonland permanent");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.not(CardType.LAND.getPredicate()));
|
||||
}
|
||||
|
||||
public StarseerMentor(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{B}");
|
||||
|
||||
this.subtype.add(SubType.BAT);
|
||||
this.subtype.add(SubType.WARLOCK);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(5);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Vigilance
|
||||
this.addAbility(VigilanceAbility.getInstance());
|
||||
|
||||
// At the beginning of your end step, if you gained or lost life this turn, target opponent loses 3 life unless they sacrifice a nonland permanent or discard a card.
|
||||
Ability ability = new ConditionalInterveningIfTriggeredAbility(
|
||||
new BeginningOfEndStepTriggeredAbility(
|
||||
new DoUnlessTargetPlayerOrTargetsControllerPaysEffect(
|
||||
new LoseLifeTargetEffect(3),
|
||||
new OrCost(
|
||||
"sacrifice a nonland permanent or discard a card",
|
||||
new SacrificeTargetCost(filter),
|
||||
new DiscardCardCost()
|
||||
),
|
||||
"Sacrifice a nonland permanent or discard a card to prevent losing 3 life?"
|
||||
), TargetController.YOU, false
|
||||
), condition, "At the beginning of your end step, if you gained or lost life this turn, "
|
||||
+ "target opponent loses 3 life unless they sacrifice a nonland permanent or discard a card."
|
||||
);
|
||||
ability.addTarget(new TargetOpponent());
|
||||
ability.addWatcher(new PlayerGainedLifeWatcher());
|
||||
ability.addWatcher(new PlayerLostLifeWatcher());
|
||||
ability.addHint(hint);
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private StarseerMentor(final StarseerMentor card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StarseerMentor copy() {
|
||||
return new StarseerMentor(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,30 +3,30 @@ package mage.cards.t;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.OrCost;
|
||||
import mage.abilities.costs.common.DiscardCardCost;
|
||||
import mage.abilities.costs.common.SacrificeTargetCost;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.DoUnlessTargetPlayerOrTargetsControllerPaysEffect;
|
||||
import mage.abilities.effects.common.LoseLifeTargetEffect;
|
||||
import mage.abilities.effects.common.UntapSourceEffect;
|
||||
import mage.abilities.keyword.MenaceAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.ModalDoubleFacedCard;
|
||||
import mage.choices.Choice;
|
||||
import mage.choices.ChoiceImpl;
|
||||
import mage.constants.*;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.PermanentToken;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.TargetPlayer;
|
||||
import mage.target.common.TargetSacrifice;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
|
@ -34,6 +34,12 @@ import java.util.UUID;
|
|||
*/
|
||||
public final class TergridGodOfFright extends ModalDoubleFacedCard {
|
||||
|
||||
private static final FilterControlledPermanent filter = new FilterControlledPermanent("nonland permanent");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.not(CardType.LAND.getPredicate()));
|
||||
}
|
||||
|
||||
public TergridGodOfFright(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(
|
||||
ownerId, setInfo,
|
||||
|
|
@ -58,7 +64,15 @@ public final class TergridGodOfFright extends ModalDoubleFacedCard {
|
|||
// Legendary Artifact
|
||||
// {T}: Target player loses 3 life unless they sacrifice a nonland permanent or discard a card.
|
||||
Ability tergridsLaternActivatedAbility = new SimpleActivatedAbility(
|
||||
new TergridsLaternEffect(), new TapSourceCost()
|
||||
new DoUnlessTargetPlayerOrTargetsControllerPaysEffect(
|
||||
new LoseLifeTargetEffect(3),
|
||||
new OrCost(
|
||||
"sacrifice a nonland permanent or discard a card",
|
||||
new SacrificeTargetCost(filter),
|
||||
new DiscardCardCost()
|
||||
),
|
||||
"Sacrifice a nonland permanent or discard a card to prevent losing 3 life?"
|
||||
), new TapSourceCost()
|
||||
);
|
||||
tergridsLaternActivatedAbility.addTarget(new TargetPlayer());
|
||||
this.getRightHalfCard().addAbility(tergridsLaternActivatedAbility);
|
||||
|
|
@ -165,70 +179,4 @@ class TergridGodOfFrightEffect extends OneShotEffect {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class TergridsLaternEffect extends OneShotEffect {
|
||||
|
||||
private static final String SACRIFICE_CHOICE = "Sacrifice a nonland permanent";
|
||||
private static final String DISCARD_CHOICE = "Discard a card";
|
||||
private static final String LIFE_LOSS_CHOICE = "Lose 3 life";
|
||||
|
||||
public TergridsLaternEffect() {
|
||||
super(Outcome.Detriment);
|
||||
staticText = "Target player loses 3 life unless they sacrifice a nonland permanent or discard a card";
|
||||
}
|
||||
|
||||
private TergridsLaternEffect(final TergridsLaternEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TergridsLaternEffect copy() {
|
||||
return new TergridsLaternEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player targetedPlayer = game.getPlayer(source.getTargets().getFirstTarget());
|
||||
if (targetedPlayer == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// AI hint to discard/sacrifice before die
|
||||
Outcome aiOutcome = (targetedPlayer.getLife() <= 3 * 2) ? Outcome.Benefit : Outcome.Detriment;
|
||||
|
||||
Set<String> choiceSet = new HashSet<>();
|
||||
if (game.getBattlefield().count(StaticFilters.FILTER_CONTROLLED_PERMANENT_NON_LAND, targetedPlayer.getId(), source, game) > 0) {
|
||||
choiceSet.add(SACRIFICE_CHOICE);
|
||||
}
|
||||
if (targetedPlayer.getHand().size() > 0) {
|
||||
choiceSet.add(DISCARD_CHOICE);
|
||||
}
|
||||
choiceSet.add(LIFE_LOSS_CHOICE);
|
||||
String chosen;
|
||||
if (choiceSet.size() > 1) {
|
||||
Choice choice = new ChoiceImpl(true);
|
||||
choice.setChoices(choiceSet);
|
||||
targetedPlayer.choose(aiOutcome, choice, game);
|
||||
chosen = choice.getChoice();
|
||||
if (chosen == null) {
|
||||
// on disconnect
|
||||
chosen = LIFE_LOSS_CHOICE;
|
||||
}
|
||||
} else {
|
||||
chosen = LIFE_LOSS_CHOICE;
|
||||
}
|
||||
switch (chosen) {
|
||||
case SACRIFICE_CHOICE:
|
||||
TargetSacrifice target = new TargetSacrifice(StaticFilters.FILTER_CONTROLLED_PERMANENT_NON_LAND);
|
||||
targetedPlayer.choose(Outcome.Sacrifice, target, source, game);
|
||||
Permanent chosenLand = game.getPermanent(target.getFirstTarget());
|
||||
return chosenLand != null && chosenLand.sacrifice(source, game);
|
||||
case DISCARD_CHOICE:
|
||||
return targetedPlayer.discard(1, false, false, source, game).size() > 0;
|
||||
case LIFE_LOSS_CHOICE:
|
||||
return targetedPlayer.loseLife(3, game, source, false) > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,8 +2,12 @@ package mage.cards.t;
|
|||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.costs.OrCost;
|
||||
import mage.abilities.costs.common.DiscardCardCost;
|
||||
import mage.abilities.costs.common.SacrificeTargetCost;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.abilities.effects.common.DoUnlessTargetPlayerOrTargetsControllerPaysEffect;
|
||||
import mage.abilities.effects.common.LoseLifeTargetEffect;
|
||||
import mage.abilities.keyword.EnchantAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
|
@ -11,21 +15,23 @@ import mage.constants.CardType;
|
|||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.TargetController;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.target.TargetPlayer;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author LevelX2
|
||||
* @author LevelX2, Susucr
|
||||
*/
|
||||
public final class TormentOfScarabs extends CardImpl {
|
||||
|
||||
private static final FilterControlledPermanent filter = new FilterControlledPermanent("nonland permanent");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.not(CardType.LAND.getPredicate()));
|
||||
}
|
||||
|
||||
public TormentOfScarabs(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}");
|
||||
|
||||
|
|
@ -40,7 +46,15 @@ public final class TormentOfScarabs extends CardImpl {
|
|||
|
||||
// At the beginning of enchanted player's upkeep, that player loses 3 life unless they sacrifice a nonland permanent or discards a card.
|
||||
this.addAbility(new BeginningOfUpkeepTriggeredAbility(
|
||||
new TormentOfScarabsEffect(), TargetController.ENCHANTED, false
|
||||
new DoUnlessTargetPlayerOrTargetsControllerPaysEffect(
|
||||
new LoseLifeTargetEffect(3),
|
||||
new OrCost(
|
||||
"sacrifice a nonland permanent or discard a card",
|
||||
new SacrificeTargetCost(filter),
|
||||
new DiscardCardCost()
|
||||
),
|
||||
"Sacrifice a nonland permanent or discard a card to prevent losing 3 life?"
|
||||
), TargetController.ENCHANTED, false
|
||||
));
|
||||
}
|
||||
|
||||
|
|
@ -52,48 +66,4 @@ public final class TormentOfScarabs extends CardImpl {
|
|||
public TormentOfScarabs copy() {
|
||||
return new TormentOfScarabs(this);
|
||||
}
|
||||
}
|
||||
|
||||
class TormentOfScarabsEffect extends OneShotEffect {
|
||||
|
||||
TormentOfScarabsEffect() {
|
||||
super(Outcome.LoseLife);
|
||||
this.staticText = "that player loses 3 life unless they sacrifice a nonland permanent or discard a card";
|
||||
}
|
||||
|
||||
private TormentOfScarabsEffect(final TormentOfScarabsEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TormentOfScarabsEffect copy() {
|
||||
return new TormentOfScarabsEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player enchantedPlayer = game.getPlayer(getTargetPointer().getFirst(game, source));
|
||||
if (enchantedPlayer == null) {
|
||||
return false;
|
||||
}
|
||||
int permanents = game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_NON_LAND, enchantedPlayer.getId(), game);
|
||||
if (permanents > 0 && enchantedPlayer.chooseUse(outcome, "Sacrifice a nonland permanent?",
|
||||
"Otherwise you have to discard a card or lose 3 life.", "Sacrifice", "Discard or life loss", source, game)) {
|
||||
Target target = new TargetPermanent(StaticFilters.FILTER_CONTROLLED_PERMANENT_NON_LAND);
|
||||
if (enchantedPlayer.choose(outcome, target, source, game)) {
|
||||
Permanent permanent = game.getPermanent(target.getFirstTarget());
|
||||
if (permanent != null) {
|
||||
permanent.sacrifice(source, game);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!enchantedPlayer.getHand().isEmpty() && enchantedPlayer.chooseUse(outcome, "Discard a card?",
|
||||
"Otherwise you lose 3 life.", "Discard", "Lose 3 life", source, game)) {
|
||||
enchantedPlayer.discardOne(false, false, source, game);
|
||||
return true;
|
||||
}
|
||||
enchantedPlayer.loseLife(3, game, source, false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
|
||||
package mage.cards.t;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
|
||||
|
|
@ -22,8 +21,9 @@ import mage.target.Target;
|
|||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public final class TormentOfVenom extends CardImpl {
|
||||
|
|
@ -46,6 +46,7 @@ public final class TormentOfVenom extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: simplify using DoUnlessTargetPlayerOrTargetsControllerPaysEffect and OrCost
|
||||
class TormentOfVenomEffect extends OneShotEffect {
|
||||
|
||||
TormentOfVenomEffect() {
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ public final class Bloomburrow extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Shrike Force", 31, Rarity.UNCOMMON, mage.cards.s.ShrikeForce.class));
|
||||
cards.add(new SetCardInfo("Splash Lasher", 73, Rarity.UNCOMMON, mage.cards.s.SplashLasher.class));
|
||||
cards.add(new SetCardInfo("Stargaze", 114, Rarity.UNCOMMON, mage.cards.s.Stargaze.class));
|
||||
cards.add(new SetCardInfo("Starseer Mentor", 233, Rarity.UNCOMMON, mage.cards.s.StarseerMentor.class));
|
||||
cards.add(new SetCardInfo("Steampath Charger", 153, Rarity.COMMON, mage.cards.s.SteampathCharger.class));
|
||||
cards.add(new SetCardInfo("Stormcatch Mentor", 234, Rarity.UNCOMMON, mage.cards.s.StormcatchMentor.class));
|
||||
cards.add(new SetCardInfo("Sunshower Druid", 195, Rarity.COMMON, mage.cards.s.SunshowerDruid.class));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,231 @@
|
|||
package org.mage.test.cards.single.blb;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public class StarseerMentorTest extends CardTestPlayerBase {
|
||||
|
||||
/**
|
||||
* {@link mage.cards.s.StarseerMentor Starseer Mentor} {3}{W}{B}
|
||||
* Creature — Bat Warlock
|
||||
* Flying, vigilance
|
||||
* At the beginning of your end step, if you gained or lost life this turn, target opponent loses 3 life unless they sacrifice a nonland permanent or discard a card.
|
||||
* 3/5
|
||||
*/
|
||||
private static final String mentor = "Starseer Mentor";
|
||||
|
||||
@Test
|
||||
public void test_NoTrigger() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, mentor);
|
||||
|
||||
setStopAt(2, PhaseStep.UPKEEP);
|
||||
execute();
|
||||
|
||||
assertLife(playerB, 20);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_LifeGain_Trigger() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, mentor);
|
||||
addCard(Zone.HAND, playerA, "Angel of Mercy"); // etb gains 5 life
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Angel of Mercy");
|
||||
|
||||
addTarget(playerA, playerB); // target for the trigger.
|
||||
// playerB has no way to pay for the cost, so no choice.
|
||||
|
||||
setStopAt(2, PhaseStep.UPKEEP);
|
||||
execute();
|
||||
|
||||
assertLife(playerB, 20 - 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_LifeLost_Trigger() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, mentor);
|
||||
addCard(Zone.HAND, playerA, "Serpent Warrior"); // etb loses 3 life
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Serpent Warrior");
|
||||
|
||||
addTarget(playerA, playerB); // target for the trigger.
|
||||
// playerB has no way to pay for the cost, so no choice.
|
||||
|
||||
setStopAt(2, PhaseStep.UPKEEP);
|
||||
execute();
|
||||
|
||||
assertLife(playerB, 20 - 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Trigger_CanDiscard_AndDiscard() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, mentor);
|
||||
addCard(Zone.HAND, playerA, "Angel of Mercy"); // etb gains 5 life
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
|
||||
addCard(Zone.HAND, playerB, "Abandon Hope");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Angel of Mercy");
|
||||
|
||||
addTarget(playerA, playerB); // target for the trigger.
|
||||
setChoice(playerB, true); // choose to pay the cost to not lose life
|
||||
setChoice(playerB, "Abandon Hope"); // Choose to discard
|
||||
|
||||
setStopAt(2, PhaseStep.UPKEEP);
|
||||
execute();
|
||||
|
||||
assertLife(playerB, 20);
|
||||
assertGraveyardCount(playerB, "Abandon Hope", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Trigger_CanDiscard_AndDontDiscard() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, mentor);
|
||||
addCard(Zone.HAND, playerA, "Angel of Mercy"); // etb gains 5 life
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
|
||||
addCard(Zone.HAND, playerB, "Abandon Hope");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Angel of Mercy");
|
||||
|
||||
addTarget(playerA, playerB); // target for the trigger.
|
||||
setChoice(playerB, false); // choose to not pay the cost to not lose life
|
||||
|
||||
setStopAt(2, PhaseStep.UPKEEP);
|
||||
execute();
|
||||
|
||||
assertLife(playerB, 20 - 3);
|
||||
assertHandCount(playerB, "Abandon Hope", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Trigger_CanSacrifice_AndSacrifice() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, mentor);
|
||||
addCard(Zone.HAND, playerA, "Angel of Mercy"); // etb gains 5 life
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Elite Vanguard");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Angel of Mercy");
|
||||
|
||||
addTarget(playerA, playerB); // target for the trigger.
|
||||
setChoice(playerB, true); // choose to pay the cost to not lose life
|
||||
setChoice(playerB, "Elite Vanguard"); // Choose to sacrifice
|
||||
|
||||
setStopAt(2, PhaseStep.UPKEEP);
|
||||
execute();
|
||||
|
||||
assertLife(playerB, 20);
|
||||
assertGraveyardCount(playerB, "Elite Vanguard", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Trigger_CanSacrifice_AndDontSacrifice() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, mentor);
|
||||
addCard(Zone.HAND, playerA, "Angel of Mercy"); // etb gains 5 life
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Elite Vanguard");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Angel of Mercy");
|
||||
|
||||
addTarget(playerA, playerB); // target for the trigger.
|
||||
setChoice(playerB, false); // choose to not pay the cost to not lose life
|
||||
|
||||
setStopAt(2, PhaseStep.UPKEEP);
|
||||
execute();
|
||||
|
||||
assertLife(playerB, 20 - 3);
|
||||
assertPermanentCount(playerB, "Elite Vanguard", 1);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void test_Trigger_CanSacrificeOrDiscard_AndSacrifice() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, mentor);
|
||||
addCard(Zone.HAND, playerA, "Angel of Mercy"); // etb gains 5 life
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Elite Vanguard");
|
||||
addCard(Zone.HAND, playerB, "Abandon Hope");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Angel of Mercy");
|
||||
|
||||
addTarget(playerA, playerB); // target for the trigger.
|
||||
setChoice(playerB, true); // choose to pay the cost to not lose life
|
||||
setChoice(playerB, true); // choose to pay the sacrifice cost
|
||||
setChoice(playerB, "Elite Vanguard"); // Choose to sacrifice
|
||||
|
||||
setStopAt(2, PhaseStep.UPKEEP);
|
||||
execute();
|
||||
|
||||
assertLife(playerB, 20);
|
||||
assertGraveyardCount(playerB, "Elite Vanguard", 1);
|
||||
assertHandCount(playerB, "Abandon Hope", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Trigger_CanSacrificeOrDiscard_AndDiscard() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, mentor);
|
||||
addCard(Zone.HAND, playerA, "Angel of Mercy"); // etb gains 5 life
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Elite Vanguard");
|
||||
addCard(Zone.HAND, playerB, "Abandon Hope");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Angel of Mercy");
|
||||
|
||||
addTarget(playerA, playerB); // target for the trigger.
|
||||
setChoice(playerB, true); // choose to pay the cost to not lose life
|
||||
setChoice(playerB, false); // choose to not pay the sacrifice cost (so will discard)
|
||||
setChoice(playerB, "Abandon Hope"); // Choose to discard
|
||||
|
||||
setStopAt(2, PhaseStep.UPKEEP);
|
||||
execute();
|
||||
|
||||
assertLife(playerB, 20);
|
||||
assertPermanentCount(playerB, "Elite Vanguard", 1);
|
||||
assertGraveyardCount(playerB, "Abandon Hope", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Trigger_CanSacrificeOrDiscard_AndDontPay() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, mentor);
|
||||
addCard(Zone.HAND, playerA, "Angel of Mercy"); // etb gains 5 life
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Elite Vanguard");
|
||||
addCard(Zone.HAND, playerB, "Abandon Hope");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Angel of Mercy");
|
||||
|
||||
addTarget(playerA, playerB); // target for the trigger.
|
||||
setChoice(playerB, false); // choose to not pay the cost to not lose life
|
||||
|
||||
setStopAt(2, PhaseStep.UPKEEP);
|
||||
execute();
|
||||
|
||||
assertLife(playerB, 20 - 3);
|
||||
assertPermanentCount(playerB, "Elite Vanguard", 1);
|
||||
assertHandCount(playerB, "Abandon Hope", 1);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package mage.abilities.condition.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.IntCompareCondition;
|
||||
import mage.constants.ComparisonType;
|
||||
import mage.game.Game;
|
||||
import mage.watchers.common.PlayerLostLifeWatcher;
|
||||
|
||||
/**
|
||||
* Needs PlayerLostLifeWatcher to work
|
||||
*
|
||||
* @author Susucr
|
||||
*/
|
||||
public class YouLostLifeCondition extends IntCompareCondition {
|
||||
|
||||
/**
|
||||
* "if you lost life this turn"
|
||||
*/
|
||||
public YouLostLifeCondition() {
|
||||
super(ComparisonType.MORE_THAN, 0);
|
||||
}
|
||||
|
||||
public YouLostLifeCondition(ComparisonType type, int value) {
|
||||
super(type, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getInputValue(Game game, Ability source) {
|
||||
PlayerLostLifeWatcher watcher = game.getState().getWatcher(PlayerLostLifeWatcher.class);
|
||||
return watcher == null ? 0 : watcher.getLifeLost(source.getControllerId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "if you lost " + (value == 0 ? "" : (value + 1) + " or more ") + "life this turn";
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue