From 9a971ce9082bdce0f85efc3492fbbb9ddbb64369 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Fri, 5 Aug 2022 05:46:53 -0500 Subject: [PATCH] Began adding improvments to the json card definitions. - added "unique" field instead of requiring that devs add * to the title - added aliases for the following fields: - possession -> itemclass - condition -> requires - cost -> twilight - for now these only work in top-level definitions - Converted dwarf, elf, and gandalf cards from V1 to the new format --- .../pc/setV01/set101_dwarven_playtest.hjson | 22 +- .../pc/setV01/set101_gandalf_playtest.hjson | 303 ++++++++++++++++++ .../pc/setV01/set101_gandalf_playtest.json | 299 ----------------- .../build/LotroCardBlueprintBuilder.java | 19 +- .../build/field/TitleFieldProcessor.java | 1 + .../build/field/UniqueFieldProcessor.java | 14 + 6 files changed, 346 insertions(+), 312 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/setV01/set101_gandalf_playtest.hjson delete mode 100644 gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/setV01/set101_gandalf_playtest.json create mode 100644 gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/UniqueFieldProcessor.java diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/setV01/set101_dwarven_playtest.hjson b/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/setV01/set101_dwarven_playtest.hjson index ba18739fd..6449a561b 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/setV01/set101_dwarven_playtest.hjson +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/setV01/set101_dwarven_playtest.hjson @@ -2,7 +2,7 @@ 151_1: { title: Hospitality of the Dwarves culture: dwarven - cost: 1 + twilight: 1 type: condition keyword: [ support area @@ -72,9 +72,10 @@ } 151_2: { - title: *Deepest Delvings + title: Deepest Delvings + unique: true culture: dwarven - cost: 1 + twilight: 1 type: condition keyword: [ support area @@ -115,10 +116,12 @@ } 151_3: { - title: *Gimli + # Hey look it's a comment because we're not in the stone age + title: Gimli + unique: true subtitle: Vengeful Naugrim culture: dwarven - cost: 2 + twilight: 2 type: companion race: dwarf strength: 6 @@ -159,7 +162,7 @@ 151_4: { title: I Name You Elf-friend culture: dwarven - cost: 1 + twilight: 1 type: event keyword: maneuver effects: { @@ -189,7 +192,7 @@ 151_5: { title: One Dwarf in Moria culture: dwarven - cost: 1 + twilight: 1 type: event keyword: maneuver condition: { @@ -238,9 +241,10 @@ } 151_6: { - title: *So Bold and So Courteous + title: So Bold and So Courteous + unique: true culture: dwarven - cost: 0 + twilight: 0 type: condition keyword: [ support area diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/setV01/set101_gandalf_playtest.hjson b/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/setV01/set101_gandalf_playtest.hjson new file mode 100644 index 000000000..361ebf4b6 --- /dev/null +++ b/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/setV01/set101_gandalf_playtest.hjson @@ -0,0 +1,303 @@ +{ + 151_13: { + title: Counsel of the Wise + culture: gandalf + cost: 0 + type: event + keyword: fellowship + condition: { + type: canSpot + filter: name(Gandalf) + } + effects: { + type: event + cost: { + type: chooseCardsFromDrawDeck + filter: choose(culture(elven),ally) + memorize: chosenAlly + text: Choose an [Elven] ally to reveal from your draw deck. + } + effect: { + type: optional + text: Would you like to pay this card's twilight cost to take it into hand? + effect: { + type: costToEffect + cost: { + type: addtwilight + amount: { + type: twilightCostInMemory + memory: chosenAlly + } + } + effect: { + type: putcardsfromdeckintohand + count: 1 + filter: memory(chosenAlly) + } + } + } + } + } + 151_14: { + title: Gandalf + unique: true + subtitle: Olorin + culture: gandalf + cost: 4 + type: companion + race: wizard + strength: 6 + vitality: 4 + signet: gandalf + resistance: 6 + effects: [ + { + type: trigger + optional: true + trigger: { + type: startOfPhase + phase: fellowship + } + condition: { + type: canSpot + filter: culture(elven),ally + count: 2 + } + cost: { + type: exert + filter: choose(name(Gandalf)) + } + effect: { + type: shuffleCardsFromDiscardIntoDrawDeck + filter: choose(or(culture(gandalf),culture(elven))) + } + } + { + type: modifier + modifier: { + type: modifyStrength + condition: { + type: canSpot + filter: culture(elven),ally + count: 3 + } + filter: name(Gandalf) + amount: 2 + } + } + + { + type: modifier + modifier: { + type: modifyStrength + condition: [ + { + type: canSpot + filter: name(Elrond) + } + { + type: canSpot + filter: name(Galadriel) + } + { + type: canSpot + filter: name(Celeborn) + } + ] + filter: name(Gandalf) + amount: 2 + } + } + ] + } + 151_15: { + title: Gwaihir + unique: true + subtitle: Lord of All Eagles + culture: gandalf + cost: 4 + type: ally + allyHome: fellowship,4 + race: eagle + strength: 8 + vitality: 2 + condition: [ + { + type: canSpot + filter: name(Gandalf) + } + ] + effects: [ + { + type: trigger + optional: true + trigger: { + type: movesTo + filter: not(your) + } + effect: { + type: heal + filter: choose(companion,signet(gandalf)) + } + } + { + type: activated + phase: regroup + cost: { + type: discard + filter: self + } + effect: [ + { + type: addModifier + modifier: { + type: modifyMoveLimit + amount: 1 + } + until: endOfTurn + } + { + type: optional + player: shadowPlayer + text: Would you like to take up to 2 Shadow cards into hand from discard? + effect: { + type: putCardsFromDiscardIntoHand + filter: choose(side(shadow)) + count: 2 + } + } + ] + } + ] + } + 151_16: { + title: My Heart Tells Me + unique: true + culture: gandalf + cost: 1 + type: condition + keyword: support area + effects: { + type: activatedtrigger + trigger: { + type: aboutToTakeWound + filter: minion + } + condition: [ + { + type: canSpot + filter: name(Gandalf) + } + { + type: perTurnLimit + limit: 1 + } + ] + effect: [ + { + type: incrementPerTurnLimit + limit: 1 + } + { + type: preventWound + filter: choose(minion) + } + { + type: heal + filter: choose(companion) + } + ] + } + } + 151_17: { + title: Two Eyes, As Often As I Can Spare Them + culture: gandalf + cost: 3 + type: event + keyword: fellowship + condition: [ + { + type: canSpot + filter: name(Frodo) + } + { + type: canSpot + filter: name(Gandalf) + } + ] + effects: { + type: event + effect: { + type: drawCards + count: { + type: forEachVitality + filter: name(Frodo) + } + } + } + } + 151_18: { + title: The White Council + unique: true + culture: gandalf + cost: 1 + type: condition + keyword: support area + effects: [ + { + type: modifier + modifier: { + type: SarumanFirstSentenceInactive + condition: [ + { + type: canspot + filter: name(Gandalf) + } + { + type: canspot + filter: culture(elven),ally + count: 2 + } + ] + } + } + { + type: activated + phase: regroup + condition: [ + { + type: perPhaseLimit + limit: 2 + } + { + type: canSpot + count: 2 + filter: culture(elven),not(exhausted) + } + ] + cost: { + type: exert + filter: choose(culture(elven),ally) + count: 2 + } + effect: { + type: conditional + condition: { + type: perPhaseLimit + limit: 2 + } + effect: [ + { + type: incrementPerPhaseLimit + limit: 1 + } + { + type: heal + filter: choose(companion,or(name(Gandalf),signet(gandalf))) + } + ] + } + } + ] + } +} diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/setV01/set101_gandalf_playtest.json b/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/setV01/set101_gandalf_playtest.json deleted file mode 100644 index 4e73e1cdd..000000000 --- a/gemp-lotr/gemp-lotr-async/src/main/web/cards/unofficial/pc/setV01/set101_gandalf_playtest.json +++ /dev/null @@ -1,299 +0,0 @@ -{ - "151_13": { - "title": "Counsel of the Wise", - "culture": "gandalf", - "cost": 0, - "type": "event", - "keyword": "fellowship", - "condition": { - "type": "canSpot", - "filter": "name(Gandalf)" - }, - "effects": { - "type": "event", - "cost": { - "type": "chooseCardsFromDrawDeck", - "filter": "choose(culture(elven),ally)", - "memorize": "chosenAlly", - "text": "Choose an [Elven] ally to reveal from your draw deck." - }, - "effect": { - "type": "optional", - "text": "Would you like to pay this card's twilight cost to take it into hand?", - "effect": { - "type": "costToEffect", - "cost": { - "type": "addtwilight", - "amount": { - "type": "twilightCostInMemory", - "memory": "chosenAlly" - } - }, - "effect": { - "type": "putcardsfromdeckintohand", - "count": 1, - "filter": "memory(chosenAlly)" - } - } - } - } - }, - "151_14": { - "title": "*Gandalf", - "subtitle": "Olorin", - "culture": "gandalf", - "cost": 4, - "type": "companion", - "race": "wizard", - "strength": 6, - "vitality": 4, - "signet": "gandalf", - "resistance": 6, - "effects": [ - { - "type": "trigger", - "optional": true, - "trigger": { - "type": "startOfPhase", - "phase": "fellowship" - }, - "condition": { - "type": "canSpot", - "filter": "culture(elven),ally", - "count": 2 - }, - "cost": { - "type": "exert", - "filter": "choose(name(Gandalf))" - }, - "effect": { - "type": "shuffleCardsFromDiscardIntoDrawDeck", - "filter": "choose(or(culture(gandalf),culture(elven)))" - } - }, - { - "type": "modifier", - "modifier": { - "type": "modifyStrength", - "condition": { - "type": "canSpot", - "filter": "culture(elven),ally", - "count": 3 - }, - "filter": "name(Gandalf)", - "amount": 2 - } - }, - - { - "type": "modifier", - "modifier": { - "type": "modifyStrength", - "condition": [ - { - "type": "canSpot", - "filter": "name(Elrond)" - }, - { - "type": "canSpot", - "filter": "name(Galadriel)" - }, - { - "type": "canSpot", - "filter": "name(Celeborn)" - } - ], - "filter": "name(Gandalf)", - "amount": 2 - } - } - ] - }, - "151_15": { - "title": "*Gwaihir", - "subtitle": "Lord of All Eagles", - "culture": "gandalf", - "cost": 4, - "type": "ally", - "allyHome": "fellowship,4", - "race": "eagle", - "strength": 8, - "vitality": 2, - "condition": [ - { - "type": "canSpot", - "filter": "name(Gandalf)" - } - ], - "effects": [ - { - "type": "trigger", - "optional": true, - "trigger": { - "type": "movesTo", - "filter": "not(your)" - }, - "effect": { - "type": "heal", - "filter": "choose(companion,signet(gandalf))" - } - }, - { - "type": "activated", - "phase": "regroup", - "cost": { - "type": "discard", - "filter": "self" - }, - "effect": [ - { - "type": "addModifier", - "modifier": { - "type": "modifyMoveLimit", - "amount": 1 - }, - "until": "endOfTurn" - }, - { - "type": "optional", - "player": "shadowPlayer", - "text": "Would you like to take up to 2 Shadow cards into hand from discard?", - "effect": { - "type": "putCardsFromDiscardIntoHand", - "filter": "choose(side(shadow))", - "count": 2 - } - } - ] - } - ] - }, - "151_16": { - "title": "*My Heart Tells Me", - "culture": "gandalf", - "cost": 1, - "type": "condition", - "keyword": "support area", - "effects": { - "type": "activatedtrigger", - "trigger": { - "type": "aboutToTakeWound", - "filter": "minion" - }, - "condition": [ - { - "type": "canSpot", - "filter": "name(Gandalf)" - }, - { - "type": "perTurnLimit", - "limit": 1 - }, - ], - "effect": [ - { - "type": "incrementPerTurnLimit", - "limit": 1 - }, - { - "type": "preventWound", - "filter": "choose(minion)" - }, - { - "type": "heal", - "filter": "choose(companion)" - } - ] - } - }, - "151_17": { - "title": "Two Eyes, As Often As I Can Spare Them", - "culture": "gandalf", - "cost": 3, - "type": "event", - "keyword": "fellowship", - "condition": [ - { - "type": "canSpot", - "filter": "name(Frodo)" - }, - { - "type": "canSpot", - "filter": "name(Gandalf)" - } - ], - "effects": { - "type": "event", - "effect": { - "type": "drawCards", - "count": { - "type": "forEachVitality", - "filter": "name(Frodo)" - } - } - } - }, - "151_18": { - "title": "*The White Council", - "culture": "gandalf", - "cost": 1, - "type": "condition", - "keyword": "support area", - "effects": [ - { - "type": "modifier", - "modifier": { - "type": "SarumanFirstSentenceInactive", - "condition": [ - { - "type": "canspot", - "filter": "name(Gandalf)" - }, - { - "type": "canspot", - "filter": "culture(elven),ally", - "count": 2 - } - ], - } - }, - { - "type": "activated", - "phase": "regroup", - "condition": [ - { - "type": "perPhaseLimit", - "limit": 2 - }, - { - "type": "canSpot", - "count": 2, - "filter": "culture(elven),not(exhausted)" - } - ], - "cost": { - "type": "exert", - "filter": "choose(culture(elven),ally)", - "count": 2 - }, - "effect": { - "type": "conditional", - "condition": { - "type": "perPhaseLimit", - "limit": 2 - }, - "effect": [ - { - "type": "incrementPerPhaseLimit", - "limit": 1 - }, - { - "type": "heal", - "filter": "choose(companion,or(name(Gandalf),signet(gandalf)))" - } - ] - } - } - ] - } -} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/LotroCardBlueprintBuilder.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/LotroCardBlueprintBuilder.java index ab891b401..8fc262855 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/LotroCardBlueprintBuilder.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/LotroCardBlueprintBuilder.java @@ -25,30 +25,41 @@ public class LotroCardBlueprintBuilder implements CardGenerationEnvironment { public LotroCardBlueprintBuilder() { fieldProcessors.put("title", new TitleFieldProcessor()); fieldProcessors.put("subtitle", new SubtitleFieldProcessor()); + fieldProcessors.put("unique", new UniqueFieldProcessor()); fieldProcessors.put("side", new SideFieldProcessor()); - fieldProcessors.put("type", new CardTypeFieldProcessor()); fieldProcessors.put("culture", new CultureFieldProcessor()); + fieldProcessors.put("type", new CardTypeFieldProcessor()); fieldProcessors.put("race", new RaceFieldProcessor()); - fieldProcessors.put("signet", new SignetFieldProcessor()); + //Deprecated: use "itemclass" instead. + fieldProcessors.put("possession", new PossessionClassFieldProcessor()); + fieldProcessors.put("itemclass", new PossessionClassFieldProcessor()); fieldProcessors.put("keyword", new KeywordFieldProcessor()); + fieldProcessors.put("keywords", new KeywordFieldProcessor()); + //Deprecated: use "twilight" instead. fieldProcessors.put("cost", new CostFieldProcessor()); + fieldProcessors.put("twilight", new CostFieldProcessor()); fieldProcessors.put("strength", new StrengthFieldProcessor()); fieldProcessors.put("vitality", new VitalityFieldProcessor()); fieldProcessors.put("resistance", new ResistanceFieldProcessor()); + fieldProcessors.put("signet", new SignetFieldProcessor()); fieldProcessors.put("block", new SiteBlockFieldProcessor()); fieldProcessors.put("site", new SiteNumberFieldProcessor()); - fieldProcessors.put("possession", new PossessionClassFieldProcessor()); + fieldProcessors.put("direction", new DirectionFieldProcessor()); fieldProcessors.put("effects", new EffectFieldProcessor()); fieldProcessors.put("target", new TargetFieldProcessor()); + //Deprecated: use "requires" instead. fieldProcessors.put("condition", new RequirementFieldProcessor()); + fieldProcessors.put("requires", new RequirementFieldProcessor()); fieldProcessors.put("allyhome", new AllyHomeFieldProcessor()); + //Deprecated; use "gametext" instead. fieldProcessors.put("text", new NullProcessor()); fieldProcessors.put("gametext", new NullProcessor()); + //Deprecated; use "lore" instead. + fieldProcessors.put("quote", new NullProcessor()); fieldProcessors.put("lore", new NullProcessor()); fieldProcessors.put("promotext", new NullProcessor()); - fieldProcessors.put("quote", new NullProcessor()); } public LotroCardBlueprint buildFromJson(JSONObject json) throws InvalidCardDefinitionException { diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/TitleFieldProcessor.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/TitleFieldProcessor.java index ad4fe5315..68a0a3909 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/TitleFieldProcessor.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/TitleFieldProcessor.java @@ -10,6 +10,7 @@ public class TitleFieldProcessor implements FieldProcessor { public void processField(String key, Object value, BuiltLotroCardBlueprint blueprint, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { boolean unique = false; String title = FieldUtils.getString(value, key); + //Deprecated, don't do this. Use the "unique" field instead. if (title.startsWith("*")) { unique = true; title = title.substring(1); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/UniqueFieldProcessor.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/UniqueFieldProcessor.java new file mode 100644 index 000000000..3c4ed6d12 --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/UniqueFieldProcessor.java @@ -0,0 +1,14 @@ +package com.gempukku.lotro.cards.build.field; + +import com.gempukku.lotro.cards.build.BuiltLotroCardBlueprint; +import com.gempukku.lotro.cards.build.CardGenerationEnvironment; +import com.gempukku.lotro.cards.build.FieldProcessor; +import com.gempukku.lotro.cards.build.InvalidCardDefinitionException; + +public class UniqueFieldProcessor implements FieldProcessor { + @Override + public void processField(String key, Object value, BuiltLotroCardBlueprint blueprint, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { + boolean unique = FieldUtils.getBoolean(value, key); + blueprint.setUnique(unique); + } +}