diff --git a/Mage.Sets/src/mage/sets/alliances/PhyrexianDevourer.java b/Mage.Sets/src/mage/sets/alliances/PhyrexianDevourer.java
index a7ba4876f7..36a4e5d6da 100644
--- a/Mage.Sets/src/mage/sets/alliances/PhyrexianDevourer.java
+++ b/Mage.Sets/src/mage/sets/alliances/PhyrexianDevourer.java
@@ -27,8 +27,6 @@
*/
package mage.sets.alliances;
-import java.util.ArrayList;
-import java.util.List;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
@@ -100,10 +98,7 @@ class PhyrexianDevourerStateTriggeredAbility extends StateTriggeredAbility {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent permanent = game.getPermanent(getSourceId());
- if(permanent != null && permanent.getPower().getValue() >= 7){
- return true;
- }
- return false;
+ return permanent != null && permanent.getPower().getValue() >= 7;
}
@Override
@@ -134,9 +129,9 @@ class PhyrexianDevourerEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Card card = null;
- for (Cost cost: source.getCosts()) {
+ for (Cost cost : source.getCosts()) {
if (cost instanceof ExileTopCardLibraryCost) {
- card = ((ExileTopCardLibraryCost)cost).getCard();
+ card = ((ExileTopCardLibraryCost) cost).getCard();
}
}
if (card != null) {
@@ -170,7 +165,7 @@ class ExileTopCardLibraryCost extends CostImpl {
if (controller != null) {
card = controller.getLibrary().getFromTop(game);
if (card != null) {
- paid = controller.moveCardToExileWithInfo(card, null, "", sourceId, game, Zone.LIBRARY, true);
+ paid = controller.moveCards(card, null, Zone.EXILED, ability, game);
}
}
return paid;
diff --git a/Mage.Sets/src/mage/sets/avacynrestored/Cloudshift.java b/Mage.Sets/src/mage/sets/avacynrestored/Cloudshift.java
index 49d0848213..42c785000e 100644
--- a/Mage.Sets/src/mage/sets/avacynrestored/Cloudshift.java
+++ b/Mage.Sets/src/mage/sets/avacynrestored/Cloudshift.java
@@ -27,15 +27,15 @@
*/
package mage.sets.avacynrestored;
-import mage.constants.CardType;
-import mage.constants.Rarity;
+import java.util.UUID;
+import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ExileTargetForSourceEffect;
import mage.abilities.effects.common.ReturnToBattlefieldUnderYourControlTargetEffect;
import mage.cards.CardImpl;
+import mage.constants.CardType;
+import mage.constants.Rarity;
import mage.target.common.TargetControlledCreaturePermanent;
-import java.util.UUID;
-
/**
*
* @author noxx
@@ -46,10 +46,11 @@ public class Cloudshift extends CardImpl {
super(ownerId, 12, "Cloudshift", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{W}");
this.expansionSetCode = "AVR";
-
// Exile target creature you control, then return that card to the battlefield under your control.
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
- this.getSpellAbility().addEffect(new ExileTargetForSourceEffect());
+ Effect effect = new ExileTargetForSourceEffect();
+ effect.setApplyEffectsAfter();
+ this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addEffect(new ReturnToBattlefieldUnderYourControlTargetEffect(true));
}
diff --git a/Mage.Sets/src/mage/sets/shadowmoor/LureboundScarecrow.java b/Mage.Sets/src/mage/sets/shadowmoor/LureboundScarecrow.java
index fc6cd8c6ce..9ab3c91bb7 100644
--- a/Mage.Sets/src/mage/sets/shadowmoor/LureboundScarecrow.java
+++ b/Mage.Sets/src/mage/sets/shadowmoor/LureboundScarecrow.java
@@ -35,7 +35,6 @@ import mage.abilities.StateTriggeredAbility;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.SacrificeSourceEffect;
-import mage.cards.Card;
import mage.cards.CardImpl;
import mage.choices.ChoiceColor;
import mage.constants.CardType;
@@ -127,20 +126,16 @@ class LureboundScarecrowTriggeredAbility extends StateTriggeredAbility {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
- if (event.getType() == GameEvent.EventType.ZONE_CHANGE || event.getType() == GameEvent.EventType.LOST_CONTROL
- || event.getType() == GameEvent.EventType.COLOR_CHANGED
- || event.getType() == GameEvent.EventType.SPELL_CAST) {
- Card card = game.getCard(this.getSourceId());
- if (card != null) {
- ObjectColor color = (ObjectColor) game.getState().getValue(card.getId() + "_color");
- if (color != null) {
- for (Permanent perm : game.getBattlefield().getAllActivePermanents(controllerId)) {
- if (perm.getColor(game).contains(color)) {
- return false;
- }
+ Permanent permanent = game.getPermanent(getSourceId());
+ if (permanent != null) {
+ ObjectColor color = (ObjectColor) game.getState().getValue(getSourceId() + "_color");
+ if (color != null) {
+ for (Permanent perm : game.getBattlefield().getAllActivePermanents(controllerId)) {
+ if (perm.getColor(game).contains(color)) {
+ return false;
}
- return true;
}
+ return true;
}
}
return false;
diff --git a/Mage.Sets/src/mage/sets/shardsofalara/ImmortalCoil.java b/Mage.Sets/src/mage/sets/shardsofalara/ImmortalCoil.java
index 1b3d3fb54a..b8307e5cc7 100644
--- a/Mage.Sets/src/mage/sets/shardsofalara/ImmortalCoil.java
+++ b/Mage.Sets/src/mage/sets/shardsofalara/ImmortalCoil.java
@@ -28,8 +28,6 @@
package mage.sets.shardsofalara;
import java.util.UUID;
-
-import mage.constants.*;
import mage.abilities.Ability;
import mage.abilities.StateTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
@@ -42,6 +40,11 @@ import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.SacrificeSourceEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
+import mage.constants.CardType;
+import mage.constants.Duration;
+import mage.constants.Outcome;
+import mage.constants.Rarity;
+import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.game.events.GameEvent;
@@ -58,7 +61,6 @@ public class ImmortalCoil extends CardImpl {
super(ownerId, 79, "Immortal Coil", Rarity.RARE, new CardType[]{CardType.ARTIFACT}, "{2}{B}{B}");
this.expansionSetCode = "ALA";
-
// {tap}, Exile two cards from your graveyard: Draw a card.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), new TapSourceCost());
ability.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard(2, new FilterCard("cards from your graveyard"))));
@@ -98,10 +100,7 @@ class ImmortalCoilAbility extends StateTriggeredAbility {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Player player = game.getPlayer(this.getControllerId());
- if(player != null && player.getGraveyard().size() == 0){
- return true;
- }
- return false;
+ return player != null && player.getGraveyard().size() == 0;
}
@Override
@@ -130,7 +129,7 @@ class LoseGameEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
- if (player != null) {
+ if (player != null) {
player.lost(game);
return true;
}
@@ -140,7 +139,6 @@ class LoseGameEffect extends OneShotEffect {
class PreventAllDamageToControllerEffect extends PreventionEffectImpl {
-
public PreventAllDamageToControllerEffect() {
super(Duration.WhileOnBattlefield);
staticText = "If damage would be dealt to you, prevent that damage. Exile a card from your graveyard for each 1 damage prevented this way";
@@ -166,10 +164,10 @@ class PreventAllDamageToControllerEffect extends PreventionEffectImpl {
if (!game.replaceEvent(preventEvent)) {
int damage = event.getAmount();
Player player = game.getPlayer(source.getControllerId());
- if(player != null){
- TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(Math.min(damage, player.getGraveyard().size()), new FilterCard());
+ if (player != null) {
+ TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(Math.min(damage, player.getGraveyard().size()), new FilterCard());
if (target.choose(Outcome.Exile, source.getControllerId(), source.getSourceId(), game)) {
- for (UUID targetId: target.getTargets()) {
+ for (UUID targetId : target.getTargets()) {
Card card = player.getGraveyard().get(targetId, game);
if (card != null) {
card.moveToZone(Zone.EXILED, source.getSourceId(), game, false);
@@ -186,7 +184,7 @@ class PreventAllDamageToControllerEffect extends PreventionEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (super.applies(event, source, game)) {
- if (event.getTargetId().equals(source.getControllerId())){
+ if (event.getTargetId().equals(source.getControllerId())) {
return true;
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/state/PhyrexianDevourerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/state/PhyrexianDevourerTest.java
new file mode 100644
index 0000000000..8b62413c14
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/state/PhyrexianDevourerTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * 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 org.mage.test.cards.triggers.state;
+
+import mage.constants.PhaseStep;
+import mage.constants.Zone;
+import org.junit.Test;
+import org.mage.test.serverside.base.CardTestPlayerBase;
+
+/**
+ *
+ * @author LevelX2
+ */
+public class PhyrexianDevourerTest extends CardTestPlayerBase {
+
+ /**
+ * Check that Phyrexian Devourer is sacrifriced as soon as the counters are
+ * added
+ *
+ */
+ @Test
+ public void testBoostChecked() {
+ // When Phyrexian Devourer's power is 7 or greater, sacrifice it.
+ // Exile the top card of your library: Put X +1/+1 counters on Phyrexian Devourer, where X is the exiled card's converted mana cost.
+ addCard(Zone.BATTLEFIELD, playerA, "Phyrexian Devourer");
+ addCard(Zone.LIBRARY, playerA, "Phyrexian Devourer");
+ skipInitShuffling();
+
+ addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion");
+
+ attack(2, playerB, "Silvercoat Lion");
+ block(2, playerA, "Phyrexian Devourer", "Silvercoat Lion");
+
+ activateAbility(2, PhaseStep.DECLARE_BLOCKERS, playerA, "Exile the top card of your library");
+
+ setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
+ execute();
+
+ assertGraveyardCount(playerA, "Phyrexian Devourer", 1);
+ assertExileCount("Phyrexian Devourer", 1);
+
+ assertPermanentCount(playerB, "Silvercoat Lion", 1);
+
+ }
+
+}
diff --git a/Mage.Tests/src/test/java/org/mage/test/commander/duel/AnafenzaTest.java b/Mage.Tests/src/test/java/org/mage/test/commander/duel/AnafenzaTest.java
index aa0eda13c9..109b704982 100644
--- a/Mage.Tests/src/test/java/org/mage/test/commander/duel/AnafenzaTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/commander/duel/AnafenzaTest.java
@@ -92,4 +92,51 @@ public class AnafenzaTest extends CardTestCommanderDuelBase {
}
+ /**
+ * Token don't go to exile because they are no creature cards
+ */
+ @Test
+ public void testAnafenzaExileInCombatOmnathToken() {
+ addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Acidic Slime", 1);
+
+ addCard(Zone.HAND, playerB, "Forest", 2);
+ // Landfall - Whenever a land enters the battlefield under your control, put a 5/5 red and green Elemental creature token onto the battlefield.
+ // Whenever Omnath, Locus of Rage or another Elemental you control dies, Omnath deals 3 damage to target creature or player.
+ addCard(Zone.BATTLEFIELD, playerB, "Omnath, Locus of Rage", 1);
+
+ // Whenever Anafenza, the Foremost attacks, put a +1/+1 counter on another target tapped creature you control.
+ // If a creature card would be put into an opponent's graveyard from anywhere, exile it instead.
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Anafenza, the Foremost");
+
+ playLand(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Forest");
+ playLand(4, PhaseStep.PRECOMBAT_MAIN, playerB, "Forest");
+
+ attack(5, playerA, "Acidic Slime");
+ block(5, playerB, "Elemental", "Acidic Slime");
+ attack(5, playerA, "Anafenza, the Foremost");
+ block(5, playerB, "Elemental", "Anafenza, the Foremost");
+ addTarget(playerB, playerA);
+
+ setStopAt(5, PhaseStep.POSTCOMBAT_MAIN);
+ execute();
+
+ assertExileCount(playerA, 0);
+ assertExileCount(playerB, 0);
+
+ assertPermanentCount(playerB, "Elemental", 1);
+
+ assertGraveyardCount(playerA, "Acidic Slime", 1);
+ assertGraveyardCount(playerA, "Anafenza, the Foremost", 0);
+ assertCommandZoneCount(playerA, "Anafenza, the Foremost", 1);
+
+ assertHandCount(playerA, 2); // turn 3 + 5 draw
+ assertHandCount(playerB, 2); // turn 2 + 4 draw
+
+ assertLife(playerA, 37);
+ assertLife(playerB, 40);
+ }
+
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java
index 664d665ecf..1114d2d073 100644
--- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java
+++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java
@@ -585,7 +585,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
actualCount++;
}
}
- Assert.assertEquals("(Battlefield) Card counts are not equal (" + commandZoneObjectName + ")", count, actualCount);
+ Assert.assertEquals("(Command Zone) Card counts are not equal (" + commandZoneObjectName + ")", count, actualCount);
}
/**
@@ -777,7 +777,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
*/
public void assertHandCount(Player player, int count) throws AssertionError {
int actual = currentGame.getPlayer(player.getId()).getHand().size();
- Assert.assertEquals("(Hand) Card counts are not equal ", count, actual);
+ Assert.assertEquals("(Hand " + player.getName() + ") Card counts are not equal ", count, actual);
}
/**
diff --git a/Mage/src/mage/abilities/AbilityImpl.java b/Mage/src/mage/abilities/AbilityImpl.java
index d9723850a2..7006eeebdc 100644
--- a/Mage/src/mage/abilities/AbilityImpl.java
+++ b/Mage/src/mage/abilities/AbilityImpl.java
@@ -237,6 +237,7 @@ public abstract class AbilityImpl implements Ability {
*/
if (effect.applyEffectsAfter()) {
game.applyEffects();
+ game.getState().getTriggers().checkStateTriggers(game);
}
}
}
diff --git a/Mage/src/mage/abilities/StateTriggeredAbility.java b/Mage/src/mage/abilities/StateTriggeredAbility.java
index 1c8cfadfb3..45425d8b32 100644
--- a/Mage/src/mage/abilities/StateTriggeredAbility.java
+++ b/Mage/src/mage/abilities/StateTriggeredAbility.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;
import java.util.UUID;
@@ -48,8 +47,7 @@ public abstract class StateTriggeredAbility extends TriggeredAbilityImpl {
super(ability);
}
- @Override
- public final boolean checkEventType(GameEvent event, Game game) {
+ public boolean canTrigger(Game game) {
//20100716 - 603.8
Boolean triggered = (Boolean) game.getState().getValue(getSourceId().toString() + "triggered");
if (triggered == null) {
@@ -58,7 +56,11 @@ public abstract class StateTriggeredAbility extends TriggeredAbilityImpl {
return !triggered;
}
-
+ @Override
+ public final boolean checkEventType(GameEvent event, Game game) {
+ return false;
+ }
+
@Override
public void trigger(Game game, UUID controllerId) {
//20100716 - 603.8
@@ -71,7 +73,7 @@ public abstract class StateTriggeredAbility extends TriggeredAbilityImpl {
//20100716 - 603.8
boolean result = super.resolve(game);
game.getState().setValue(this.getSourceId().toString() + "triggered", Boolean.FALSE);
- return result;
+ return result;
}
public void counter(Game game) {
diff --git a/Mage/src/mage/abilities/TriggeredAbilities.java b/Mage/src/mage/abilities/TriggeredAbilities.java
index 969e3cb78f..599e44068c 100644
--- a/Mage/src/mage/abilities/TriggeredAbilities.java
+++ b/Mage/src/mage/abilities/TriggeredAbilities.java
@@ -69,45 +69,57 @@ public class TriggeredAbilities extends ConcurrentHashMap it = this.values().iterator(); it.hasNext();) {
+ TriggeredAbility ability = it.next();
+ if (ability instanceof StateTriggeredAbility && ((StateTriggeredAbility) ability).canTrigger(game)) {
+ checkTrigger(ability, null, game);
+ }
+ }
+ }
+
public void checkTriggers(GameEvent event, Game game) {
for (Iterator it = this.values().iterator(); it.hasNext();) {
TriggeredAbility ability = it.next();
- if (!ability.checkEventType(event, game)) {
- continue;
+ if (ability.checkEventType(event, game)) {
+ checkTrigger(ability, event, game);
}
- // for effects like when leaves battlefield or destroyed use ShortLKI to check if permanent was in the correct zone before (e.g. Oblivion Ring or Karmic Justice)
- MageObject object = game.getObject(ability.getSourceId());
- if (ability.isInUseableZone(game, object, event)) {
- if (!game.getContinuousEffects().preventedByRuleModification(event, ability, game, false)) {
- if (object != null) {
- boolean controllerSet = false;
- if (!ability.getZone().equals(Zone.COMMAND) && event.getTargetId() != null && event.getTargetId().equals(ability.getSourceId())
- && (event.getType().equals(EventType.ZONE_CHANGE) || event.getType().equals(EventType.DESTROYED_PERMANENT))) {
- // need to check if object was face down for dies and destroy events because the ability triggers in the new zone, zone counter -1 is used
- Permanent permanent = (Permanent) game.getLastKnownInformation(ability.getSourceId(), Zone.BATTLEFIELD, ability.getSourceObjectZoneChangeCounter() - 1);
- if (permanent != null) {
- if (!ability.getWorksFaceDown() && permanent.isFaceDown(game)) {
- continue;
- }
- controllerSet = true;
- ability.setControllerId(permanent.getControllerId());
- }
- }
- if (!controllerSet) {
- if (object instanceof Permanent) {
- ability.setControllerId(((Permanent) object).getControllerId());
- } else if (object instanceof Spell) {
- // needed so that cast triggered abilities have to correct controller (e.g. Ulamog, the Infinite Gyre).
- ability.setControllerId(((Spell) object).getControllerId());
- } else if (object instanceof Card) {
- ability.setControllerId(((Card) object).getOwnerId());
- }
- }
- }
+ }
+ }
- if (ability.checkTrigger(event, game)) {
- ability.trigger(game, ability.getControllerId());
+ private void checkTrigger(TriggeredAbility ability, GameEvent event, Game game) {
+ // for effects like when leaves battlefield or destroyed use ShortLKI to check if permanent was in the correct zone before (e.g. Oblivion Ring or Karmic Justice)
+ MageObject object = game.getObject(ability.getSourceId());
+ if (ability.isInUseableZone(game, object, event)) {
+ if (event == null || !game.getContinuousEffects().preventedByRuleModification(event, ability, game, false)) {
+ if (object != null) {
+ boolean controllerSet = false;
+ if (!ability.getZone().equals(Zone.COMMAND) && event != null && event.getTargetId() != null && event.getTargetId().equals(ability.getSourceId())
+ && (event.getType().equals(EventType.ZONE_CHANGE) || event.getType().equals(EventType.DESTROYED_PERMANENT))) {
+ // need to check if object was face down for dies and destroy events because the ability triggers in the new zone, zone counter -1 is used
+ Permanent permanent = (Permanent) game.getLastKnownInformation(ability.getSourceId(), Zone.BATTLEFIELD, ability.getSourceObjectZoneChangeCounter() - 1);
+ if (permanent != null) {
+ if (!ability.getWorksFaceDown() && permanent.isFaceDown(game)) {
+ return;
+ }
+ controllerSet = true;
+ ability.setControllerId(permanent.getControllerId());
+ }
}
+ if (!controllerSet) {
+ if (object instanceof Permanent) {
+ ability.setControllerId(((Permanent) object).getControllerId());
+ } else if (object instanceof Spell) {
+ // needed so that cast triggered abilities have to correct controller (e.g. Ulamog, the Infinite Gyre).
+ ability.setControllerId(((Spell) object).getControllerId());
+ } else if (object instanceof Card) {
+ ability.setControllerId(((Card) object).getOwnerId());
+ }
+ }
+ }
+
+ if (ability.checkTrigger(event, game)) {
+ ability.trigger(game, ability.getControllerId());
}
}
}
diff --git a/Mage/src/mage/abilities/common/DiesThisOrAnotherCreatureTriggeredAbility.java b/Mage/src/mage/abilities/common/DiesThisOrAnotherCreatureTriggeredAbility.java
index 2e8aefd917..494c05fa7b 100644
--- a/Mage/src/mage/abilities/common/DiesThisOrAnotherCreatureTriggeredAbility.java
+++ b/Mage/src/mage/abilities/common/DiesThisOrAnotherCreatureTriggeredAbility.java
@@ -28,9 +28,9 @@
package mage.abilities.common;
import mage.MageObject;
-import mage.constants.Zone;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
+import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
@@ -67,7 +67,7 @@ public class DiesThisOrAnotherCreatureTriggeredAbility extends TriggeredAbilityI
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
-
+
@Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {
Permanent sourcePermanent;
@@ -81,24 +81,21 @@ public class DiesThisOrAnotherCreatureTriggeredAbility extends TriggeredAbilityI
}
return hasSourceObjectAbility(game, sourcePermanent, event);
}
-
+
@Override
public boolean checkTrigger(GameEvent event, Game game) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
- if (game.getPermanent(sourceId) == null) {
- if (game.getLastKnownInformation(sourceId, Zone.BATTLEFIELD) == null) {
- return false;
- }
+ if (game.getPermanentOrLKIBattlefield(getSourceId()) == null) {
+ return false;
}
if (zEvent.getFromZone() == Zone.BATTLEFIELD && zEvent.getToZone() == Zone.GRAVEYARD) {
- Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD);
- if (permanent != null) {
- if (permanent.getId().equals(this.getSourceId())) {
+ if (zEvent.getTarget() != null) {
+ if (zEvent.getTarget().getId().equals(this.getSourceId())) {
return true;
} else {
- if (filter.match(permanent, sourceId, controllerId, game)) {
+ if (filter.match(zEvent.getTarget(), sourceId, controllerId, game)) {
return true;
}
}
diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java
index 92014988e0..f1d6cf8b25 100644
--- a/Mage/src/mage/game/GameImpl.java
+++ b/Mage/src/mage/game/GameImpl.java
@@ -1464,6 +1464,7 @@ public abstract class GameImpl implements Game, Serializable {
*/
public boolean checkTriggered() {
boolean played = false;
+ state.getTriggers().checkStateTriggers(this);
for (UUID playerId : state.getPlayerList(state.getActivePlayerId())) {
Player player = getPlayer(playerId);
while (player.isInGame()) { // player can die or win caused by triggered abilities or leave the game