mirror of
https://github.com/magefree/mage.git
synced 2025-12-21 19:11:59 -08:00
This commit is contained in:
parent
1bebc62902
commit
ccb1a0aeed
3 changed files with 181 additions and 16 deletions
|
|
@ -69,7 +69,7 @@ class ChangeOfPlansEffect extends OneShotEffect {
|
||||||
.getTargetPointer()
|
.getTargetPointer()
|
||||||
.getTargets(game, source)
|
.getTargets(game, source)
|
||||||
.stream()
|
.stream()
|
||||||
.map(game::getPermanent)
|
.map(game::getPermanentOrLKIBattlefield)
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
if (permanents.isEmpty()) {
|
if (permanents.isEmpty()) {
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ public final class SpymastersVault extends CardImpl {
|
||||||
|
|
||||||
// {T}: Add {B}.
|
// {T}: Add {B}.
|
||||||
this.addAbility(new BlackManaAbility());
|
this.addAbility(new BlackManaAbility());
|
||||||
|
|
||||||
// {B}, {T}: Target creature you control connives X, where X is the number of creatures that died this turn.
|
// {B}, {T}: Target creature you control connives X, where X is the number of creatures that died this turn.
|
||||||
Ability ability = new SimpleActivatedAbility(new SpymastersVaultEffect(), new ManaCostsImpl<>("{B}"));
|
Ability ability = new SimpleActivatedAbility(new SpymastersVaultEffect(), new ManaCostsImpl<>("{B}"));
|
||||||
ability.addCost(new TapSourceCost());
|
ability.addCost(new TapSourceCost());
|
||||||
|
|
@ -80,7 +81,7 @@ class SpymastersVaultEffect extends OneShotEffect {
|
||||||
if (deaths < 1) {
|
if (deaths < 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
Permanent permanent = game.getPermanentOrLKIBattlefield(source.getFirstTarget());
|
||||||
if (permanent == null) {
|
if (permanent == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,23 @@ package org.mage.test.cards.abilities.keywords;
|
||||||
import mage.constants.PhaseStep;
|
import mage.constants.PhaseStep;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.mage.test.player.TestPlayer;
|
||||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Alex-Vasile
|
* @author Alex-Vasile, JayDi85
|
||||||
* To have a creature connive, draw a card, then discard a card. If you discarded a nonland card, put a +1/+1 counter on that creature.
|
* <p>
|
||||||
|
* Once an ability that causes a creature to connive begins to resolve, no player may take any other actions until it's done. Notably, opponents can't try to remove the conniving creature after you discard cards but before it receives +1/+1 counters, if any.
|
||||||
|
* (2024-06-07)
|
||||||
|
* <p>
|
||||||
|
* To have a creature connive, draw a card, then discard a card. If you discarded a nonland card,
|
||||||
|
* put a +1/+1 counter on that creature.
|
||||||
|
* <p>
|
||||||
|
* If no cards are discarded, most likely because that player's hand is empty and an effect says they can't draw cards, the conniving creature does not receive any +1/+1 counters.
|
||||||
|
* (2024-06-07)
|
||||||
|
* <p>
|
||||||
|
* If a resolving spell or ability instructs a specific creature to connive but that creature has left the battlefield, the creature still connives, although you can't put any +1/+1 counters on it. Abilities that trigger "when [that creature] connives" will trigger.
|
||||||
|
* (2024-06-07)
|
||||||
*/
|
*/
|
||||||
public class ConniveTest extends CardTestPlayerBase {
|
public class ConniveTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
|
@ -16,7 +28,7 @@ public class ConniveTest extends CardTestPlayerBase {
|
||||||
* Creature should not get a +1/+1 counter.
|
* Creature should not get a +1/+1 counter.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void conniveDiscardLand() {
|
public void test_OnLandDiscard() {
|
||||||
// P/T : 1/2
|
// P/T : 1/2
|
||||||
// {3}: Hypnotic Grifter connives
|
// {3}: Hypnotic Grifter connives
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Hypnotic Grifter");
|
addCard(Zone.BATTLEFIELD, playerA, "Hypnotic Grifter");
|
||||||
|
|
@ -41,7 +53,7 @@ public class ConniveTest extends CardTestPlayerBase {
|
||||||
* Creature should get a +1/+1 counter.
|
* Creature should get a +1/+1 counter.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void conniveDiscardCreature() {
|
public void test_OnCreatureDiscard() {
|
||||||
// P/T : 1/2
|
// P/T : 1/2
|
||||||
// {3}: Hypnotic Grifter connives
|
// {3}: Hypnotic Grifter connives
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Hypnotic Grifter");
|
addCard(Zone.BATTLEFIELD, playerA, "Hypnotic Grifter");
|
||||||
|
|
@ -66,7 +78,7 @@ public class ConniveTest extends CardTestPlayerBase {
|
||||||
* Creature should get a +1/+1 counter and the madness card gets played.
|
* Creature should get a +1/+1 counter and the madness card gets played.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void conniveMadness() {
|
public void test_Madness() {
|
||||||
// P/T : 1/2
|
// P/T : 1/2
|
||||||
// {3}: Hypnotic Grifter connives
|
// {3}: Hypnotic Grifter connives
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Hypnotic Grifter");
|
addCard(Zone.BATTLEFIELD, playerA, "Hypnotic Grifter");
|
||||||
|
|
@ -95,10 +107,10 @@ public class ConniveTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obscura Confluence allows you to connive a creature you don't control.
|
* Obscura Confluence allows you to connive a creature you don't control.
|
||||||
* It's the only card that causes you to coonnive a creature you don't control.
|
* It's the only card that causes you to connive a creature you don't control.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void conniveNonControlledCreature() {
|
public void test_OpponentCreature() {
|
||||||
// Choose three. You may choose the same mode more than once.
|
// Choose three. You may choose the same mode more than once.
|
||||||
//• Until end of turn, target creature loses all abilities and has base power and toughness 1/1.
|
//• Until end of turn, target creature loses all abilities and has base power and toughness 1/1.
|
||||||
//• Target creature connives. (Draw a card, then discard a card. If you discarded a nonland card, put a +1/+1 counter on that creature.)
|
//• Target creature connives. (Draw a card, then discard a card. If you discarded a nonland card, put a +1/+1 counter on that creature.)
|
||||||
|
|
@ -135,16 +147,16 @@ public class ConniveTest extends CardTestPlayerBase {
|
||||||
/**
|
/**
|
||||||
* Reported bug: https://github.com/magefree/mage/issues/9252
|
* Reported bug: https://github.com/magefree/mage/issues/9252
|
||||||
* Connive fizzles if the creature that connived leaves the battlefield before connive resolves.
|
* Connive fizzles if the creature that connived leaves the battlefield before connive resolves.
|
||||||
*
|
* <p>
|
||||||
* Ruling:
|
* Ruling:
|
||||||
* If a resolving spell or ability instructs a specific creature to connive but that creature has left the battlefield,
|
* If a resolving spell or ability instructs a specific creature to connive but that creature has left the battlefield,
|
||||||
* the creature still connives.
|
* the creature still connives.
|
||||||
* If you discard a nonland card this way, you won’t put a +1/+1 counter on anything.
|
* If you discard a nonland card this way, you won’t put a +1/+1 counter on anything.
|
||||||
* Abilities that trigger “when [that creature] connives” will trigger.
|
* Abilities that trigger “when [that creature] connives” will trigger.
|
||||||
* (2022-04-29)
|
* (2022-04-29)
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void conniveDoesNotFizzle() {
|
public void test_LKI_PsychicPickpocket() {
|
||||||
// {4}{U}
|
// {4}{U}
|
||||||
// 3/2
|
// 3/2
|
||||||
// When Psychic Pickpocket enters the battlefield, it connives.
|
// When Psychic Pickpocket enters the battlefield, it connives.
|
||||||
|
|
@ -175,4 +187,156 @@ public class ConniveTest extends CardTestPlayerBase {
|
||||||
assertGraveyardCount(playerA, "Psychic Pickpocket", 1); // Destroyed by Lightning Bolt
|
assertGraveyardCount(playerA, "Psychic Pickpocket", 1); // Destroyed by Lightning Bolt
|
||||||
assertGraveyardCount(playerB, "Lightning Bolt", 1);
|
assertGraveyardCount(playerB, "Lightning Bolt", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_LKI_Source_Normal() {
|
||||||
|
// When Raffine’s Silencer enters, it connives.
|
||||||
|
addCard(Zone.HAND, playerA, "Raffine's Silencer");// {2}{B}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
|
||||||
|
addCard(Zone.HAND, playerA, "Grizzly Bears", 1);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Raffine's Silencer");
|
||||||
|
setChoice(playerA, "Grizzly Bears"); // to discard
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPowerToughness(playerA, "Raffine's Silencer", 1 + 1, 1 + 1);
|
||||||
|
assertGraveyardCount(playerA, "Grizzly Bears", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_LKI_Source_Dies() {
|
||||||
|
// When Raffine’s Silencer enters, it connives.
|
||||||
|
addCard(Zone.HAND, playerA, "Raffine's Silencer");// {2}{B}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
|
||||||
|
addCard(Zone.HAND, playerA, "Grizzly Bears", 1);
|
||||||
|
//
|
||||||
|
addCard(Zone.HAND, playerA, "Lightning Bolt", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||||
|
|
||||||
|
// cast and kill raffine before cannive resolve
|
||||||
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}", 3);
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Raffine's Silencer");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, 1); // resolve raffine
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt");
|
||||||
|
addTarget(playerA, "Raffine's Silencer"); // to kill
|
||||||
|
setChoice(playerA, "Grizzly Bears"); // to discard
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertGraveyardCount(playerA, "Raffine's Silencer", 1);
|
||||||
|
assertGraveyardCount(playerA, "Grizzly Bears", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_LKI_SpymastersVault_Normal() {
|
||||||
|
// {B}, {T}: Target creature you control connives X, where X is the number of creatures that died this turn.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Spymaster's Vault");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
|
||||||
|
addCard(Zone.HAND, playerA, "Grizzly Bears", 1);
|
||||||
|
//
|
||||||
|
addCustomEffect_DestroyTarget(playerA);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Razorclaw Bear", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1);
|
||||||
|
|
||||||
|
// prepare X = 1 from died amount
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "target destroy", "Razorclaw Bear");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkGraveyardCount("prepare", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Razorclaw Bear", 1);
|
||||||
|
|
||||||
|
// cannive lion
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{B}, {T}: Target creature", "Silvercoat Lion");
|
||||||
|
setChoice(playerA, "Grizzly Bears"); // to discard
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPowerToughness(playerA, "Silvercoat Lion", 2 + 1, 2 + 1);
|
||||||
|
assertGraveyardCount(playerA, "Grizzly Bears", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_LKI_SpymastersVault_Fizzle() {
|
||||||
|
// {B}, {T}: Target creature you control connives X, where X is the number of creatures that died this turn.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Spymaster's Vault");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
|
||||||
|
addCard(Zone.HAND, playerA, "Grizzly Bears", 1);
|
||||||
|
//
|
||||||
|
addCustomEffect_DestroyTarget(playerA);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Razorclaw Bear", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1);
|
||||||
|
|
||||||
|
// prepare X = 1 from died amount
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "target destroy", "Razorclaw Bear");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkGraveyardCount("prepare", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Razorclaw Bear", 1);
|
||||||
|
|
||||||
|
// cannive lion
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{B}, {T}: Target creature", "Silvercoat Lion");
|
||||||
|
// destroy lion before cannive
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "target destroy", "Silvercoat Lion");
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
// no connive due invalid target (ability fizzled)
|
||||||
|
assertGraveyardCount(playerA, "Silvercoat Lion", 1);
|
||||||
|
assertGraveyardCount(playerA, "Grizzly Bears", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_LKI_ChangeOfPlans_Normal() {
|
||||||
|
// Each of X target creatures you control connive. You may have any number of them phase out.
|
||||||
|
addCard(Zone.HAND, playerA, "Change of Plans"); // {X}{1}{U}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
|
||||||
|
addCard(Zone.HAND, playerA, "Grizzly Bears", 1);
|
||||||
|
//
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1);
|
||||||
|
|
||||||
|
// connive lion
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Change of Plans");
|
||||||
|
setChoice(playerA, "X=1");
|
||||||
|
addTarget(playerA, "Silvercoat Lion");
|
||||||
|
setChoice(playerA, "Grizzly Bears"); // to discard
|
||||||
|
setChoice(playerA, TestPlayer.CHOICE_SKIP); // no phase out
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPowerToughness(playerA, "Silvercoat Lion", 2 + 1, 2 + 1);
|
||||||
|
assertGraveyardCount(playerA, "Grizzly Bears", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_LKI_ChangeOfPlans_Fizzle() {
|
||||||
|
// Each of X target creatures you control connive. You may have any number of them phase out.
|
||||||
|
addCard(Zone.HAND, playerA, "Change of Plans"); // {X}{1}{U}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
|
||||||
|
addCard(Zone.HAND, playerA, "Grizzly Bears", 1);
|
||||||
|
//
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1);
|
||||||
|
//
|
||||||
|
addCustomEffect_DestroyTarget(playerA);
|
||||||
|
|
||||||
|
// connive lion
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Change of Plans");
|
||||||
|
setChoice(playerA, "X=1");
|
||||||
|
addTarget(playerA, "Silvercoat Lion");
|
||||||
|
// destroy lion before connive resolve
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "target destroy", "Silvercoat Lion");
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
// no connive due invalid target (ability fizzled)
|
||||||
|
assertGraveyardCount(playerA, "Silvercoat Lion", 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue