* Soulfire Grand Master - Fixed that delayed effects (e.g. Deflecting Palm) have also lifelink if Soulfire Grand Master is still on the battlefield.

This commit is contained in:
LevelX2 2015-05-26 22:16:32 +02:00
parent 7b5b4928a4
commit f0ef479402
3 changed files with 73 additions and 61 deletions

View file

@ -27,8 +27,6 @@
*/
package mage.sets.fatereforged;
import java.util.HashSet;
import java.util.Iterator;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
@ -48,7 +46,6 @@ import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.SubLayer;
import mage.constants.WatcherScope;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.FilterObject;
@ -61,7 +58,6 @@ import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.game.stack.StackObject;
import mage.players.Player;
import mage.watchers.Watcher;
/**
*
@ -89,7 +85,7 @@ public class SoulfireGrandMaster extends CardImpl {
// Instant and sorcery spells you control have lifelink.
Effect effect = new GainAbilitySpellsEffect(LifelinkAbility.getInstance(), filter);
effect.setText("Instant and sorcery spells you control have lifelink");
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect), new SoulfireGrandMasterLeavesStackWatcher());
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect));
// {2}{U/R}{U/R}: The next time you cast an instant or sorcery spell from your hand this turn, put that card into your hand instead of your graveyard as it resolves.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new SoulfireGrandMasterCastFromHandReplacementEffect(), new ManaCostsImpl("{2}{U/R}{U/R}")));
@ -134,17 +130,32 @@ class GainAbilitySpellsEffect extends ContinuousEffectImpl {
Player player = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanent(source.getSourceId());
if (player != null && permanent != null) {
for (Iterator<StackObject> iterator = game.getStack().iterator(); iterator.hasNext();) {
StackObject stackObject = iterator.next();
for (Card card: game.getExile().getAllCards(game)) {
if (card.getOwnerId().equals(source.getControllerId()) && filter.match(card, game)) {
game.getState().addOtherAbility(card, ability);
}
}
for (Card card: player.getLibrary().getCards(game)) {
if (filter.match(card, game)) {
game.getState().addOtherAbility(card, ability);
}
}
for (Card card: player.getHand().getCards(game)) {
if (filter.match(card, game)) {
game.getState().addOtherAbility(card, ability);
}
}
for (Card card: player.getGraveyard().getCards(game)) {
if (filter.match(card, game)) {
game.getState().addOtherAbility(card, ability);
}
}
for (StackObject stackObject : game.getStack()) {
if (stackObject.getControllerId().equals(source.getControllerId())) {
Card card = game.getCard(stackObject.getSourceId());
if (card != null && filter.match(card, game)) {
if (!card.getAbilities().contains(ability)) {
game.getState().addOtherAbility(card, ability);
SoulfireGrandMasterLeavesStackWatcher watcher = (SoulfireGrandMasterLeavesStackWatcher) game.getState().getWatchers().get("SoulfireGrandMasterLeavesStackWatcher");
if (watcher != null) {
watcher.addCardId(card.getId());
}
}
}
}
@ -238,44 +249,3 @@ class SoulfireGrandMasterCastFromHandReplacementEffect extends ReplacementEffect
}
}
class SoulfireGrandMasterLeavesStackWatcher extends Watcher {
private final HashSet<UUID> cardIds = new HashSet<>();
public SoulfireGrandMasterLeavesStackWatcher() {
super("SoulfireGrandMasterLeavesStackWatcher", WatcherScope.GAME);
}
public SoulfireGrandMasterLeavesStackWatcher(final SoulfireGrandMasterLeavesStackWatcher watcher) {
super(watcher);
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.ZONE_CHANGE && cardIds.contains(event.getTargetId())) {
Card card = game.getCard(event.getTargetId());
if (card != null) {
Iterator<Ability> it = card.getAbilities().iterator();
while (it.hasNext()) {
if (it.next() instanceof LifelinkAbility) {
it.remove();
break;
}
}
cardIds.remove(event.getTargetId());
}
}
}
public void addCardId(UUID cardId) {
cardIds.add(cardId);
}
@Override
public SoulfireGrandMasterLeavesStackWatcher copy() {
return new SoulfireGrandMasterLeavesStackWatcher(this);
}
}

View file

@ -205,7 +205,7 @@ public class SoulfireGrandMasterTest extends CardTestPlayerBase {
}
/**
* Test that if Soulfire Grand Master has left the battlefield
* spell have no longer lifelink
* spell has no longer lifelink
*/
@Test
@ -294,5 +294,39 @@ public class SoulfireGrandMasterTest extends CardTestPlayerBase {
assertLife(playerB, 20);
assertLife(playerA, 20);
}
}
/**
* With a Soulfire Grand Master in play, Deflecting Palm doesn't gain the caster life.
* It should as it has lifelink, and it's Deflecting Palm (an instant) dealing damage.
* I was playing against a human in Standard Constructed.
*
*/
@Test
public void testWithDeflectingPalm() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
// Instant -{R}{W}
// The next time a source of your choice would deal damage to you this turn, prevent that damage.
// If damage is prevented this way, Deflecting Palm deals that much damage to that source's controller.
addCard(Zone.HAND, playerA, "Deflecting Palm");
addCard(Zone.BATTLEFIELD, playerA, "Soulfire Grand Master", 1);
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1);
addCard(Zone.HAND, playerB, "Lightning Bolt", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", playerA);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Deflecting Palm", null, "Lightning Bolt");
setChoice(playerA, "Lightning Bolt");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerB, "Lightning Bolt", 1);
assertGraveyardCount(playerA, "Deflecting Palm", 1);
assertLife(playerB, 17);
assertLife(playerA, 23); // damage is prevented + lifelink + 3
}
}

View file

@ -360,16 +360,24 @@ public class TestPlayer extends ComputerPlayer {
MageObject targetObject = game.getObject(targetId);
if (targetObject != null) {
for (String choose2: choices) {
if (targetObject.getName().equals(choose2)) {
List<UUID> alreadyTargetted = target.getTargets();
if (t.canTarget(targetObject.getId(), game)) {
if (alreadyTargetted != null && !alreadyTargetted.contains(targetObject.getId())) {
target.add(targetObject.getId(), game);
choices.remove(choose2);
return true;
String[] targetList = choose2.split("\\^");
boolean targetFound = false;
for (String targetName: targetList) {
if (targetObject.getName().equals(targetName)) {
List<UUID> alreadyTargetted = target.getTargets();
if (t.canTarget(targetObject.getId(), game)) {
if (alreadyTargetted != null && !alreadyTargetted.contains(targetObject.getId())) {
target.add(targetObject.getId(), game);
choices.remove(choose2);
targetFound = true;
}
}
}
}
if (targetFound) {
choices.remove(choose2);
return true;
}
}
}
}