diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set07/set07-Sauron.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set07/set07-Sauron.hjson index 66660a159..72c243ac7 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set07/set07-Sauron.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set07/set07-Sauron.hjson @@ -531,9 +531,10 @@ { type: trigger trigger: { - type: playedFromStacked + type: played filter: self from: controlledSite + fromZone: stacked } effect: { type: addBurdens @@ -649,9 +650,10 @@ { type: trigger trigger: { - type: playedFromStacked + type: played filter: self from: controlledSite + fromZone: stacked } effect: { type: addThreats diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set08/set08-Ringwraith.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set08/set08-Ringwraith.hjson index 258478fc2..4940504da 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set08/set08-Ringwraith.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set08/set08-Ringwraith.hjson @@ -269,9 +269,10 @@ type: trigger optional: true trigger: { - type: playedFromStacked + type: played filter: minion from: self + fromZone: stacked } effect: { type: exert diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set17/set17-Men.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set17/set17-Men.hjson index b00cd4ec4..45e2a0aa8 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set17/set17-Men.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set17/set17-Men.hjson @@ -633,7 +633,7 @@ trigger: { type: played filter: self - from: hand + fromZone: hand } effect: { type: choice @@ -1563,12 +1563,13 @@ { type: played filter: self - from: deck + fromZone: deck } { - type: playedFromStacked + type: played filter: self from: your,culture(men),possession + fromZone: stacked } ] effect: { diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set18/set18-Rohan.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set18/set18-Rohan.hjson index 0d6746066..4810e9e4e 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set18/set18-Rohan.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set18/set18-Rohan.hjson @@ -29,7 +29,7 @@ type: played player: you filter: culture(rohan),possession - from: hand + fromZone: hand } effect: { type: addTokens diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/second-edition/set40/set40-moria.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/second-edition/set40/set40-moria.hjson index 341f33a09..901025245 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/second-edition/set40/set40-moria.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/second-edition/set40/set40-moria.hjson @@ -246,9 +246,10 @@ type: trigger optional: true trigger: { - type: playedFromStacked + type: played filter: culture(moria),minion from: culture(moria),condition + fromZone: stacked } effect: { type: modifyStrength diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/PlayedFromStacked.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/PlayedFromStacked.java deleted file mode 100644 index 9b84eb440..000000000 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/PlayedFromStacked.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.gempukku.lotro.cards.build.field.effect.trigger; - -import com.gempukku.lotro.cards.build.ActionContext; -import com.gempukku.lotro.cards.build.CardGenerationEnvironment; -import com.gempukku.lotro.cards.build.FilterableSource; -import com.gempukku.lotro.cards.build.InvalidCardDefinitionException; -import com.gempukku.lotro.cards.build.field.FieldUtils; -import com.gempukku.lotro.common.Filterable; -import com.gempukku.lotro.game.PhysicalCard; -import com.gempukku.lotro.logic.timing.TriggerConditions; -import com.gempukku.lotro.logic.timing.results.PlayCardResult; -import org.json.simple.JSONObject; - -public class PlayedFromStacked implements TriggerCheckerProducer { - @Override - public TriggerChecker getTriggerChecker(JSONObject value, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { - FieldUtils.validateAllowedFields(value, "filter", "from", "memorize"); - - final String filterString = FieldUtils.getString(value.get("filter"), "filter"); - final String fromString = FieldUtils.getString(value.get("from"), "from"); - final String memorize = FieldUtils.getString(value.get("memorize"), "memorize"); - final FilterableSource filter = environment.getFilterFactory().generateFilter(filterString, environment); - final FilterableSource fromFilter = environment.getFilterFactory().generateFilter(fromString, environment); - return new TriggerChecker() { - @Override - public boolean accepts(ActionContext actionContext) { - final Filterable filterable = filter.getFilterable(actionContext); - final Filterable from = fromFilter.getFilterable(actionContext); - final boolean played = TriggerConditions.playedFromStacked(actionContext.getGame(), actionContext.getEffectResult(), from, filterable); - if (played && memorize != null) { - PhysicalCard playedCard = ((PlayCardResult) actionContext.getEffectResult()).getPlayedCard(); - actionContext.setCardMemory(memorize, playedCard); - } - return played; - } - - @Override - public boolean isBefore() { - return false; - } - }; - } -} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/PlayedTriggerCheckerProducer.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/PlayedTriggerCheckerProducer.java index 458ca489d..acda901c8 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/PlayedTriggerCheckerProducer.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/PlayedTriggerCheckerProducer.java @@ -5,7 +5,9 @@ import com.gempukku.lotro.cards.build.field.FieldUtils; import com.gempukku.lotro.cards.build.field.effect.appender.resolver.PlayerResolver; import com.gempukku.lotro.common.Filterable; import com.gempukku.lotro.common.Zone; +import com.gempukku.lotro.filters.Filters; import com.gempukku.lotro.game.PhysicalCard; +import com.gempukku.lotro.logic.timing.EffectResult; import com.gempukku.lotro.logic.timing.TriggerConditions; import com.gempukku.lotro.logic.timing.results.PlayCardResult; import com.gempukku.lotro.logic.timing.results.PlayEventResult; @@ -14,47 +16,55 @@ import org.json.simple.JSONObject; public class PlayedTriggerCheckerProducer implements TriggerCheckerProducer { @Override public TriggerChecker getTriggerChecker(JSONObject value, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { - FieldUtils.validateAllowedFields(value, "filter", "on", "memorize", "exertsRanger", "from", "player"); + FieldUtils.validateAllowedFields(value, "filter", "from", "fromZone", "player", "on", "memorize", "exertsRanger"); final String filterString = FieldUtils.getString(value.get("filter"), "filter"); + final String fromString = FieldUtils.getString(value.get("from"), "from"); + final String player = FieldUtils.getString(value.get("player"), "player"); final String onString = FieldUtils.getString(value.get("on"), "on"); final String memorize = FieldUtils.getString(value.get("memorize"), "memorize"); boolean exertsRanger = FieldUtils.getBoolean(value.get("exertsRanger"), "exertsRanger", false); + final FilterableSource filter = environment.getFilterFactory().generateFilter(filterString, environment); final FilterableSource onFilter = (onString != null) ? environment.getFilterFactory().generateFilter(onString, environment) : null; - Zone zone = FieldUtils.getEnum(Zone.class, value.get("from"), "from"); - String player = FieldUtils.getString(value.get("player"), "player"); + final FilterableSource fromFilter = (fromString != null) ? environment.getFilterFactory().generateFilter(fromString, environment): null; + final Zone zone = FieldUtils.getEnum(Zone.class, value.get("fromZone"), "fromZone"); + + //Squelch incoherent zone values + if (zone == Zone.FREE_CHARACTERS || zone == Zone.SHADOW_CHARACTERS || zone == Zone.ATTACHED || zone == Zone.ADVENTURE_PATH + || zone == Zone.SUPPORT || zone == Zone.VOID || zone == Zone.VOID_FROM_HAND ) + { + throw new InvalidCardDefinitionException("'fromZone' using an unsupported zone in Played trigger."); + } // TODO: this should be used by most cards - need to revise the HJSONs + // Not sure about that assertion. The vast majority are "when you play this" triggers, which has a "you" but + // that's an instruction to the acting player and not an assertion that it isn't in force if your opponent + // somehow plays the card for you. PlayerSource playerSource = player != null ? PlayerResolver.resolvePlayer(player, environment) : null; return new TriggerChecker() { @Override public boolean accepts(ActionContext actionContext) { final Filterable filterable = filter.getFilterable(actionContext); - boolean played; - if (onFilter != null) { - final Filterable onFilterable = onFilter.getFilterable(actionContext); - played = TriggerConditions.playedOn(actionContext.getGame(), actionContext.getEffectResult(), onFilterable, filterable); - } else { - played = TriggerConditions.played(actionContext.getGame(), actionContext.getEffectResult(), filterable); - } + final Filterable from = fromFilter != null ? fromFilter.getFilterable(actionContext) : null; + final Filterable on = onFilter != null ? onFilter.getFilterable(actionContext) : null; + + final boolean played = TriggerConditions.played(actionContext.getGame(), + actionContext.getEffectResult(), on, from, zone, filterable); if (played) { - PlayCardResult playCardResult = (PlayCardResult) actionContext.getEffectResult(); + var playCardResult = (PlayCardResult)actionContext.getEffectResult(); String playerId = playerSource != null ? playerSource.getPlayer(actionContext) : null; if (playerId != null && !playerId.equals(playCardResult.getPerformingPlayerId())) return false; - if (zone != null && playCardResult.getPlayedFrom() != zone) - return false; - if (exertsRanger && playCardResult instanceof PlayEventResult && !((PlayEventResult) playCardResult).isRequiresRanger()) return false; if (memorize != null) { - PhysicalCard playedCard = playCardResult.getPlayedCard(); + var playedCard = playCardResult.getPlayedCard(); actionContext.setCardMemory(memorize, playedCard); } } diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java index 168be45b9..4427de121 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java @@ -57,7 +57,6 @@ public class TriggerCheckerFactory { triggerCheckers.put("losesinitiative", new LosesInitiative()); triggerCheckers.put("losesskirmish", new LosesSkirmish()); triggerCheckers.put("played", new PlayedTriggerCheckerProducer()); - triggerCheckers.put("playedfromstacked", new PlayedFromStacked()); triggerCheckers.put("playerdrawscard", new PlayerDrawsCard()); triggerCheckers.put("putsonring", new PutsOnRing()); triggerCheckers.put("reconciles", new Reconciles()); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java index 993c6f996..ae8428f4a 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java @@ -354,34 +354,25 @@ public class TriggerConditions { return false; } - public static boolean played(LotroGame game, EffectResult effectResult, Filterable... filters) { + public static boolean played(LotroGame game, EffectResult effectResult, Filterable targetFilter, Filterable fromFilter, Zone fromZone, Filterable... filters) { if (effectResult.getType() == EffectResult.Type.PLAY) { - PhysicalCard playedCard = ((PlayCardResult) effectResult).getPlayedCard(); - return Filters.and(filters).accepts(game, playedCard); - } - return false; - } + final var playResult = (PlayCardResult) effectResult; + final var attachedTo = playResult.getAttachedTo(); + final var cardPlayedFrom = playResult.getAttachedOrStackedPlayedFrom(); + final var zone = playResult.getPlayedFrom(); - public static boolean playedFromStacked(LotroGame game, EffectResult effectResult, Filterable stackedOnFilter, Filterable... filters) { - if (effectResult.getType() == EffectResult.Type.PLAY) { - final PlayCardResult playResult = (PlayCardResult) effectResult; - PhysicalCard playedCard = playResult.getPlayedCard(); - return (playResult.getPlayedFrom() == Zone.STACKED - && Filters.accepts(game, stackedOnFilter, playResult.getAttachedOrStackedPlayedFrom()) - && Filters.and(filters).accepts(game, playedCard)); - } - return false; - } - - public static boolean playedOn(LotroGame game, EffectResult effectResult, Filterable targetFilter, Filterable... filters) { - if (effectResult.getType() == EffectResult.Type.PLAY) { - final PlayCardResult playResult = (PlayCardResult) effectResult; - final PhysicalCard attachedTo = playResult.getAttachedTo(); - if (attachedTo == null) + if (targetFilter != null && targetFilter != Filters.any && attachedTo != null + && !Filters.accepts(game, targetFilter, attachedTo)) return false; - PhysicalCard playedCard = playResult.getPlayedCard(); - return Filters.and(filters).accepts(game, playedCard) - && Filters.accepts(game, targetFilter, attachedTo); + + if(fromFilter != null && fromFilter != Filters.any && cardPlayedFrom != null + && !Filters.accepts(game, fromFilter, cardPlayedFrom)) + return false; + + if(fromZone != null && zone != fromZone) + return false; + + return Filters.and(filters).accepts(game, playResult.getPlayedCard()); } return false; }