diff --git a/Mage.Sets/src/mage/sets/fallenempires/FarrelitePriest.java b/Mage.Sets/src/mage/sets/fallenempires/FarrelitePriest.java index 8378dda0a83..bbf2927b12d 100644 --- a/Mage.Sets/src/mage/sets/fallenempires/FarrelitePriest.java +++ b/Mage.Sets/src/mage/sets/fallenempires/FarrelitePriest.java @@ -31,19 +31,20 @@ import java.util.UUID; import mage.MageInt; import static mage.Mana.WhiteMana; import mage.abilities.Ability; +import mage.abilities.ActivationInfo; import mage.abilities.DelayedTriggeredAbility; -import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.BasicManaEffect; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.mana.SimpleManaAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; import mage.game.Game; -import mage.game.permanent.Permanent; /** * @@ -60,11 +61,11 @@ public class FarrelitePriest extends CardImpl { this.toughness = new MageInt(3); // {1}: Add {W} to your mana pool. If this ability has been activated four or more times this turn, sacrifice Farrelite Priest at the beginning of the next end step. - SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + SimpleManaAbility ability = new SimpleManaAbility(Zone.BATTLEFIELD, new BasicManaEffect(WhiteMana(1)), new ManaCostsImpl("{1}")); ability.addEffect(new FarrelitePriestEffect()); - this.addAbility(ability); + this.addAbility(ability); } public FarrelitePriest(final FarrelitePriest card) { @@ -76,6 +77,7 @@ public class FarrelitePriest extends CardImpl { return new FarrelitePriest(this); } } + class FarrelitePriestEffect extends OneShotEffect { public FarrelitePriestEffect() { @@ -94,46 +96,13 @@ class FarrelitePriestEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Integer amount = (Integer) game.getState().getValue(source.getSourceId().toString() + "FarrelitePriest"); - if (amount == null) { - amount = 0; - DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new FarrelitePriestResetEffect()); + ActivationInfo activationInfo = ActivationInfo.getInstance(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); + activationInfo.addActivation(game); + if (activationInfo.getActivationCounter() == 4) { + DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new SacrificeSourceEffect()); game.addDelayedTriggeredAbility(delayedAbility, source); } - amount++; - game.getState().setValue(source.getSourceId().toString() + "FarrelitePriest", amount); - return true; } + } - -class FarrelitePriestResetEffect extends OneShotEffect { - - public FarrelitePriestResetEffect() { - super(Outcome.Neutral); - this.staticText = "If this ability has been activated four or more times this turn, sacrifice {this} at the beginning of the next end step"; - } - - public FarrelitePriestResetEffect(final FarrelitePriestResetEffect effect) { - super(effect); - } - - @Override - public FarrelitePriestResetEffect copy() { - return new FarrelitePriestResetEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Integer amount = (Integer) game.getState().getValue(source.getSourceId().toString() + "FarrelitePriest"); - if (amount != null && amount >= 4) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - permanent.sacrifice(source.getSourceId(), game); - } - } - game.getState().setValue(source.getSourceId().toString() + "FarrelitePriest", null); - - return true; - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/fallenempires/InitiatesOfTheEbonHand.java b/Mage.Sets/src/mage/sets/fallenempires/InitiatesOfTheEbonHand.java index 6ec6d8beb7d..64b3b57cb84 100644 --- a/Mage.Sets/src/mage/sets/fallenempires/InitiatesOfTheEbonHand.java +++ b/Mage.Sets/src/mage/sets/fallenempires/InitiatesOfTheEbonHand.java @@ -31,19 +31,20 @@ import java.util.UUID; import mage.MageInt; import static mage.Mana.BlackMana; import mage.abilities.Ability; +import mage.abilities.ActivationInfo; import mage.abilities.DelayedTriggeredAbility; -import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.BasicManaEffect; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.mana.SimpleManaAbility; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; import mage.game.Game; -import mage.game.permanent.Permanent; /** * @@ -59,11 +60,11 @@ public class InitiatesOfTheEbonHand extends CardImpl { this.toughness = new MageInt(1); // {1}: Add {B} to your mana pool. If this ability has been activated four or more times this turn, sacrifice Initiates of the Ebon Hand at the beginning of the next end step. - SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + SimpleManaAbility ability = new SimpleManaAbility(Zone.BATTLEFIELD, new BasicManaEffect(BlackMana(1)), new ManaCostsImpl("{1}")); ability.addEffect(new InitiatesOfTheEbonHandEffect()); - this.addAbility(ability); + this.addAbility(ability); } public InitiatesOfTheEbonHand(final InitiatesOfTheEbonHand card) { @@ -94,46 +95,13 @@ class InitiatesOfTheEbonHandEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Integer amount = (Integer) game.getState().getValue(source.getSourceId().toString() + "InitiatesOfTheEbonHand"); - if (amount == null) { - amount = 0; - DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new InitiatesOfTheEbonHandResetEffect()); + ActivationInfo activationInfo = ActivationInfo.getInstance(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); + activationInfo.addActivation(game); + if (activationInfo.getActivationCounter() == 4) { + DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new SacrificeSourceEffect()); game.addDelayedTriggeredAbility(delayedAbility, source); } - amount++; - game.getState().setValue(source.getSourceId().toString() + "InitiatesOfTheEbonHand", amount); - return true; } + } - -class InitiatesOfTheEbonHandResetEffect extends OneShotEffect { - - public InitiatesOfTheEbonHandResetEffect() { - super(Outcome.Neutral); - this.staticText = "If this ability has been activated four or more times this turn, sacrifice {this} at the beginning of the next end step"; - } - - public InitiatesOfTheEbonHandResetEffect(final InitiatesOfTheEbonHandResetEffect effect) { - super(effect); - } - - @Override - public InitiatesOfTheEbonHandResetEffect copy() { - return new InitiatesOfTheEbonHandResetEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Integer amount = (Integer) game.getState().getValue(source.getSourceId().toString() + "InitiatesOfTheEbonHand"); - if (amount != null && amount >= 4) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - permanent.sacrifice(source.getSourceId(), game); - } - } - game.getState().setValue(source.getSourceId().toString() + "InitiatesOfTheEbonHand", null); - - return true; - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/journeyintonyx/BrainMaggot.java b/Mage.Sets/src/mage/sets/journeyintonyx/BrainMaggot.java index dd4a185cce2..ee3fb7215d3 100644 --- a/Mage.Sets/src/mage/sets/journeyintonyx/BrainMaggot.java +++ b/Mage.Sets/src/mage/sets/journeyintonyx/BrainMaggot.java @@ -49,7 +49,6 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; -import mage.game.permanent.PermanentToken; import mage.players.Player; import mage.target.TargetCard; import mage.target.common.TargetOpponent; @@ -188,8 +187,7 @@ class BrainMaggotReturnExiledCardEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = source.getSourceObject(game); if (sourceObject != null && controller != null) { - int zoneChangeCounter = (sourceObject instanceof PermanentToken) ? source.getSourceObjectZoneChangeCounter() : source.getSourceObjectZoneChangeCounter() - 1; - ExileZone exile = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source.getSourceId(), zoneChangeCounter)); + ExileZone exile = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter())); Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); if (exile != null && sourcePermanent != null) { controller.moveCards(exile, Zone.HAND, source, game); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/LimitedCountedActivationsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/LimitedCountedActivationsTest.java index 15fdefd210f..250ba777cfa 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/LimitedCountedActivationsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/LimitedCountedActivationsTest.java @@ -155,4 +155,51 @@ public class LimitedCountedActivationsTest extends CardTestPlayerBase { assertLife(playerA, 16); assertLife(playerB, 15); } + + @Test + public void testDragonWhelpDontSacrificeNewObject() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 8); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); + // Flying + // {R}: Dragon Whelp gets +1/+0 until end of turn. If this ability has been activated four or more times this turn, sacrifice Dragon Whelp at the beginning of the next end step. + addCard(Zone.BATTLEFIELD, playerA, "Dragon Whelp", 1); // 3/3 + // Put target creature card from a graveyard onto the battlefield under your control. You lose life equal to its converted mana cost. + addCard(Zone.HAND, playerA, "Reanimate", 1); + // Target creature gains haste until end of turn. + addCard(Zone.HAND, playerA, "Unnatural Speed", 1); + + addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2); + // Destroy target nonartifact, nonblack creature. It can't be regenerated. + addCard(Zone.HAND, playerB, "Terror", 1); // {1}{B} + + activateAbility(1, PhaseStep.UPKEEP, playerA, "{R}: "); + activateAbility(1, PhaseStep.UPKEEP, playerA, "{R}: "); + activateAbility(1, PhaseStep.UPKEEP, playerA, "{R}: "); + activateAbility(1, PhaseStep.UPKEEP, playerA, "{R}: "); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Terror", "Dragon Whelp"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate", "Dragon Whelp"); + castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Unnatural Speed", "Dragon Whelp"); + + activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "{R}: "); + activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "{R}: "); + activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "{R}: "); + + attack(1, playerA, "Dragon Whelp"); + + setStopAt(2, PhaseStep.UPKEEP); + execute(); + + assertGraveyardCount(playerA, "Unnatural Speed", 1); + assertGraveyardCount(playerA, "Reanimate", 1); + + assertGraveyardCount(playerB, "Terror", 1); + + assertPermanentCount(playerA, "Dragon Whelp", 1); + assertPowerToughness(playerA, "Dragon Whelp", 2, 3); + assertGraveyardCount(playerA, "Dragon Whelp", 0); + + assertLife(playerA, 16); + assertLife(playerB, 15); + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/NecromancyTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/NecromancyTest.java index 5b2a9ae2f6c..4cf62035433 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/NecromancyTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/NecromancyTest.java @@ -25,7 +25,6 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package org.mage.test.cards.abilities.other; import mage.constants.PhaseStep; @@ -39,20 +38,18 @@ import org.mage.test.serverside.base.CardTestPlayerBase; */ public class NecromancyTest extends CardTestPlayerBase { - /** - * Necromancy - * Enchantment, 2B (3) - * You may cast Necromancy as though it had flash. If you cast it any time a - * sorcery couldn't have been cast, the controller of the permanent it - * becomes sacrifices it at the beginning of the next cleanup step. - * When Necromancy enters the battlefield, if it's on the battlefield, it - * becomes an Aura with "enchant creature put onto the battlefield with - * Necromancy." Put target creature card from a graveyard onto the - * battlefield under your control and attach Necromancy to it. When - * Necromancy leaves the battlefield, that creature's controller sacrifices it. + /** + * Necromancy Enchantment, 2B (3) You may cast Necromancy as though it had + * flash. If you cast it any time a sorcery couldn't have been cast, the + * controller of the permanent it becomes sacrifices it at the beginning of + * the next cleanup step. When Necromancy enters the battlefield, if it's on + * the battlefield, it becomes an Aura with "enchant creature put onto the + * battlefield with Necromancy." Put target creature card from a graveyard + * onto the battlefield under your control and attach Necromancy to it. When + * Necromancy leaves the battlefield, that creature's controller sacrifices + * it. * */ - @Test public void testNecromancy() { addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); @@ -60,7 +57,7 @@ public class NecromancyTest extends CardTestPlayerBase { addCard(Zone.GRAVEYARD, playerA, "Craw Wurm"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Necromancy"); - + setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); @@ -77,7 +74,7 @@ public class NecromancyTest extends CardTestPlayerBase { addCard(Zone.GRAVEYARD, playerA, "Craw Wurm"); castSpell(1, PhaseStep.UPKEEP, playerA, "Necromancy"); - + setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); @@ -87,14 +84,20 @@ public class NecromancyTest extends CardTestPlayerBase { } + /** + * Check if Necromancy is sacrificed if cast as instant and if the + * reanimated creature will be sacrificed. + */ @Test public void testNecromancyFlashSacrifice() { addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); + // If you cast it any time a sorcery couldn't have been cast, the controller of the permanent it becomes sacrifices it at the beginning of the next cleanup step. + // When Necromancy leaves the battlefield, that creature's controller sacrifices it. addCard(Zone.HAND, playerA, "Necromancy"); - addCard(Zone.GRAVEYARD, playerA, "Craw Wurm"); + addCard(Zone.GRAVEYARD, playerA, "Craw Wurm"); // 6/4 castSpell(1, PhaseStep.UPKEEP, playerA, "Necromancy"); - + setStopAt(2, PhaseStep.BEGIN_COMBAT); execute(); @@ -114,7 +117,7 @@ public class NecromancyTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Necromancy"); // enchanting the Craw Wurm castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Disenchant", "Necromancy"); // if Necromancy leaves, the enchanted creature has to leave too - + setStopAt(1, PhaseStep.END_TURN); execute(); @@ -124,5 +127,5 @@ public class NecromancyTest extends CardTestPlayerBase { assertGraveyardCount(playerA, "Necromancy", 1); assertGraveyardCount(playerA, "Craw Wurm", 1); } - + } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/BrainMaggotTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/BrainMaggotTest.java index 5bfd5cab697..49b840a07bb 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/BrainMaggotTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/BrainMaggotTest.java @@ -36,13 +36,13 @@ import org.mage.test.serverside.base.CardTestPlayerBase; * * @author LevelX2 */ - public class BrainMaggotTest extends CardTestPlayerBase { /** - * When Brain Maggot enters the battlefield, target opponent reveals his or her hand and - * you choose a nonland card from it. Exile that card until Brain Maggot leaves the battlefield. - * + * When Brain Maggot enters the battlefield, target opponent reveals his or + * her hand and you choose a nonland card from it. Exile that card until + * Brain Maggot leaves the battlefield. + * */ @Test public void testCardFromHandWillBeExiled() { @@ -61,10 +61,10 @@ public class BrainMaggotTest extends CardTestPlayerBase { assertExileCount("Bloodflow Connoisseur", 1); } - @Test public void testCardFromHandWillBeExiledAndReturn() { addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2); + // When Brain Maggot enters the battlefield, target opponent reveals his or her hand and you choose a nonland card from it. Exile that card until Brain Maggot leaves the battlefield. addCard(Zone.HAND, playerA, "Brain Maggot", 2); addCard(Zone.HAND, playerB, "Bloodflow Connoisseur", 1); @@ -105,4 +105,4 @@ public class BrainMaggotTest extends CardTestPlayerBase { assertHandCount(playerB, "Bloodflow Connoisseur", 1); assertExileCount("Bloodflow Connoisseur", 0); } -} \ No newline at end of file +} diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java index cb4de5e1ecf..497fc66ddbb 100644 --- a/Mage/src/main/java/mage/abilities/AbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java @@ -1191,8 +1191,6 @@ public abstract class AbilityImpl implements Ability { public void setSourceObject(MageObject sourceObject, Game game) { if (sourceObject == null) { this.sourceObject = game.getObject(sourceId); - // if permanent get card /permanent instead of spell - } else { this.sourceObject = sourceObject; } diff --git a/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java b/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java index 016369ac856..54e6926dcc6 100644 --- a/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java @@ -70,7 +70,9 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge public void trigger(Game game, UUID controllerId) { //20091005 - 603.4 if (checkInterveningIfClause(game)) { - setSourceObject(null, game); + if (!(this instanceof DelayedTriggeredAbility)) { + setSourceObject(null, game); + } game.addTriggeredAbility(this); } } diff --git a/Mage/src/main/java/mage/abilities/common/delayed/OnLeaveReturnExiledToBattlefieldAbility.java b/Mage/src/main/java/mage/abilities/common/delayed/OnLeaveReturnExiledToBattlefieldAbility.java index 3da2208a19c..996b05d9c67 100644 --- a/Mage/src/main/java/mage/abilities/common/delayed/OnLeaveReturnExiledToBattlefieldAbility.java +++ b/Mage/src/main/java/mage/abilities/common/delayed/OnLeaveReturnExiledToBattlefieldAbility.java @@ -40,7 +40,6 @@ import mage.game.ExileZone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; -import mage.game.permanent.PermanentToken; import mage.players.Player; import mage.util.CardUtil; @@ -107,8 +106,7 @@ class ReturnExiledPermanentsEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = source.getSourceObject(game); if (sourceObject != null && controller != null) { - int zoneChangeCounter = (sourceObject instanceof PermanentToken) ? source.getSourceObjectZoneChangeCounter() : source.getSourceObjectZoneChangeCounter() - 1; - UUID exileZone = CardUtil.getExileZoneId(game, source.getSourceId(), zoneChangeCounter); + UUID exileZone = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); if (exileZone != null) { ExileZone exile = game.getExile().getExileZone(exileZone); if (exile != null) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java index bb1f89ea2cf..2dfc09db98e 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java @@ -1,16 +1,16 @@ /* * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR @@ -20,12 +20,11 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.abilities.effects.common; import mage.MageObject; @@ -34,6 +33,7 @@ import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.game.stack.Spell; /** * @@ -58,6 +58,15 @@ public class SacrificeSourceEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { MageObject sourceObject = source.getSourceObjectIfItStillExists(game); + if (sourceObject == null) { + // Check if the effect was installed by the spell the source was cast by (e.g. Necromancy), if not don't sacrifice the permanent + if (source.getSourceObject(game) instanceof Spell) { + sourceObject = game.getPermanent(source.getSourceId()); + if (sourceObject.getZoneChangeCounter(game) > source.getSourceObjectZoneChangeCounter() + 1) { + return false; + } + } + } if (sourceObject instanceof Permanent) { Permanent permanent = (Permanent) sourceObject; // you can only sacrifice a permanent you control