mirror of
https://github.com/correl/mage.git
synced 2024-12-26 03:00:11 +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) {
|
||||
UUID defenderId = group.getDefenderId();
|
||||
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;
|
||||
parentPoint = getParentPoint(attackerCard);
|
||||
PlayAreaPanel p = MageFrame.getGamePlayers(gameId).get(defenderId);
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
|
||||
package mage.cards.c;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
|
@ -16,15 +14,16 @@ import mage.constants.*;
|
|||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Galatolol
|
||||
*/
|
||||
public final class Carapace extends CardImpl {
|
||||
|
||||
public Carapace(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{G}");
|
||||
|
||||
|
||||
this.subtype.add(SubType.AURA);
|
||||
|
||||
// Enchant creature
|
||||
|
|
|
@ -1,43 +1,370 @@
|
|||
|
||||
package org.mage.test.cards.replacement;
|
||||
|
||||
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 LevelX2
|
||||
* @author LevelX2, JayDi85
|
||||
*/
|
||||
|
||||
public class RegenerateTest extends CardTestPlayerBase {
|
||||
|
||||
@Test
|
||||
public void testRegenerateAbilityGainedByEnchantment() {
|
||||
public void test_GainedByEnchantment() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Underworld Cerberus");
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Sagu Archer");
|
||||
addCard(Zone.HAND, playerB, "Molting Snakeskin");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 4);
|
||||
|
||||
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Molting Snakeskin", "Sagu Archer");
|
||||
attack(2, playerB, "Sagu Archer");
|
||||
block(2, playerA, "Underworld Cerberus", "Sagu Archer");
|
||||
activateAbility(2, PhaseStep.DECLARE_BLOCKERS, playerB, "{2}{B}: Regenerate {this}.");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 20);
|
||||
|
||||
// attacker has to regenerat because of damage
|
||||
|
||||
// attacker has to regenerate because of damage
|
||||
|
||||
assertPermanentCount(playerA, "Underworld Cerberus", 1);
|
||||
assertPermanentCount(playerB, "Sagu Archer", 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;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.AttachmentType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author jeff
|
||||
*/
|
||||
public class RegenerateAttachedEffect extends ReplacementEffectImpl {
|
||||
public class RegenerateAttachedEffect extends OneShotEffect {
|
||||
|
||||
protected AttachmentType attachmentType;
|
||||
|
||||
public RegenerateAttachedEffect(AttachmentType attachmentType) {
|
||||
super(Duration.EndOfTurn, Outcome.Regenerate);
|
||||
super(Outcome.Regenerate);
|
||||
this.attachmentType = attachmentType;
|
||||
this.setText();
|
||||
}
|
||||
|
||||
public RegenerateAttachedEffect(final RegenerateAttachedEffect effect) {
|
||||
super(effect);
|
||||
this.attachmentType = effect.attachmentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
//20110204 - 701.11
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
// must use lki cause attachment can be sacrificed to activate regen
|
||||
Permanent attachment = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
||||
if (attachment == null) {
|
||||
return false;
|
||||
}
|
||||
Permanent permanent = game.getPermanent(attachment.getAttachedTo());
|
||||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
Permanent equipped = game.getPermanent(permanent.getAttachedTo());
|
||||
if (equipped != null && equipped.regenerate(source, game)) {
|
||||
this.used = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Ability source, Game game) {
|
||||
super.init(source, game);
|
||||
|
||||
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());
|
||||
RegenerateTargetEffect regenEffect = new RegenerateTargetEffect();
|
||||
regenEffect.setTargetPointer(new FixedTarget(permanent, game));
|
||||
game.addEffect(regenEffect, source);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -65,32 +51,6 @@ public class RegenerateAttachedEffect extends ReplacementEffectImpl {
|
|||
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() {
|
||||
staticText = "Regenerate " + attachmentType.verb().toLowerCase(Locale.ENGLISH) + " creature";
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
package mage.abilities.effects.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.condition.common.AttachedToPermanentCondition;
|
||||
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.Outcome;
|
||||
import mage.game.Game;
|
||||
|
@ -15,7 +14,7 @@ import mage.util.CardUtil;
|
|||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
* @author BetaSteward_at_googlemail.com, JayDi85
|
||||
*/
|
||||
public class RegenerateSourceEffect extends ReplacementEffectImpl {
|
||||
|
||||
|
@ -50,7 +49,7 @@ public class RegenerateSourceEffect extends ReplacementEffectImpl {
|
|||
public void init(Ability source, Game game) {
|
||||
super.init(source, game);
|
||||
|
||||
RegenerateSourceEffect.initRegenerationInfo(game, source, source.getSourceId());
|
||||
RegenerateSourceEffect.initRegenerationShieldInfo(game, source, source.getSourceId());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -83,44 +82,70 @@ public class RegenerateSourceEffect extends ReplacementEffectImpl {
|
|||
&& !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);
|
||||
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,
|
||||
new ConditionHint(RegeneratingCanBeUsedCondition.instance, "Permanent will be regenerated instead destroy"),
|
||||
Duration.EndOfTurn
|
||||
);
|
||||
RegenerationShieldsHint.instance, Duration.EndOfTurn);
|
||||
}
|
||||
}
|
||||
|
||||
public static void initRegenerationInfoWhileAttached(Game game, Ability source, UUID permanentId) {
|
||||
// enable regen info for attached permanent
|
||||
Permanent permanent = game.getPermanent(permanentId);
|
||||
if (permanent != null) {
|
||||
game.getState().setValue(CardUtil.getCardZoneString("RegenerationActivated", permanent.getId(), game), Boolean.TRUE);
|
||||
|
||||
InfoEffect.addCardHintToPermanentConditional(game, source, permanent,
|
||||
new ConditionHint(RegeneratingCanBeUsedCondition.instance, "Permanent will be regenerated instead destroy"),
|
||||
Duration.EndOfTurn,
|
||||
new AttachedToPermanentCondition(permanent.getId())
|
||||
);
|
||||
public static int getRegenerationShieldsAmount(Game game, UUID permanentId) {
|
||||
// info must be reset on new turn
|
||||
Integer amount = (Integer) game.getState().getValue(
|
||||
CardUtil.getCardZoneString("RegenerationShieldsAmount_turn" + game.getTurnNum(), permanentId, game));
|
||||
if (amount != null) {
|
||||
return amount;
|
||||
}
|
||||
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;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null) {
|
||||
Boolean shieldActivated = (Boolean) game.getState().getValue(CardUtil.getCardZoneString("RegenerationActivated", permanent.getId(), game));
|
||||
return shieldActivated != null && shieldActivated;
|
||||
public String getText(Game game, Ability ability) {
|
||||
int amount = RegenerateSourceEffect.getRegenerationShieldsAmount(game, ability.getSourceId());
|
||||
String info = "Regeneration shields: " + amount + " (permanent will be regenerated instead destroy)";
|
||||
if (amount > 0) {
|
||||
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) {
|
||||
super.init(source, game);
|
||||
|
||||
RegenerateSourceEffect.initRegenerationInfo(game, source, targetPointer.getFirst(game, source));
|
||||
RegenerateSourceEffect.initRegenerationShieldInfo(game, source, targetPointer.getFirst(game, source));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -10,6 +10,7 @@ import mage.abilities.effects.ContinuousEffect;
|
|||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.RequirementEffect;
|
||||
import mage.abilities.effects.RestrictionEffect;
|
||||
import mage.abilities.effects.common.RegenerateSourceEffect;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.abilities.hint.HintUtils;
|
||||
import mage.abilities.keyword.*;
|
||||
|
@ -1179,8 +1180,8 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
this.removeFromCombat(game);
|
||||
this.removeAllDamage(game);
|
||||
|
||||
// remove regen info
|
||||
game.getState().setValue(CardUtil.getCardZoneString("RegenerationActivated", this.getId(), game), Boolean.FALSE);
|
||||
// remove one regen shield
|
||||
RegenerateSourceEffect.decRegenerationShieldsAmount(game, this.getId());
|
||||
|
||||
game.fireEvent(GameEvent.getEvent(EventType.REGENERATED, objectId, source.getSourceId(), controllerId));
|
||||
return true;
|
||||
|
|
Loading…
Reference in a new issue