* 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:
Oleg Agafonov 2020-08-02 14:01:58 +04:00
parent 516a4104f1
commit 00411b4a9b
7 changed files with 411 additions and 99 deletions

View file

@ -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);

View file

@ -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,8 +14,9 @@ import mage.constants.*;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
*
* @author Galatolol
*/
public final class Carapace extends CardImpl {

View file

@ -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 isnt.
// 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 isnt.
// 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 isnt.
// 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 isnt.
// 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 isnt.
// 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();
}
}

View file

@ -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";
}

View file

@ -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;
}
}

View file

@ -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

View file

@ -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;