mirror of
https://github.com/correl/mage.git
synced 2024-11-29 03:00:12 +00:00
* Regeneration abilities improved:
* Fixed that regeneration shield isn't added to permanent on aura sacrifice cost (example: Stamina, Carapace, see #2221); * Fixed that regeneration shields accumulated in attached aura instead permanent (bug example: re-attached aura gives old shields to new permanent, see #6846); * Added card hint with regeneration shields amount (#6846);
This commit is contained in:
parent
516a4104f1
commit
00411b4a9b
7 changed files with 411 additions and 99 deletions
|
@ -82,7 +82,7 @@ public enum CombatManager {
|
||||||
private void drawDefender(CombatGroupView group, MagePermanent attackerCard, UUID gameId) {
|
private void drawDefender(CombatGroupView group, MagePermanent attackerCard, UUID gameId) {
|
||||||
UUID defenderId = group.getDefenderId();
|
UUID defenderId = group.getDefenderId();
|
||||||
if (defenderId != null) {
|
if (defenderId != null) {
|
||||||
// if attacker was blocked then use another allow color
|
// if attacker was blocked then use another arrow color
|
||||||
Color attackColor = group.getBlockers().isEmpty() ? ARROW_COLOR_ATTACKER : ARROW_COLOR_BLOCKED_ATTACKER;
|
Color attackColor = group.getBlockers().isEmpty() ? ARROW_COLOR_ATTACKER : ARROW_COLOR_BLOCKED_ATTACKER;
|
||||||
parentPoint = getParentPoint(attackerCard);
|
parentPoint = getParentPoint(attackerCard);
|
||||||
PlayAreaPanel p = MageFrame.getGamePlayers(gameId).get(defenderId);
|
PlayAreaPanel p = MageFrame.getGamePlayers(gameId).get(defenderId);
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
|
|
||||||
package mage.cards.c;
|
package mage.cards.c;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.common.SimpleActivatedAbility;
|
import mage.abilities.common.SimpleActivatedAbility;
|
||||||
import mage.abilities.common.SimpleStaticAbility;
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
@ -16,8 +14,9 @@ import mage.constants.*;
|
||||||
import mage.target.TargetPermanent;
|
import mage.target.TargetPermanent;
|
||||||
import mage.target.common.TargetCreaturePermanent;
|
import mage.target.common.TargetCreaturePermanent;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author Galatolol
|
* @author Galatolol
|
||||||
*/
|
*/
|
||||||
public final class Carapace extends CardImpl {
|
public final class Carapace extends CardImpl {
|
||||||
|
|
|
@ -1,43 +1,370 @@
|
||||||
|
|
||||||
package org.mage.test.cards.replacement;
|
package org.mage.test.cards.replacement;
|
||||||
|
|
||||||
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 LevelX2, JayDi85
|
||||||
* @author LevelX2
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class RegenerateTest extends CardTestPlayerBase {
|
public class RegenerateTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRegenerateAbilityGainedByEnchantment() {
|
public void test_GainedByEnchantment() {
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Underworld Cerberus");
|
addCard(Zone.BATTLEFIELD, playerA, "Underworld Cerberus");
|
||||||
|
|
||||||
addCard(Zone.BATTLEFIELD, playerB, "Sagu Archer");
|
addCard(Zone.BATTLEFIELD, playerB, "Sagu Archer");
|
||||||
addCard(Zone.HAND, playerB, "Molting Snakeskin");
|
addCard(Zone.HAND, playerB, "Molting Snakeskin");
|
||||||
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 4);
|
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 4);
|
||||||
|
|
||||||
|
|
||||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Molting Snakeskin", "Sagu Archer");
|
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Molting Snakeskin", "Sagu Archer");
|
||||||
attack(2, playerB, "Sagu Archer");
|
attack(2, playerB, "Sagu Archer");
|
||||||
block(2, playerA, "Underworld Cerberus", "Sagu Archer");
|
block(2, playerA, "Underworld Cerberus", "Sagu Archer");
|
||||||
activateAbility(2, PhaseStep.DECLARE_BLOCKERS, playerB, "{2}{B}: Regenerate {this}.");
|
activateAbility(2, PhaseStep.DECLARE_BLOCKERS, playerB, "{2}{B}: Regenerate {this}.");
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
execute();
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
|
||||||
assertLife(playerA, 20);
|
assertLife(playerA, 20);
|
||||||
assertLife(playerB, 20);
|
assertLife(playerB, 20);
|
||||||
|
|
||||||
// attacker has to regenerat because of damage
|
// attacker has to regenerate because of damage
|
||||||
|
|
||||||
assertPermanentCount(playerA, "Underworld Cerberus", 1);
|
assertPermanentCount(playerA, "Underworld Cerberus", 1);
|
||||||
assertPermanentCount(playerB, "Sagu Archer", 1);
|
assertPermanentCount(playerB, "Sagu Archer", 1);
|
||||||
assertPermanentCount(playerB, "Molting Snakeskin", 1);
|
assertPermanentCount(playerB, "Molting Snakeskin", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Source_Normal() {
|
||||||
|
// {B}: Regenerate Drudge Skeletons. (The next time this creature would be destroyed this turn, it isn’t.
|
||||||
|
// Instead tap it, remove all damage from it, and remove it from combat.)
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Drudge Skeletons", 1); // 1/1
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||||
|
//
|
||||||
|
addCard(Zone.HAND, playerA, "Lightning Bolt", 3);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||||
|
|
||||||
|
// add multiple regen shields
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{B}: Regenerate");
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{B}: Regenerate");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
|
||||||
|
// damage 1 - regen
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Drudge Skeletons");
|
||||||
|
setChoice(playerA, "Drudge Skeletons"); // two replacement effects
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkPermanentCount("alive 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Drudge Skeletons", 1);
|
||||||
|
|
||||||
|
// damage 2 - regen
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Drudge Skeletons");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkPermanentCount("alive 2", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Drudge Skeletons", 1);
|
||||||
|
|
||||||
|
// damage 3 - die
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Drudge Skeletons");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkGraveyardCount("die", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Drudge Skeletons", 1);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Source_Blinked() {
|
||||||
|
// {B}: Regenerate Drudge Skeletons. (The next time this creature would be destroyed this turn, it isn’t.
|
||||||
|
// Instead tap it, remove all damage from it, and remove it from combat.)
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Drudge Skeletons", 1); // 1/1
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||||
|
//
|
||||||
|
addCard(Zone.HAND, playerA, "Lightning Bolt", 3);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||||
|
//
|
||||||
|
// Exile target creature you control, then return that card to the battlefield under your control.
|
||||||
|
addCard(Zone.HAND, playerA, "Cloudshift", 1); // {W} instant
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||||
|
|
||||||
|
// add multiple regen shields
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{B}: Regenerate");
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{B}: Regenerate");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
|
||||||
|
// blink and reset regens
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cloudshift", "Drudge Skeletons");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkPermanentCount("alive blinked", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Drudge Skeletons", 1);
|
||||||
|
|
||||||
|
// damage - die (no regens)
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Drudge Skeletons");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkGraveyardCount("die", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Drudge Skeletons", 1);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Target_Normal() {
|
||||||
|
// {G}, {T}, Discard a card: Regenerate target creature.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Rushwood Herbalist", 2);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
|
||||||
|
addCard(Zone.HAND, playerA, "Forest", 2);
|
||||||
|
//
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 1); // 2/2
|
||||||
|
//
|
||||||
|
addCard(Zone.HAND, playerA, "Lightning Bolt", 3);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||||
|
|
||||||
|
// add multiple regen shields
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{G}, {T}, Discard", "Grizzly Bears");
|
||||||
|
setChoice(playerA, "Forest"); // discard cost
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{G}, {T}, Discard", "Grizzly Bears");
|
||||||
|
setChoice(playerA, "Forest"); // discard cost
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
|
||||||
|
// damage 1 - regen
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Grizzly Bears");
|
||||||
|
setChoice(playerA, "Rushwood Herbalist"); // two replacement effects
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkPermanentCount("alive 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", 1);
|
||||||
|
|
||||||
|
// damage 2 - regen
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Grizzly Bears");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkPermanentCount("alive 2", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", 1);
|
||||||
|
|
||||||
|
// damage 3 - die
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Grizzly Bears");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkGraveyardCount("die", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", 1);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Target_Blinked() {
|
||||||
|
// {G}, {T}, Discard a card: Regenerate target creature.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Rushwood Herbalist", 2);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
|
||||||
|
addCard(Zone.HAND, playerA, "Forest", 2);
|
||||||
|
//
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 1); // 2/2
|
||||||
|
//
|
||||||
|
addCard(Zone.HAND, playerA, "Lightning Bolt", 3);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||||
|
//
|
||||||
|
// Exile target creature you control, then return that card to the battlefield under your control.
|
||||||
|
addCard(Zone.HAND, playerA, "Cloudshift", 1); // {W} instant
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||||
|
|
||||||
|
// add multiple regen shields
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{G}, {T}, Discard", "Grizzly Bears");
|
||||||
|
setChoice(playerA, "Forest"); // discard cost
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{G}, {T}, Discard", "Grizzly Bears");
|
||||||
|
setChoice(playerA, "Forest"); // discard cost
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
|
||||||
|
// blink and reset regens
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cloudshift", "Grizzly Bears");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkPermanentCount("alive blinked", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", 1);
|
||||||
|
|
||||||
|
// damage - die (no regens)
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Grizzly Bears");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkGraveyardCount("die", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", 1);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Attached_Normal() {
|
||||||
|
// Enchant creature (Target a creature as you cast this. This card enters the battlefield attached to that creature.)
|
||||||
|
// {G}: Regenerate enchanted creature. (The next time that creature would be destroyed this turn, it isn’t.
|
||||||
|
// Instead tap it, remove all damage from it, and remove it from combat.)
|
||||||
|
addCard(Zone.HAND, playerA, "Regeneration", 1); // {1}{G} aura
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2 + 2); // cast + 2 activates
|
||||||
|
//
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 1); // 2/2
|
||||||
|
//
|
||||||
|
addCard(Zone.HAND, playerA, "Lightning Bolt", 3);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||||
|
|
||||||
|
// attach
|
||||||
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G}", 2);
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Regeneration", "Grizzly Bears");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||||
|
|
||||||
|
// add multiple regen shields
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{G}: Regenerate");
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{G}: Regenerate");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
|
||||||
|
// damage 1 - regen
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Grizzly Bears");
|
||||||
|
setChoice(playerA, "Regeneration"); // two replacement effects
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkPermanentCount("alive 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", 1);
|
||||||
|
|
||||||
|
// damage 2 - regen
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Grizzly Bears");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkPermanentCount("alive 2", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", 1);
|
||||||
|
|
||||||
|
// damage 3 - die
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Grizzly Bears");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkGraveyardCount("die", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", 1);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Attached_Blinked() {
|
||||||
|
// Enchant creature (Target a creature as you cast this. This card enters the battlefield attached to that creature.)
|
||||||
|
// {G}: Regenerate enchanted creature. (The next time that creature would be destroyed this turn, it isn’t.
|
||||||
|
// Instead tap it, remove all damage from it, and remove it from combat.)
|
||||||
|
addCard(Zone.HAND, playerA, "Regeneration", 1); // {1}{G} aura
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2 + 2); // cast + 2 activates
|
||||||
|
//
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 1); // 2/2
|
||||||
|
//
|
||||||
|
addCard(Zone.HAND, playerA, "Lightning Bolt", 3);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||||
|
//
|
||||||
|
// Exile target creature you control, then return that card to the battlefield under your control.
|
||||||
|
addCard(Zone.HAND, playerA, "Cloudshift", 1); // {W} instant
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||||
|
|
||||||
|
// attach
|
||||||
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G}", 2);
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Regeneration", "Grizzly Bears");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||||
|
|
||||||
|
// add multiple regen shields
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{G}: Regenerate");
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{G}: Regenerate");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
|
||||||
|
// blink and reset regens
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cloudshift", "Grizzly Bears");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkPermanentCount("alive blinked", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", 1);
|
||||||
|
|
||||||
|
// damage - die (no regens)
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Grizzly Bears");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkGraveyardCount("die", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", 1);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Attached_Moved() {
|
||||||
|
// regen shields must be accumulated in permanent, not aura
|
||||||
|
|
||||||
|
// Enchant creature (Target a creature as you cast this. This card enters the battlefield attached to that creature.)
|
||||||
|
// {G}: Regenerate enchanted creature. (The next time that creature would be destroyed this turn, it isn’t.
|
||||||
|
// Instead tap it, remove all damage from it, and remove it from combat.)
|
||||||
|
addCard(Zone.HAND, playerA, "Regeneration", 1); // {1}{G} aura
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2 + 2); // cast + 2 activates
|
||||||
|
//
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 1); // 2/2 permanent 1
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Kitesail Corsair", 1); // 2/1 permanent 2
|
||||||
|
//
|
||||||
|
addCard(Zone.HAND, playerA, "Lightning Bolt", 3);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||||
|
//
|
||||||
|
// Attach target Aura you control to target creature.
|
||||||
|
addCard(Zone.HAND, playerA, "Aura Finesse", 1); // {U} instant
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||||
|
|
||||||
|
// attach to first
|
||||||
|
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G}", 2);
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Regeneration", "Grizzly Bears");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||||
|
|
||||||
|
// add multiple regen shields
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{G}: Regenerate");
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{G}: Regenerate");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
|
||||||
|
// re-attach to second
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Aura Finesse");
|
||||||
|
addTarget(playerA, "Regeneration"); // aura to move
|
||||||
|
addTarget(playerA, "Kitesail Corsair"); // attach to permanent 2
|
||||||
|
|
||||||
|
// damage to one - have regens
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Grizzly Bears");
|
||||||
|
setChoice(playerA, "Regeneration"); // two replacement effects
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkPermanentCount("alive", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", 1);
|
||||||
|
|
||||||
|
// damage to second -- die (no regens)
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Kitesail Corsair");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
checkGraveyardCount("die", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Kitesail Corsair", 1);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Attached_Sacrifice() {
|
||||||
|
// if you sacrifice aura to enable regen then it must works
|
||||||
|
|
||||||
|
// Enchant creature
|
||||||
|
// Enchanted creature gets +0/+2.
|
||||||
|
// Sacrifice Carapace: Regenerate enchanted creature.
|
||||||
|
addCard(Zone.HAND, playerA, "Carapace", 1); // {G} aura
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
|
||||||
|
//
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 1); // 2/2
|
||||||
|
//
|
||||||
|
addCard(Zone.HAND, playerA, "Lightning Bolt", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||||
|
|
||||||
|
// attach
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Carapace", "Grizzly Bears");
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA);
|
||||||
|
checkPT("boosted", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", 2, 2 + 2);
|
||||||
|
|
||||||
|
// try to kill (boost lost after regen activate, so need only 1 bolt)
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Grizzly Bears");
|
||||||
|
// activate regen before kill
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice", TestPlayer.NO_TARGET, "Cast Lightning Bolt", StackClause.WHILE_ON_STACK);
|
||||||
|
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||||
|
|
||||||
|
// permanent must be alive
|
||||||
|
checkGraveyardCount("aura sacrificed", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Carapace", 1);
|
||||||
|
checkPermanentCount("permanent alive", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears", 1);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,63 +1,49 @@
|
||||||
package mage.abilities.effects.common;
|
package mage.abilities.effects.common;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.effects.ReplacementEffectImpl;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.constants.AttachmentType;
|
import mage.constants.AttachmentType;
|
||||||
import mage.constants.Duration;
|
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.target.targetpointer.FixedTarget;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author jeff
|
* @author jeff
|
||||||
*/
|
*/
|
||||||
public class RegenerateAttachedEffect extends ReplacementEffectImpl {
|
public class RegenerateAttachedEffect extends OneShotEffect {
|
||||||
|
|
||||||
protected AttachmentType attachmentType;
|
protected AttachmentType attachmentType;
|
||||||
|
|
||||||
public RegenerateAttachedEffect(AttachmentType attachmentType) {
|
public RegenerateAttachedEffect(AttachmentType attachmentType) {
|
||||||
super(Duration.EndOfTurn, Outcome.Regenerate);
|
super(Outcome.Regenerate);
|
||||||
this.attachmentType = attachmentType;
|
this.attachmentType = attachmentType;
|
||||||
this.setText();
|
this.setText();
|
||||||
}
|
}
|
||||||
|
|
||||||
public RegenerateAttachedEffect(final RegenerateAttachedEffect effect) {
|
public RegenerateAttachedEffect(final RegenerateAttachedEffect effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
|
this.attachmentType = effect.attachmentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
//20110204 - 701.11
|
// must use lki cause attachment can be sacrificed to activate regen
|
||||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
Permanent attachment = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
||||||
|
if (attachment == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Permanent permanent = game.getPermanent(attachment.getAttachedTo());
|
||||||
if (permanent == null) {
|
if (permanent == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Permanent equipped = game.getPermanent(permanent.getAttachedTo());
|
|
||||||
if (equipped != null && equipped.regenerate(source, game)) {
|
|
||||||
this.used = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
RegenerateTargetEffect regenEffect = new RegenerateTargetEffect();
|
||||||
public void init(Ability source, Game game) {
|
regenEffect.setTargetPointer(new FixedTarget(permanent, game));
|
||||||
super.init(source, game);
|
game.addEffect(regenEffect, source);
|
||||||
|
return true;
|
||||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
|
||||||
if (permanent == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Permanent equipped = game.getPermanent(permanent.getAttachedTo());
|
|
||||||
if (equipped == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RegenerateSourceEffect.initRegenerationInfoWhileAttached(game, source, equipped.getId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -65,32 +51,6 @@ public class RegenerateAttachedEffect extends ReplacementEffectImpl {
|
||||||
return new RegenerateAttachedEffect(this);
|
return new RegenerateAttachedEffect(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
|
||||||
return apply(game, source);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean checksEventType(GameEvent event, Game game) {
|
|
||||||
return event.getType() == GameEvent.EventType.DESTROY_PERMANENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
|
||||||
//20110204 - 701.11c - event.getAmount() is used to signal if regeneration is allowed
|
|
||||||
Permanent equipment = game.getPermanent(source.getSourceId());
|
|
||||||
if (equipment != null) {
|
|
||||||
Permanent equipped = game.getPermanent(equipment.getAttachedTo());
|
|
||||||
if (equipped != null) {
|
|
||||||
UUID equippedID = equipped.getId();
|
|
||||||
if (event.getAmount() == 0 && event.getTargetId().equals(equippedID) && !this.used) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setText() {
|
private void setText() {
|
||||||
staticText = "Regenerate " + attachmentType.verb().toLowerCase(Locale.ENGLISH) + " creature";
|
staticText = "Regenerate " + attachmentType.verb().toLowerCase(Locale.ENGLISH) + " creature";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
package mage.abilities.effects.common;
|
package mage.abilities.effects.common;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.condition.Condition;
|
|
||||||
import mage.abilities.condition.common.AttachedToPermanentCondition;
|
|
||||||
import mage.abilities.effects.ReplacementEffectImpl;
|
import mage.abilities.effects.ReplacementEffectImpl;
|
||||||
import mage.abilities.hint.ConditionHint;
|
import mage.abilities.hint.Hint;
|
||||||
|
import mage.abilities.hint.HintUtils;
|
||||||
import mage.constants.Duration;
|
import mage.constants.Duration;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
@ -15,7 +14,7 @@ import mage.util.CardUtil;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com, JayDi85
|
||||||
*/
|
*/
|
||||||
public class RegenerateSourceEffect extends ReplacementEffectImpl {
|
public class RegenerateSourceEffect extends ReplacementEffectImpl {
|
||||||
|
|
||||||
|
@ -50,7 +49,7 @@ public class RegenerateSourceEffect extends ReplacementEffectImpl {
|
||||||
public void init(Ability source, Game game) {
|
public void init(Ability source, Game game) {
|
||||||
super.init(source, game);
|
super.init(source, game);
|
||||||
|
|
||||||
RegenerateSourceEffect.initRegenerationInfo(game, source, source.getSourceId());
|
RegenerateSourceEffect.initRegenerationShieldInfo(game, source, source.getSourceId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -83,44 +82,70 @@ public class RegenerateSourceEffect extends ReplacementEffectImpl {
|
||||||
&& !this.used;
|
&& !this.used;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initRegenerationInfo(Game game, Ability source, UUID permanentId) {
|
/**
|
||||||
// enable regen info
|
* Add info about new regen shield.
|
||||||
|
* Warning, it's a workaround to show regen shields info, real effects will be use replacement logic.
|
||||||
|
*
|
||||||
|
* @param game
|
||||||
|
* @param source
|
||||||
|
* @param permanentId
|
||||||
|
*/
|
||||||
|
public static void initRegenerationShieldInfo(Game game, Ability source, UUID permanentId) {
|
||||||
Permanent permanent = game.getPermanent(permanentId);
|
Permanent permanent = game.getPermanent(permanentId);
|
||||||
if (permanent != null) {
|
if (permanent != null) {
|
||||||
game.getState().setValue(CardUtil.getCardZoneString("RegenerationActivated", permanent.getId(), game), Boolean.TRUE);
|
// add one regen shield
|
||||||
|
RegenerateSourceEffect.incRegenerationShieldsAmount(game, permanent.getId());
|
||||||
|
// add regen info
|
||||||
InfoEffect.addCardHintToPermanent(game, source, permanent,
|
InfoEffect.addCardHintToPermanent(game, source, permanent,
|
||||||
new ConditionHint(RegeneratingCanBeUsedCondition.instance, "Permanent will be regenerated instead destroy"),
|
RegenerationShieldsHint.instance, Duration.EndOfTurn);
|
||||||
Duration.EndOfTurn
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initRegenerationInfoWhileAttached(Game game, Ability source, UUID permanentId) {
|
public static int getRegenerationShieldsAmount(Game game, UUID permanentId) {
|
||||||
// enable regen info for attached permanent
|
// info must be reset on new turn
|
||||||
Permanent permanent = game.getPermanent(permanentId);
|
Integer amount = (Integer) game.getState().getValue(
|
||||||
if (permanent != null) {
|
CardUtil.getCardZoneString("RegenerationShieldsAmount_turn" + game.getTurnNum(), permanentId, game));
|
||||||
game.getState().setValue(CardUtil.getCardZoneString("RegenerationActivated", permanent.getId(), game), Boolean.TRUE);
|
if (amount != null) {
|
||||||
|
return amount;
|
||||||
InfoEffect.addCardHintToPermanentConditional(game, source, permanent,
|
|
||||||
new ConditionHint(RegeneratingCanBeUsedCondition.instance, "Permanent will be regenerated instead destroy"),
|
|
||||||
Duration.EndOfTurn,
|
|
||||||
new AttachedToPermanentCondition(permanent.getId())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setRegenerationShieldsAmount(Game game, UUID permanentId, int amount) {
|
||||||
|
game.getState().setValue(
|
||||||
|
CardUtil.getCardZoneString("RegenerationShieldsAmount_turn" + game.getTurnNum(), permanentId, game), amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int incRegenerationShieldsAmount(Game game, UUID permanentId) {
|
||||||
|
int amount = getRegenerationShieldsAmount(game, permanentId) + 1;
|
||||||
|
setRegenerationShieldsAmount(game, permanentId, amount);
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int decRegenerationShieldsAmount(Game game, UUID permanentId) {
|
||||||
|
int amount = Math.max(0, getRegenerationShieldsAmount(game, permanentId) - 1);
|
||||||
|
setRegenerationShieldsAmount(game, permanentId, amount);
|
||||||
|
return amount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum RegeneratingCanBeUsedCondition implements Condition {
|
enum RegenerationShieldsHint implements Hint {
|
||||||
|
|
||||||
instance;
|
instance;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public String getText(Game game, Ability ability) {
|
||||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
int amount = RegenerateSourceEffect.getRegenerationShieldsAmount(game, ability.getSourceId());
|
||||||
if (permanent != null) {
|
String info = "Regeneration shields: " + amount + " (permanent will be regenerated instead destroy)";
|
||||||
Boolean shieldActivated = (Boolean) game.getState().getValue(CardUtil.getCardZoneString("RegenerationActivated", permanent.getId(), game));
|
if (amount > 0) {
|
||||||
return shieldActivated != null && shieldActivated;
|
return HintUtils.prepareText(info, null, HintUtils.HINT_ICON_GOOD);
|
||||||
|
} else {
|
||||||
|
return HintUtils.prepareText(info, null, HintUtils.HINT_ICON_BAD);
|
||||||
}
|
}
|
||||||
return false;
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Hint copy() {
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ public class RegenerateTargetEffect extends ReplacementEffectImpl {
|
||||||
public void init(Ability source, Game game) {
|
public void init(Ability source, Game game) {
|
||||||
super.init(source, game);
|
super.init(source, game);
|
||||||
|
|
||||||
RegenerateSourceEffect.initRegenerationInfo(game, source, targetPointer.getFirst(game, source));
|
RegenerateSourceEffect.initRegenerationShieldInfo(game, source, targetPointer.getFirst(game, source));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -10,6 +10,7 @@ import mage.abilities.effects.ContinuousEffect;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.abilities.effects.RequirementEffect;
|
import mage.abilities.effects.RequirementEffect;
|
||||||
import mage.abilities.effects.RestrictionEffect;
|
import mage.abilities.effects.RestrictionEffect;
|
||||||
|
import mage.abilities.effects.common.RegenerateSourceEffect;
|
||||||
import mage.abilities.hint.Hint;
|
import mage.abilities.hint.Hint;
|
||||||
import mage.abilities.hint.HintUtils;
|
import mage.abilities.hint.HintUtils;
|
||||||
import mage.abilities.keyword.*;
|
import mage.abilities.keyword.*;
|
||||||
|
@ -1179,8 +1180,8 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
||||||
this.removeFromCombat(game);
|
this.removeFromCombat(game);
|
||||||
this.removeAllDamage(game);
|
this.removeAllDamage(game);
|
||||||
|
|
||||||
// remove regen info
|
// remove one regen shield
|
||||||
game.getState().setValue(CardUtil.getCardZoneString("RegenerationActivated", this.getId(), game), Boolean.FALSE);
|
RegenerateSourceEffect.decRegenerationShieldsAmount(game, this.getId());
|
||||||
|
|
||||||
game.fireEvent(GameEvent.getEvent(EventType.REGENERATED, objectId, source.getSourceId(), controllerId));
|
game.fireEvent(GameEvent.getEvent(EventType.REGENERATED, objectId, source.getSourceId(), controllerId));
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in a new issue