diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java index b91a39db1e4..7f33bc8604a 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java @@ -19,11 +19,13 @@ package forge.game.trigger; import java.util.*; +import com.google.common.base.Predicates; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Iterables; import com.google.common.collect.ListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Multimaps; +import com.google.common.collect.Table.Cell; import forge.game.CardTraitBase; import forge.game.CardTraitPredicates; @@ -445,29 +447,71 @@ public class TriggerHandler { // Torpor Orb check if (game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.noCreatureETBTriggers) - && !regtrig.isStatic() && mode.equals(TriggerType.ChangesZone)) { - if (runParams.get(AbilityKey.Destination) instanceof String) { - final String dest = (String) runParams.get(AbilityKey.Destination); - if (dest.equals("Battlefield") && runParams.get(AbilityKey.Card) instanceof Card) { - final Card card = (Card) runParams.get(AbilityKey.Card); - if (card.isCreature()) { - return false; + && !regtrig.isStatic()) { + if (mode.equals(TriggerType.ChangesZone)) { + if (runParams.get(AbilityKey.Destination) instanceof String) { + final String dest = (String) runParams.get(AbilityKey.Destination); + if (dest.equals("Battlefield") && runParams.get(AbilityKey.Card) instanceof Card) { + final Card card = (Card) runParams.get(AbilityKey.Card); + if (card.isCreature()) { + return false; + } } } + } else if (mode.equals(TriggerType.ChangesZoneAll)) { + CardZoneTable table = (CardZoneTable) runParams.get(AbilityKey.Cards); + // find out if any other cards would still trigger it + boolean found = false; + for (Cell cell : table.cellSet()) { + // this currently assumes the table will not contain multiple destinations + // however with some effects (e.g. Goblin Welder) that should indeed be the case + // once Forge handles that correctly this section needs to account for that + // (by doing a closer check of the triggered ability first) + if (cell.getColumnKey() != ZoneType.Battlefield) { + found = true; + } else if (Iterables.any(cell.getValue(), Predicates.not(CardPredicates.isType("Creature")))) { + found = true; + } + if (found) break; + } + if (!found) { + return false; + } } } // Torpor Orb check if (game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.noCreatureDyingTriggers) - && !regtrig.isStatic() && mode.equals(TriggerType.ChangesZone)) { - if (runParams.get(AbilityKey.Destination) instanceof String && runParams.get(AbilityKey.Origin) instanceof String) { - final String dest = (String) runParams.get(AbilityKey.Destination); - final String origin = (String) runParams.get(AbilityKey.Origin); - if (dest.equals("Graveyard") && origin.equals("Battlefield") && runParams.get(AbilityKey.Card) instanceof Card) { - final Card card = (Card) runParams.get(AbilityKey.Card); - if (card.isCreature()) { - return false; + && !regtrig.isStatic()) { + if (mode.equals(TriggerType.ChangesZone)) { + if (runParams.get(AbilityKey.Destination) instanceof String && runParams.get(AbilityKey.Origin) instanceof String) { + final String dest = (String) runParams.get(AbilityKey.Destination); + final String origin = (String) runParams.get(AbilityKey.Origin); + if (dest.equals("Graveyard") && origin.equals("Battlefield") && runParams.get(AbilityKey.Card) instanceof Card) { + // It will trigger if the ability is of a dying creature that triggers only when that creature is put into a graveyard from anywhere + if (!"Card.Self".equals(regtrig.getParam("ValidCard")) || (regtrig.hasParam("Origin") && !"Any".equals(regtrig.getParam("Origin")))) { + final Card card = (Card) runParams.get(AbilityKey.Card); + if (card.isCreature()) { + return false; + } + } } } + } else if (mode.equals(TriggerType.ChangesZoneAll)) { + CardZoneTable table = (CardZoneTable) runParams.get(AbilityKey.Cards); + boolean found = false; + for (Cell cell : table.cellSet()) { + if (cell.getRowKey() != ZoneType.Battlefield) { + found = true; + } else if (cell.getColumnKey() != ZoneType.Graveyard) { + found = true; + } else if (Iterables.any(cell.getValue(), Predicates.not(CardPredicates.isType("Creature")))) { + found = true; + } + if (found) break; + } + if (!found) { + return false; + } } } return true; diff --git a/forge-gui/res/cardsfolder/s/soul_of_emancipation.txt b/forge-gui/res/cardsfolder/s/soul_of_emancipation.txt index a434c8fa7c5..99a84b94924 100644 --- a/forge-gui/res/cardsfolder/s/soul_of_emancipation.txt +++ b/forge-gui/res/cardsfolder/s/soul_of_emancipation.txt @@ -4,7 +4,8 @@ Types:Creature Avatar PT:5/7 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDestroy | TriggerDescription$ When CARDNAME enters the battlefield, destroy up to three other target nonland permanents. For each of those permanents, its controller creates a 3/3 white Angel creature token with flying. SVar:TrigDestroy:DB$ Destroy | TargetMin$ 0 | TargetMax$ 3 | ValidTgts$ Permanent.nonLand | TgtPrompt$ Choose up to three nonland permanents | RememberTargets$ True | SubAbility$ MakeTokens -SVar:MakeTokens:DB$ RepeatEach | RepeatSubAbility$ DBToken | DefinedCards$ Remembered | UseImprinted$ True | ChangeZoneTable$ True +SVar:MakeTokens:DB$ RepeatEach | RepeatSubAbility$ DBToken | DefinedCards$ Remembered | UseImprinted$ True | ChangeZoneTable$ True | SubAbility$ DBCleanup SVar:DBToken:DB$ Token | TokenScript$ w_3_3_angel_flying | TokenOwner$ ImprintedController +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True DeckHas:Ability$Token & Type$Angel Oracle:When Soul of Emancipation enters the battlefield, destroy up to three other target nonland permanents. For each of those permanents, its controller creates a 3/3 white Angel creature token with flying.