From c62fd736f02d67783776d8d2eae17d2191f7b764 Mon Sep 17 00:00:00 2001 From: "marcin.sciesinski" Date: Thu, 29 Aug 2019 18:55:18 -0700 Subject: [PATCH] Effect that add trigger --- .../src/main/web/cards/set40.json | 23 +++ .../field/effect/EffectAppenderFactory.java | 14 ++ .../field/effect/appender/AddTrigger.java | 139 ++++++++++++++++++ .../build/field/effect/appender/Choice.java | 6 +- .../effect/appender/StackPlayedEvent.java | 42 ++++++ .../lotro/game/AbstractActionProxy.java | 57 +++---- .../com/gempukku/lotro/game/ActionProxy.java | 36 ++--- .../actions/DefaultActionsEnvironment.java | 8 + 8 files changed, 277 insertions(+), 48 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AddTrigger.java create mode 100644 gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/StackPlayedEvent.java diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set40.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set40.json index aff9e7c7f..6cf700287 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set40.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set40.json @@ -735,6 +735,29 @@ } } }, + "40_25": { + "title": "Resourcefulness", + "side": "free people", + "culture": "dwarven", + "cost": 2, + "type": "event", + "keyword": "maneuver", + "effects": { + "type": "event", + "effect": { + "type": "addTrigger", + "until": "start(regroup)", + "trigger": { + "type": "played", + "filter": "culture(dwarven),skirmish,event" + }, + "effect": { + "type": "stackPlayedEvent", + "where": "choose(culture(dwarven),support area,condition)" + } + } + } + }, "40_184": { "title": "Black Steed", "subtitle": "Bred to Serve", diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/EffectAppenderFactory.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/EffectAppenderFactory.java index 44dd8a326..7ec79fb8a 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/EffectAppenderFactory.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/EffectAppenderFactory.java @@ -44,6 +44,8 @@ public class EffectAppenderFactory { effectAppenderProducers.put("stackcardsfromhand", new StackCardsFromHand()); effectAppenderProducers.put("stackcardsfromdiscard", new StackCardsFromDiscard()); effectAppenderProducers.put("putcardsfromdiscardintohand", new PutCardsFromDiscardIntoHand()); + effectAppenderProducers.put("addtrigger", new AddTrigger()); + effectAppenderProducers.put("stackplayedevent", new StackPlayedEvent()); } public EffectAppender getEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { @@ -53,4 +55,16 @@ public class EffectAppenderFactory { throw new InvalidCardDefinitionException("Unable to find effect of type: " + type); return effectAppenderProducer.createEffectAppender(effectObject, environment); } + + public EffectAppender[] getEffectAppenders(JSONObject[] effectArray, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { + EffectAppender[] result = new EffectAppender[effectArray.length]; + for (int i = 0; i < result.length; i++) { + final String type = FieldUtils.getString(effectArray[i].get("type"), "type"); + final EffectAppenderProducer effectAppenderProducer = effectAppenderProducers.get(type.toLowerCase()); + if (effectAppenderProducer == null) + throw new InvalidCardDefinitionException("Unable to find effect of type: " + type); + result[i] = effectAppenderProducer.createEffectAppender(effectArray[i], environment); + } + return result; + } } diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AddTrigger.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AddTrigger.java new file mode 100644 index 000000000..7bf661a78 --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AddTrigger.java @@ -0,0 +1,139 @@ +package com.gempukku.lotro.cards.build.field.effect.appender; + +import com.gempukku.lotro.cards.build.CardGenerationEnvironment; +import com.gempukku.lotro.cards.build.InvalidCardDefinitionException; +import com.gempukku.lotro.cards.build.Requirement; +import com.gempukku.lotro.cards.build.field.FieldUtils; +import com.gempukku.lotro.cards.build.field.effect.EffectAppender; +import com.gempukku.lotro.cards.build.field.effect.EffectAppenderProducer; +import com.gempukku.lotro.cards.build.field.effect.appender.resolver.TimeResolver; +import com.gempukku.lotro.cards.build.field.effect.trigger.TriggerChecker; +import com.gempukku.lotro.game.ActionProxy; +import com.gempukku.lotro.game.PhysicalCard; +import com.gempukku.lotro.game.state.LotroGame; +import com.gempukku.lotro.logic.actions.AbstractCostToEffectAction; +import com.gempukku.lotro.logic.actions.CostToEffectAction; +import com.gempukku.lotro.logic.actions.OptionalTriggerAction; +import com.gempukku.lotro.logic.actions.RequiredTriggerAction; +import com.gempukku.lotro.logic.effects.AddUntilEndOfPhaseActionProxyEffect; +import com.gempukku.lotro.logic.effects.AddUntilStartOfPhaseActionProxyEffect; +import com.gempukku.lotro.logic.timing.Effect; +import com.gempukku.lotro.logic.timing.EffectResult; +import org.json.simple.JSONObject; + +import java.util.Collections; +import java.util.List; + +public class AddTrigger implements EffectAppenderProducer { + @Override + public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { + FieldUtils.validateAllowedFields(effectObject, "trigger", "until", "optional", "requirement", "cost", "effect"); + + final TimeResolver.Time until = TimeResolver.resolveTime(effectObject.get("until"), "end(current)"); + final TriggerChecker trigger = environment.getTriggerCheckerFactory().getTriggerChecker((JSONObject) effectObject.get("trigger"), environment); + final boolean optional = FieldUtils.getBoolean(effectObject.get("optional"), "optional", false); + + final JSONObject[] requirementArray = FieldUtils.getObjectArray(effectObject.get("requirement"), "requirement"); + final JSONObject[] costArray = FieldUtils.getObjectArray(effectObject.get("cost"), "cost"); + final JSONObject[] effectArray = FieldUtils.getObjectArray(effectObject.get("effect"), "effect"); + + final Requirement[] requirements = environment.getRequirementFactory().getRequirements(requirementArray, environment); + final EffectAppender[] costs = environment.getEffectAppenderFactory().getEffectAppenders(costArray, environment); + final EffectAppender[] effects = environment.getEffectAppenderFactory().getEffectAppenders(effectArray, environment); + + + return new DelayedAppender() { + @Override + protected Effect createEffect(CostToEffectAction action, String playerId, LotroGame game, PhysicalCard self, EffectResult effectResult, Effect effect) { + ActionProxy actionProxy = createActionProxy(self, optional, trigger, requirements, costs, effects); + + if (until.isStart()) { + return new AddUntilStartOfPhaseActionProxyEffect(actionProxy, until.getPhase()); + } else { + return new AddUntilEndOfPhaseActionProxyEffect(actionProxy, until.getPhase()); + } + } + }; + } + + private ActionProxy createActionProxy(PhysicalCard self, boolean optional, TriggerChecker trigger, Requirement[] requirements, EffectAppender[] costs, EffectAppender[] effects) { + return new ActionProxy() { + private boolean checkRequirements(String playerId, CostToEffectAction action, LotroGame game, PhysicalCard self, EffectResult effectResult, Effect effect) { + for (Requirement requirement : requirements) { + if (!requirement.accepts(action, playerId, game, self, effectResult, effect)) + return true; + } + + for (EffectAppender cost : costs) { + if (!cost.isPlayableInFull(action, playerId, game, self, effectResult, effect)) + return true; + } + return false; + } + + private void customizeTriggerAction(AbstractCostToEffectAction action, String playerId, LotroGame game, PhysicalCard self, EffectResult effectResult, Effect effect) { + action.setVirtualCardAction(true); + for (EffectAppender cost : costs) + cost.appendCost(action, playerId, game, self, effectResult, effect); + for (EffectAppender effectAppender : effects) + effectAppender.appendEffect(action, playerId, game, self, effectResult, effect); + } + + @Override + public List getRequiredBeforeTriggers(LotroGame lotroGame, Effect effect) { + if (trigger.isBefore() && !optional && trigger.accepts(null, null, lotroGame, self, null, effect)) { + if (checkRequirements(null, null, lotroGame, self, null, effect)) + return null; + + RequiredTriggerAction action = new RequiredTriggerAction(self); + customizeTriggerAction(action, null, lotroGame, self, null, effect); + + return Collections.singletonList(action); + } + return null; + } + + @Override + public List getOptionalBeforeTriggers(String playerId, LotroGame lotroGame, Effect effect) { + if (trigger.isBefore() && optional && trigger.accepts(null, playerId, lotroGame, self, null, effect)) { + if (checkRequirements(playerId, null, lotroGame, self, null, effect)) + return null; + + OptionalTriggerAction action = new OptionalTriggerAction(self); + customizeTriggerAction(action, playerId, lotroGame, self, null, effect); + + return Collections.singletonList(action); + } + return null; + } + + @Override + public List getRequiredAfterTriggers(LotroGame lotroGame, EffectResult effectResult) { + if (!trigger.isBefore() && !optional && trigger.accepts(null, null, lotroGame, self, effectResult, null)) { + if (checkRequirements(null, null, lotroGame, self, effectResult, null)) + return null; + + RequiredTriggerAction action = new RequiredTriggerAction(self); + customizeTriggerAction(action, null, lotroGame, self, effectResult, null); + + return Collections.singletonList(action); + } + return null; + } + + @Override + public List getOptionalAfterTriggers(String playerId, LotroGame lotroGame, EffectResult effectResult) { + if (!trigger.isBefore() && optional && trigger.accepts(null, playerId, lotroGame, self, effectResult, null)) { + if (checkRequirements(playerId, null, lotroGame, self, effectResult, null)) + return null; + + OptionalTriggerAction action = new OptionalTriggerAction(self); + customizeTriggerAction(action, playerId, lotroGame, self, effectResult, null); + + return Collections.singletonList(action); + } + return null; + } + }; + } +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/Choice.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/Choice.java index ed79f9208..d6a797bd5 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/Choice.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/Choice.java @@ -31,11 +31,7 @@ public class Choice implements EffectAppenderProducer { if (effectArray.length != textArray.length) throw new InvalidCardDefinitionException("Number of texts and effects does not match in choice effect"); - List possibleEffectAppenders = new LinkedList<>(); - for (JSONObject effect : effectArray) { - possibleEffectAppenders.add( - environment.getEffectAppenderFactory().getEffectAppender(effect, environment)); - } + EffectAppender[] possibleEffectAppenders = environment.getEffectAppenderFactory().getEffectAppenders(effectArray, environment); final PlayerSource playerSource = PlayerResolver.resolvePlayer(player, environment); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/StackPlayedEvent.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/StackPlayedEvent.java new file mode 100644 index 000000000..aeb0a430e --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/StackPlayedEvent.java @@ -0,0 +1,42 @@ +package com.gempukku.lotro.cards.build.field.effect.appender; + +import com.gempukku.lotro.cards.build.CardGenerationEnvironment; +import com.gempukku.lotro.cards.build.InvalidCardDefinitionException; +import com.gempukku.lotro.cards.build.field.FieldUtils; +import com.gempukku.lotro.cards.build.field.effect.EffectAppender; +import com.gempukku.lotro.cards.build.field.effect.EffectAppenderProducer; +import com.gempukku.lotro.cards.build.field.effect.appender.resolver.CardResolver; +import com.gempukku.lotro.game.PhysicalCard; +import com.gempukku.lotro.game.state.LotroGame; +import com.gempukku.lotro.logic.actions.CostToEffectAction; +import com.gempukku.lotro.logic.effects.StackPlayedEventOnACardEffect; +import com.gempukku.lotro.logic.timing.Effect; +import com.gempukku.lotro.logic.timing.EffectResult; +import com.gempukku.lotro.logic.timing.results.PlayEventResult; +import org.json.simple.JSONObject; + +public class StackPlayedEvent implements EffectAppenderProducer { + @Override + public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { + FieldUtils.validateAllowedFields(effectObject, "where"); + + final String where = FieldUtils.getString(effectObject.get("where"), "where"); + + MultiEffectAppender result = new MultiEffectAppender(); + + result.addEffectAppender( + CardResolver.resolveCard(where, "_temp1", "owner", "Choose card to stack on", environment)); + result.addEffectAppender( + new DelayedAppender() { + @Override + protected Effect createEffect(CostToEffectAction action, String playerId, LotroGame game, PhysicalCard self, EffectResult effectResult, Effect effect) { + final PhysicalCard card = action.getCardFromMemory("_temp1"); + + final PlayEventResult playEventResult = (PlayEventResult) effectResult; + return new StackPlayedEventOnACardEffect(playEventResult.getPlayEventAction(), card); + } + }); + + return result; + } +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/AbstractActionProxy.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/AbstractActionProxy.java index fee4bff84..b57cc4e0f 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/AbstractActionProxy.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/AbstractActionProxy.java @@ -1,26 +1,31 @@ -package com.gempukku.lotro.game; - -import com.gempukku.lotro.game.state.LotroGame; -import com.gempukku.lotro.logic.actions.OptionalTriggerAction; -import com.gempukku.lotro.logic.actions.RequiredTriggerAction; -import com.gempukku.lotro.logic.timing.Effect; -import com.gempukku.lotro.logic.timing.EffectResult; - -import java.util.List; - -public abstract class AbstractActionProxy implements ActionProxy { - @Override - public List getRequiredBeforeTriggers(LotroGame game, Effect effect) { - return null; - } - - @Override - public List getRequiredAfterTriggers(LotroGame game, EffectResult effectResult) { - return null; - } - - @Override - public List getOptionalAfterTriggers(String playerId, LotroGame game, EffectResult effectResult) { - return null; - } -} +package com.gempukku.lotro.game; + +import com.gempukku.lotro.game.state.LotroGame; +import com.gempukku.lotro.logic.actions.OptionalTriggerAction; +import com.gempukku.lotro.logic.actions.RequiredTriggerAction; +import com.gempukku.lotro.logic.timing.Effect; +import com.gempukku.lotro.logic.timing.EffectResult; + +import java.util.List; + +public abstract class AbstractActionProxy implements ActionProxy { + @Override + public List getRequiredBeforeTriggers(LotroGame game, Effect effect) { + return null; + } + + @Override + public List getRequiredAfterTriggers(LotroGame game, EffectResult effectResult) { + return null; + } + + @Override + public List getOptionalAfterTriggers(String playerId, LotroGame game, EffectResult effectResult) { + return null; + } + + @Override + public List getOptionalBeforeTriggers(String playerId, LotroGame lotroGame, Effect effect) { + return null; + } +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/ActionProxy.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/ActionProxy.java index db3241fff..99e89f4d0 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/ActionProxy.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/ActionProxy.java @@ -1,17 +1,19 @@ -package com.gempukku.lotro.game; - -import com.gempukku.lotro.game.state.LotroGame; -import com.gempukku.lotro.logic.actions.OptionalTriggerAction; -import com.gempukku.lotro.logic.actions.RequiredTriggerAction; -import com.gempukku.lotro.logic.timing.Effect; -import com.gempukku.lotro.logic.timing.EffectResult; - -import java.util.List; - -public interface ActionProxy { - public List getRequiredBeforeTriggers(LotroGame lotroGame, Effect effect); - - public List getRequiredAfterTriggers(LotroGame lotroGame, EffectResult effectResults); - - public List getOptionalAfterTriggers(String playerId, LotroGame lotroGame, EffectResult effectResults); -} +package com.gempukku.lotro.game; + +import com.gempukku.lotro.game.state.LotroGame; +import com.gempukku.lotro.logic.actions.OptionalTriggerAction; +import com.gempukku.lotro.logic.actions.RequiredTriggerAction; +import com.gempukku.lotro.logic.timing.Effect; +import com.gempukku.lotro.logic.timing.EffectResult; + +import java.util.List; + +public interface ActionProxy { + public List getRequiredBeforeTriggers(LotroGame lotroGame, Effect effect); + + public List getOptionalBeforeTriggers(String playerId, LotroGame lotroGame, Effect effect); + + public List getRequiredAfterTriggers(LotroGame lotroGame, EffectResult effectResult); + + public List getOptionalAfterTriggers(String playerId, LotroGame lotroGame, EffectResult effectResult); +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/actions/DefaultActionsEnvironment.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/actions/DefaultActionsEnvironment.java index a92744820..3ce612d63 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/actions/DefaultActionsEnvironment.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/actions/DefaultActionsEnvironment.java @@ -191,6 +191,14 @@ public class DefaultActionsEnvironment implements ActionsEnvironment { _lotroGame.getGameState().iterateActiveTextCards(playerId, gatherActions); List actionList = gatherActions.getActions(); + + for (ActionProxy actionProxy : _actionProxies) { + List actions = actionProxy.getOptionalBeforeTriggers(playerId, _lotroGame, effect); + if (actions != null) { + actionList.addAll(actions); + } + } + for (Action action : actionList) action.setPerformingPlayer(playerId);