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 ca789385b..3ab560c43 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 @@ -1,4 +1,57 @@ { + "40_1": { + "title": "The One Ring", + "subtitle": "Doom of Free Peoples", + "unique": true, + "type": "the one ring", + "strength": 1, + "vitality": 1, + "resistance": 1, + "effects": [ + { + "type": "trigger", + "requirement": { + "type": "ringIsOn" + }, + "trigger": { + "type": "aboutToTakeWound", + "filter": "hasAttached(self)" + }, + "effect": [ + { + "type": "negateWound", + "filter": "all(hasAttached(self))" + }, + { + "type": "addBurden" + } + ] + }, + { + "type": "activated", + "phase": "maneuver", + "cost": { + "type": "choice", + "texts": [ + "Exert bearer", + "Discard a card at random" + ], + "effects": [ + { + "type": "exert", + "filter": "choose(hasAttached(self))" + }, + { + "type": "discardCardAtRandomFromHand" + } + ] + }, + "effect": { + "type": "putOnRing" + } + } + ] + }, "40_3": { "title": "Balin's Lament", "unique": true, 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 4372dbc31..650a35f4d 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 @@ -32,6 +32,9 @@ public class EffectAppenderFactory { effectAppenderProducers.put("assigntoskirmishagainstminion", new AssignToSkirmishAgainstMinion()); effectAppenderProducers.put("putcardfromhandonbottomofdeck", new PutCardFromHandOnBottomOfDeck()); effectAppenderProducers.put("doesnotaddtoarcherytotal", new DoesNotAddToArcheryTotal()); + effectAppenderProducers.put("negatewound", new NegateWound()); + effectAppenderProducers.put("discardcardatrandomfromhand", new DiscardCardAtRandomFromHand()); + effectAppenderProducers.put("putonring", new PutOnRing()); } 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/AddBurden.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AddBurden.java index 7f34657fc..ad217876a 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AddBurden.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AddBurden.java @@ -23,7 +23,7 @@ public class AddBurden implements EffectAppenderProducer { FieldUtils.validateAllowedFields(effectObject, "amount", "player"); final int amount = FieldUtils.getInteger(effectObject.get("amount"), "amount", 1); - final String player = FieldUtils.getString(effectObject.get("player"), "player"); + final String player = FieldUtils.getString(effectObject.get("player"), "player", "owner"); 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/DiscardCardAtRandomFromHand.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/DiscardCardAtRandomFromHand.java new file mode 100644 index 000000000..04c47c7c5 --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/DiscardCardAtRandomFromHand.java @@ -0,0 +1,40 @@ +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.game.PhysicalCard; +import com.gempukku.lotro.game.state.LotroGame; +import com.gempukku.lotro.logic.actions.CostToEffectAction; +import com.gempukku.lotro.logic.effects.DiscardCardAtRandomFromHandEffect; +import com.gempukku.lotro.logic.timing.Effect; +import com.gempukku.lotro.logic.timing.EffectResult; +import org.json.simple.JSONObject; + +public class DiscardCardAtRandomFromHand implements EffectAppenderProducer { + @Override + public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { + FieldUtils.validateAllowedFields(effectObject); + + return new AbstractEffectAppender() { + @Override + protected Effect createEffect(CostToEffectAction action, String playerId, LotroGame game, PhysicalCard self, EffectResult effectResult, Effect effect) { + return new DiscardCardAtRandomFromHandEffect(self, self.getOwner(), false); + } + + @Override + public boolean isPlayableInFull(String playerId, LotroGame game, PhysicalCard self, EffectResult effectResult, Effect effect) { + return game.getGameState().getDeck(self.getOwner()).size() >= 1; + } + }; + } + + @Override + public Requirement createCostRequirement(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { + FieldUtils.validateAllowedFields(effectObject); + return (playerId, game, self, effectResult, effect) -> game.getGameState().getDeck(self.getOwner()).size() >= 1; + } +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/NegateWound.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/NegateWound.java new file mode 100644 index 000000000..b52c662d7 --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/NegateWound.java @@ -0,0 +1,60 @@ +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.CardResolver; +import com.gempukku.lotro.filters.Filters; +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.NegateWoundEffect; +import com.gempukku.lotro.logic.effects.WoundCharactersEffect; +import com.gempukku.lotro.logic.timing.Effect; +import com.gempukku.lotro.logic.timing.EffectResult; +import org.json.simple.JSONObject; + +import java.util.Collection; + +public class NegateWound implements EffectAppenderProducer { + @Override + public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { + FieldUtils.validateAllowedFields(effectObject, "filter"); + + final String filter = FieldUtils.getString(effectObject.get("filter"), "filter", "all(any)"); + + MultiEffectAppender result = new MultiEffectAppender(); + + result.addEffectAppender( + CardResolver.resolveCards(filter, + (playerId, game, source, effectResult, effect) -> { + final WoundCharactersEffect woundEffect = (WoundCharactersEffect) effect; + return Filters.in(woundEffect.getAffectedCardsMinusPrevented(game)); + }, 1, 1, "_temp", "owner", "Choose characters to negate wound to", environment)); + result.addEffectAppender( + new AbstractEffectAppender() { + @Override + protected Effect createEffect(CostToEffectAction action, String playerId, LotroGame game, PhysicalCard self, EffectResult effectResult, Effect effect) { + final Collection cards = action.getCardsFromMemory("_temp"); + final WoundCharactersEffect woundEffect = (WoundCharactersEffect) effect; + + return new NegateWoundEffect(woundEffect, Filters.in(cards)); + } + + @Override + public boolean isPlayableInFull(String playerId, LotroGame game, PhysicalCard self, EffectResult effectResult, Effect effect) { + return true; + } + }); + + return result; + } + + @Override + public Requirement createCostRequirement(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { + return null; + } +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PutCardFromHandOnBottomOfDeck.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PutCardFromHandOnBottomOfDeck.java index d8d56c1f4..d7f0ba4de 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PutCardFromHandOnBottomOfDeck.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PutCardFromHandOnBottomOfDeck.java @@ -41,8 +41,7 @@ public class PutCardFromHandOnBottomOfDeck implements EffectAppenderProducer { } }); - - return null; + return result; } @Override diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PutOnRing.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PutOnRing.java new file mode 100644 index 000000000..2cdaa1a78 --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PutOnRing.java @@ -0,0 +1,38 @@ +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.game.PhysicalCard; +import com.gempukku.lotro.game.state.LotroGame; +import com.gempukku.lotro.logic.actions.CostToEffectAction; +import com.gempukku.lotro.logic.effects.PutOnTheOneRingEffect; +import com.gempukku.lotro.logic.timing.Effect; +import com.gempukku.lotro.logic.timing.EffectResult; +import org.json.simple.JSONObject; + +public class PutOnRing implements EffectAppenderProducer { + @Override + public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { + FieldUtils.validateAllowedFields(effectObject); + return new AbstractEffectAppender() { + @Override + protected Effect createEffect(CostToEffectAction action, String playerId, LotroGame game, PhysicalCard self, EffectResult effectResult, Effect effect) { + return new PutOnTheOneRingEffect(); + } + + @Override + public boolean isPlayableInFull(String playerId, LotroGame game, PhysicalCard self, EffectResult effectResult, Effect effect) { + return !game.getGameState().isWearingRing(); + } + }; + } + + @Override + public Requirement createCostRequirement(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { + return (playerId, game, self, effectResult, effect) -> !game.getGameState().isWearingRing(); + } +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/resolver/CardResolver.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/resolver/CardResolver.java index 42f2647f6..031acadca 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/resolver/CardResolver.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/resolver/CardResolver.java @@ -116,6 +116,26 @@ public class CardResolver { }; } }; + } else if (type.startsWith("all(") && type.endsWith(")")) { + final String filter = type.substring(type.indexOf("(") + 1, type.lastIndexOf(")")); + final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter); + return new AbstractEffectAppender() { + @Override + protected Effect createEffect(CostToEffectAction action, String playerId, LotroGame game, PhysicalCard self, EffectResult effectResult, Effect effect) { + return new UnrespondableEffect() { + @Override + protected void doPlayEffect(LotroGame game) { + final Filterable filterable = filterableSource.getFilterable(playerId, game, self, effectResult, effect); + action.setCardMemory(memory, Filters.filterActive(game, filterable)); + } + }; + } + + @Override + public boolean isPlayableInFull(String playerId, LotroGame game, PhysicalCard self, EffectResult effectResult, Effect effect) { + return true; + } + }; } else if (type.startsWith("choose(") && type.endsWith(")")) { final String filter = type.substring(type.indexOf("(") + 1, type.lastIndexOf(")")); final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter); @@ -146,6 +166,6 @@ public class CardResolver { } }; } - throw new RuntimeException("Unable to resolve card resolver of type: " + type); + throw new InvalidCardDefinitionException("Unable to resolve card resolver of type: " + type); } } diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/requirement/RequirementFactory.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/requirement/RequirementFactory.java index 87373a9ca..61ea04007 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/requirement/RequirementFactory.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/requirement/RequirementFactory.java @@ -18,6 +18,7 @@ public class RequirementFactory { requirementProducers.put("controlssite", new ControlsSite()); requirementProducers.put("twilightpoollessthan", new TwilightPoolLessThan()); requirementProducers.put("location", new Location()); + requirementProducers.put("ringison", new RingIsOn()); } public Requirement getRequirement(JSONObject object, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/requirement/RingIsOn.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/requirement/RingIsOn.java new file mode 100644 index 000000000..820d9d221 --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/requirement/RingIsOn.java @@ -0,0 +1,13 @@ +package com.gempukku.lotro.cards.build.field.effect.requirement; + +import com.gempukku.lotro.cards.build.CardGenerationEnvironment; +import com.gempukku.lotro.cards.build.InvalidCardDefinitionException; +import com.gempukku.lotro.cards.build.Requirement; +import org.json.simple.JSONObject; + +public class RingIsOn implements RequirementProducer { + @Override + public Requirement getPlayRequirement(JSONObject object, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { + return (playerId, game, self, effectResult, effect) -> game.getGameState().isWearingRing(); + } +} diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/AboutToTakeWound.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/AboutToTakeWound.java new file mode 100644 index 000000000..28f4b7fae --- /dev/null +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/AboutToTakeWound.java @@ -0,0 +1,44 @@ +package com.gempukku.lotro.cards.build.field.effect.trigger; + +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.filters.Filters; +import com.gempukku.lotro.game.PhysicalCard; +import com.gempukku.lotro.game.state.LotroGame; +import com.gempukku.lotro.logic.timing.Effect; +import com.gempukku.lotro.logic.timing.EffectResult; +import com.gempukku.lotro.logic.timing.TriggerConditions; +import org.json.simple.JSONObject; + +public class AboutToTakeWound implements TriggerCheckerProducer { + @Override + public TriggerChecker getTriggerChecker(JSONObject value, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { + FieldUtils.validateAllowedFields(value, "source", "filter"); + + String source = FieldUtils.getString(value.get("source"), "source", "any"); + String filter = FieldUtils.getString(value.get("filter"), "source"); + + final FilterableSource sourceFilter = environment.getFilterFactory().generateFilter(source); + final FilterableSource affectedFilter = environment.getFilterFactory().generateFilter(filter); + + return new TriggerChecker() { + @Override + public boolean accepts(String playerId, LotroGame game, PhysicalCard self, EffectResult effectResult, Effect effect) { + final Filterable sourceFilterable = sourceFilter.getFilterable(playerId, game, self, effectResult, effect); + final Filterable affected = affectedFilter.getFilterable(playerId, game, self, effectResult, effect); + if (sourceFilterable == Filters.any) + return TriggerConditions.isGettingWounded(effect, game, affected); + else + return TriggerConditions.isGettingWoundedBy(effect, game, sourceFilterable, affected); + } + + @Override + public boolean isBefore() { + return true; + } + }; + } +} 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 f41ef3fd5..f2374cb5e 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 @@ -17,6 +17,7 @@ public class TriggerCheckerFactory { triggerCheckers.put("losesskirmish", new LosesSkirmish()); triggerCheckers.put("winsskirmish", new WinsSkirmish()); triggerCheckers.put("startofturn", new StartOfTurn()); + triggerCheckers.put("abouttotakewound", new AboutToTakeWound()); } public TriggerChecker getTriggerChecker(JSONObject object, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {