mirror of
https://github.com/correl/mage.git
synced 2024-12-24 03:00:14 +00:00
* Fixed that state triggered abilities were not checked at the correct times.
This commit is contained in:
parent
92f30f3f2f
commit
340398fb74
12 changed files with 217 additions and 97 deletions
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
// <i>Landfall</i> - 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -237,6 +237,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
*/
|
||||
if (effect.applyEffectsAfter()) {
|
||||
game.applyEffects();
|
||||
game.getState().getTriggers().checkStateTriggers(game);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -69,45 +69,57 @@ public class TriggeredAbilities extends ConcurrentHashMap<String, TriggeredAbili
|
|||
}
|
||||
}
|
||||
|
||||
public void checkStateTriggers(Game game) {
|
||||
for (Iterator<TriggeredAbility> 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<TriggeredAbility> 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue