From a8885271c3171a7aae64d467e03cdc744ccb4d5d Mon Sep 17 00:00:00 2001 From: "marcin.sciesinski" Date: Sun, 1 Sep 2019 16:07:39 -0700 Subject: [PATCH] All elven cards --- .../src/main/web/cards/set1.json | 1 + .../src/main/web/cards/set4.json | 1 + .../main/web/cards/set40/set40-dwarven.json | 1 + .../src/main/web/cards/set40/set40-elven.json | 308 +++++++++++++++++- .../field/effect/EffectAppenderFactory.java | 1 + .../field/effect/appender/AddThreats.java | 40 +++ .../build/field/effect/appender/Wound.java | 5 +- .../build/field/effect/trigger/Moves.java | 27 ++ .../build/field/effect/trigger/MovesTo.java | 32 ++ .../effect/trigger/TriggerCheckerFactory.java | 2 + 10 files changed, 409 insertions(+), 9 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AddThreats.java create mode 100644 gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/Moves.java create mode 100644 gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/MovesTo.java diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set1.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set1.json index ae64d1942..d9fc079bf 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set1.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set1.json @@ -147,6 +147,7 @@ "type": "event", "effect": { "type": "modifyArcheryTotal", + "side": "free people", "amount": 1 } } diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set4.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set4.json index 5b8b6e8b1..f6b907078 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set4.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set4.json @@ -14,6 +14,7 @@ ], "effects": { "type": "archeryTotal", + "side": "shadow", "condition": { "type": "controlsSite", "player": "owner" diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set40/set40-dwarven.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set40/set40-dwarven.json index 3a0fe4021..957873ffb 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set40/set40-dwarven.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set40/set40-dwarven.json @@ -820,6 +820,7 @@ }, "effect": { "type": "modifyArcheryTotal", + "side": "shadow", "amount": { "type": "multiply", "source": { diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set40/set40-elven.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set40/set40-elven.json index 6f7dc84a3..f85dcbba2 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/set40/set40-elven.json +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/set40/set40-elven.json @@ -1,7 +1,6 @@ { "40_33": { "title": "Arrows of Light", - "culture": "elven", "cost": 2, "type": "event", @@ -14,7 +13,7 @@ "type": "event", "cost": { "type": "reduceArcheryTotal", - + "side": "free people", "memorize": "reducedBy" }, "effect": { @@ -30,7 +29,6 @@ "40_34": { "title": "*Arwen", "subtitle": "Fearless Rider", - "culture": "elven", "cost": 2, "type": "companion", @@ -51,7 +49,6 @@ "40_35": { "title": "*Arwen", "subtitle": "Lady of Imladris", - "culture": "elven", "cost": 2, "type": "companion", @@ -92,7 +89,6 @@ "40_36": { "title": "*Bow of the Galadhrim", "subtitle": "Galadriel's Gift", - "culture": "elven", "cost": 1, "type": "possession", @@ -118,7 +114,6 @@ }, "40_37": { "title": "*Bruinen Unleashed", - "culture": "elven", "cost": 1, "type": "condition", @@ -156,7 +151,6 @@ "40_38": { "title": "*Celeborn", "subtitle": "Lord of the Golden Wood", - "culture": "elven", "cost": 2, "type": "ally", @@ -239,6 +233,7 @@ ], "effect": { "type": "modifyArcheryTotal", + "side": "free people", "amount": 2 } } @@ -676,6 +671,217 @@ ] } }, + "40_52": { + "title": "*Legolas", + "subtitle": "Swiftshot", + "culture": "elven", + "cost": 2, + "type": "companion", + "race": "elf", + "strength": 6, + "vitality": 3, + "resistance": 8, + "keyword": "archer", + "effects": { + "type": "activated", + "phase": "archery", + "condition": { + "type": "location", + "filter": "battleground" + }, + "cost": { + "type": "exert", + "filter": "self" + }, + "effect": { + "type": "modifyArcheryTotal", + "side": "free people", + "amount": 1 + } + } + }, + "40_53": { + "title": "*Lights of Caras Galadhon", + "culture": "elven", + "cost": 1, + "type": "condition", + "keyword": "support area", + "condition": { + "type": "canSpot", + "filter": "elf" + }, + "effects": { + "type": "trigger", + "trigger": { + "type": "movesTo", + "filter": "sanctuary" + }, + "cost": { + "type": "exert", + "filter": "choose(elf)", + "memorize": "exertedElf" + }, + "effect": { + "type": "removeBurdens", + "amount": { + "type": "condition", + "condition": { + "type": "memoryMatches", + "memory": "exertedElf", + "filter": "name(Galadriel)" + }, + "true": 2, + "false": 1 + } + } + } + }, + "40_54": { + "title": "*Long-knives of Legolas", + "subtitle": "Dancing Blades", + "culture": "elven", + "cost": 1, + "type": "possession", + "possession": "hand weapon", + "strength": 1, + "target": "name(Legolas)", + "effects": { + "type": "modifyStrength", + "filter": "wounded,minion,inSkirmishAgainst(bearer)", + "amount": -2 + } + }, + "40_55": { + "title": "Lorien Patrol", + "culture": "elven", + "cost": 1, + "type": "event", + "keyword": "archery", + "effects": { + "type": "event", + "cost": [ + { + "type": "exert", + "filter": "choose(culture(elven),ally)" + }, + { + "type": "addThreats" + } + ], + "effect": [ + { + "type": "wound", + "filter": "choose(minion)", + "memorize": "woundedMinion" + }, + { + "type": "conditional", + "condition": { + "type": "memoryMatches", + "memory": "woundedMinion", + "filter": "culture(isengard),minion" + }, + "effect": { + "type": "wound", + "filter": "memory(woundedMinion)" + } + } + ] + } + }, + "40_57": { + "title": "*Peering Forward", + "culture": "elven", + "cost": 0, + "type": "condition", + "keyword": "support area", + "effects": { + "type": "trigger", + "trigger": { + "type": "revealCardFromTopOfDrawDeck" + }, + "optional": true, + "cost": { + "type": "exert", + "filter": "choose(elf)" + }, + "effect": { + "type": "modifyStrength", + "filter": "choose(minion)", + "amount": -1, + "until": "start(regroup)" + } + } + }, + "40_58": { + "title": "*Silent Scouts", + "culture": "elven", + "cost": 1, + "type": "condition", + "keyword": "support area", + "effects": { + "type": "trigger", + "trigger": { + "type": "moves" + }, + "condition": { + "type": "phase", + "phase": "regroup" + }, + "effect": [ + { + "type": "revealTopCardsOfDrawDeck", + "memorize": "revealedCard" + }, + { + "type": "conditional", + "condition": { + "type": "memoryMatches", + "memory": "revealedCard", + "filter": "culture(elven)" + }, + "effect": { + "type": "optional", + "text": "Would you like to make the Shadow player wound a minion?", + "effect": { + "type": "wound", + "player": "shadowPlayer", + "filter": "choose(minion)" + } + } + } + ] + } + }, + "40_59": { + "title": "*The Tale of Gil-Galad", + "culture": "elven", + "cost": 1, + "type": "condition", + "target": "elf,companion", + "vitality": 1, + "keyword": "tale", + "effects": { + "type": "activated", + "phase": "skirmish", + "cost": [ + { + "type": "memorize", + "filter": "bearer", + "memory": "bearer" + }, + { + "type": "discard", + "filter": "self" + } + ], + "effect": { + "type": "modifyStrength", + "filter": "memory(bearer)", + "amount": 2 + } + } + }, "40_60": { "title": "*The Mirror of Galadriel", "subtitle": "Revealer of Portents", @@ -727,5 +933,93 @@ ] } ] + }, + "40_61": { + "title": "*Three for the Elven-kings", + "culture": "elven", + "cost": 0, + "type": "artifact", + "keyword": "support area", + "effects": [ + { + "type": "activated", + "phase": "fellowship", + "effect": { + "type": "stackCardsFromHand", + "filter": "choose(culture(elven))", + "where": "self" + } + }, + { + "type": "activatedTrigger", + "trigger": { + "type": "aboutToDiscard", + "filter": "culture(elven),condition" + }, + "cost": { + "type": "discardStackedCards", + "on": "self", + "count": 2 + }, + "effect": { + "type": "preventDiscard", + "filter": "choose(culture(elven),condition)" + } + }, + { + "type": "activated", + "phase": "regroup", + "cost": { + "type": "discardStackedCards", + "on": "self", + "count": 3 + }, + "effect": [ + { + "type": "heal", + "filter": "choose(elf)", + "count": "0-1" + }, + { + "type": "heal", + "filter": "choose(elf)", + "count": "0-1" + }, + { + "type": "heal", + "filter": "choose(elf)", + "count": "0-1" + } + ] + } + ] + }, + "40_62": { + "title": "We Could Have Shot Him in the Dark", + "culture": "elven", + "cost": 2, + "type": "event", + "keyword": "archery", + "condition": { + "type": "canSpot", + "count": 2, + "filter": "elf,archer" + }, + "effects": { + "type": "event", + "effect": { + "type": "modifyArcheryTotal", + "side": "free people", + "amount": { + "type": "condition", + "condition": { + "type": "location", + "filter": "forest" + }, + "true": 3, + "false": 2 + } + } + } } } 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 09075b92c..34a4aa0b1 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 @@ -66,6 +66,7 @@ public class EffectAppenderFactory { effectAppenderProducers.put("removekeyword", new RemoveKeyword()); effectAppenderProducers.put("putcardsfromdiscardontopofdrawdeck", new PutCardsFromDiscardOnTopOfDrawDeck()); effectAppenderProducers.put("lookattopcardsofdrawdeck", new LookAtTopCardsOfDrawDeck()); + effectAppenderProducers.put("addthreats", new AddThreats()); } public EffectAppender getEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AddThreats.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AddThreats.java new file mode 100644 index 000000000..fe3e6b186 --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AddThreats.java @@ -0,0 +1,40 @@ +package com.gempukku.lotro.cards.build.field.effect.appender; + +import com.gempukku.lotro.cards.build.*; +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.PlayerResolver; +import com.gempukku.lotro.cards.build.field.effect.appender.resolver.ValueResolver; +import com.gempukku.lotro.logic.actions.CostToEffectAction; +import com.gempukku.lotro.logic.effects.AddThreatsEffect; +import com.gempukku.lotro.logic.timing.Effect; +import com.gempukku.lotro.logic.timing.PlayConditions; +import org.json.simple.JSONObject; + +public class AddThreats implements EffectAppenderProducer { + @Override + public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { + FieldUtils.validateAllowedFields(effectObject, "amount", "player"); + + final ValueSource valueSource = ValueResolver.resolveEvaluator(effectObject.get("amount"), 1, environment); + final String player = FieldUtils.getString(effectObject.get("player"), "player", "you"); + + final PlayerSource playerSource = PlayerResolver.resolvePlayer(player, environment); + + return new DelayedAppender() { + @Override + protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) { + final int amount = valueSource.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), null); + final String playerAddingBurden = playerSource.getPlayer(actionContext); + return new AddThreatsEffect(playerAddingBurden, actionContext.getSource(), amount); + } + + @Override + public boolean isPlayableInFull(ActionContext actionContext) { + final int amount = valueSource.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), null); + return PlayConditions.canAddThreat(actionContext.getGame(), actionContext.getSource(), amount); + } + }; + } +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/Wound.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/Wound.java index f88900118..846a5bdaa 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/Wound.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/Wound.java @@ -23,8 +23,9 @@ import java.util.List; public class Wound implements EffectAppenderProducer { @Override public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { - FieldUtils.validateAllowedFields(effectObject, "count", "times", "filter", "memorize"); + FieldUtils.validateAllowedFields(effectObject, "count", "times", "filter", "memorize", "player"); + final String player = FieldUtils.getString(effectObject.get("player"), "player", "you"); final ValueSource valueSource = ValueResolver.resolveEvaluator(effectObject.get("count"), 1, environment); final int times = FieldUtils.getInteger(effectObject.get("times"), "times", 1); final String filter = FieldUtils.getString(effectObject.get("filter"), "filter"); @@ -35,7 +36,7 @@ public class Wound implements EffectAppenderProducer { result.addEffectAppender( CardResolver.resolveCards(filter, (actionContext) -> Filters.canTakeWounds(actionContext.getSource(), times), - valueSource, memory, "you", "Choose cards to wound", environment)); + valueSource, memory, player, "Choose cards to wound", environment)); result.addEffectAppender( new DelayedAppender() { @Override diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/Moves.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/Moves.java new file mode 100644 index 000000000..19f11f314 --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/Moves.java @@ -0,0 +1,27 @@ +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.InvalidCardDefinitionException; +import com.gempukku.lotro.cards.build.field.FieldUtils; +import com.gempukku.lotro.logic.timing.TriggerConditions; +import org.json.simple.JSONObject; + +public class Moves implements TriggerCheckerProducer { + @Override + public TriggerChecker getTriggerChecker(JSONObject value, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { + FieldUtils.validateAllowedFields(value, "filter"); + + return new TriggerChecker() { + @Override + public boolean accepts(ActionContext actionContext) { + return TriggerConditions.moves(actionContext.getGame(), actionContext.getEffectResult()); + } + + @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/MovesTo.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/MovesTo.java new file mode 100644 index 000000000..5099e0378 --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/MovesTo.java @@ -0,0 +1,32 @@ +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.logic.timing.TriggerConditions; +import org.json.simple.JSONObject; + +public class MovesTo implements TriggerCheckerProducer { + @Override + public TriggerChecker getTriggerChecker(JSONObject value, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { + FieldUtils.validateAllowedFields(value, "filter"); + + String filter = FieldUtils.getString(value.get("filter"), "filter", "any"); + + final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter); + + return new TriggerChecker() { + @Override + public boolean accepts(ActionContext actionContext) { + return TriggerConditions.movesTo(actionContext.getGame(), actionContext.getEffectResult(), filterableSource.getFilterable(actionContext)); + } + + @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/TriggerCheckerFactory.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java index c27b2f1d5..7a983cb05 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 @@ -22,6 +22,8 @@ public class TriggerCheckerFactory { triggerCheckers.put("condition", new ConditionTrigger()); triggerCheckers.put("assignedtoskirmish", new AssignedToSkirmish()); triggerCheckers.put("revealcardfromtopofdrawdeck", new RevealCardFromTopOfDrawDeck()); + triggerCheckers.put("movesto", new MovesTo()); + triggerCheckers.put("moves", new Moves()); } public TriggerChecker getTriggerChecker(JSONObject object, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {