Added all the cards

This commit is contained in:
marcin.sciesinski
2019-09-01 02:03:40 -07:00
parent d34ed59829
commit 644f8448db
15 changed files with 511 additions and 14 deletions

View File

@@ -0,0 +1,57 @@
{
"40_314": {
"title": "Brute Force",
"side": "shadow",
"culture": "isengard",
"cost": 1,
"type": "event",
"keyword": "maneuver",
"effects": {
"type": "event",
"cost": [
{
"type": "exert",
"filter": "choose(uruk-hai)"
},
{
"type": "chooseAndRemoveTwilight",
"memorize": "twilightRemoved"
}
],
"effect": {
"type": "discard",
"filter": "choose(not(weapon),side(free people),possession,maxTwilight(memory(twilightRemoved)))"
}
}
},
"40_315": {
"title": "*Uruk Taskmaster",
"side": "shadow",
"culture": "isengard",
"cost": 4,
"type": "minion",
"race": "uruk-hai",
"strength": 9,
"vitality": 3,
"site": 5,
"effects": {
"type": "activated",
"phase": "skirmish",
"cost": [
{
"type": "exert",
"filter": "self"
},
{
"type": "removeTwilight",
"amount": 3
}
],
"effect": {
"type": "addKeyword",
"filter": "choose(uruk-hai)",
"keyword": "damage+1"
}
}
}
}

View File

@@ -60,5 +60,50 @@
"filter": "memory(unboundCompanion)"
}
}
},
"40_316": {
"title": "Deep Places of the World",
"side": "shadow",
"culture": "moria",
"cost": 1,
"type": "condition",
"keyword": "support area",
"effects": {
"type": "activated",
"phase": [
"shadow",
"maneuver"
],
"cost": {
"type": "removeTwilight",
"amount": 4
},
"effect": {
"type": "playCardFromDiscard",
"filter": "choose(culture(moria),goblin)",
"removedTwilight": 4
}
}
},
"40_317": {
"title": "Scurrying Away",
"side": "shadow",
"culture": "moria",
"cost": 2,
"type": "condition",
"keyword": "support area",
"effects": {
"type": "activated",
"phase": "skirmish",
"cost": {
"type": "removeTwilight",
"amount": 3
},
"effect": {
"type": "stackCards",
"filter": "choose(culture(moria),goblin)",
"where": "choose(culture(moria),support area,condition)"
}
}
}
}

View File

@@ -133,5 +133,33 @@
}
}
]
},
"40_318": {
"title": "*Orc Flanker",
"side": "shadow",
"culture": "sauron",
"cost": 3,
"type": "minion",
"race": "orc",
"strength": 8,
"vitality": 3,
"site": 6,
"keyword": "tracker",
"effects": {
"type": "activated",
"phase": "skirmish",
"condition": {
"type": "canSpot",
"filter": "not(self),tracker"
},
"cost": {
"type": "removeTwilight",
"amount": 4
},
"effect": {
"type": "exert",
"filter": "choose(companion,notAssignedToSkirmish)"
}
}
}
}

View File

@@ -239,5 +239,111 @@
}
}
]
},
"40_319": {
"title": "*A Hobbit's Tale",
"side": "free people",
"culture": "shire",
"cost": 2,
"type": "condition",
"target": "companion,ring bound,hobbit",
"keyword": "tale",
"effects": [
{
"type": "activated",
"phase": "maneuver",
"condition": [
{
"type": "location",
"filter": "siteNumber(1-4)"
},
{
"type": "canSpot",
"count": 2,
"filter": "hobbit,companion"
}
],
"cost": {
"type": "discard",
"filter": "self"
},
"effect": {
"type": "modifyStrength",
"until": "start(regroup)",
"filter": "all(hobbit,companion)",
"amount": 2
}
},
{
"type": "activated",
"phase": "maneuver",
"condition": {
"type": "location",
"filter": "siteNumber(1-4)"
},
"cost": [
{
"type": "memorize",
"filter": "hasAttached(self)",
"memory": "bearer"
},
{
"type": "discard",
"filter": "self"
}
],
"effect": [
{
"type": "heal",
"filter": "memory(bearer)"
},
{
"type": "removeBurdens"
}
]
}
]
},
"40_320": {
"title": "Get Out of the Shire",
"side": "free people",
"culture": "shire",
"cost": 1,
"type": "event",
"keyword": "skirmish",
"effects": {
"type": "event",
"effect": {
"type": "choice",
"texts": [
"Prevent Hobbit from being overwhelmed unless that Hobbit's strength is tripled",
"Cancel skirmish involving a Hobbit"
],
"effects": [
{
"type": "cantBeOverwhelmedMultiplier",
"filter": "choose(hobbit)"
},
{
"type": "conditional",
"condition": [
{
"type": "canSpot",
"count": 2,
"filter": "hobbit,companion"
},
{
"type": "location",
"filter": "siteNumber(1-4)"
}
],
"effect": {
"type": "cancelSkirmish",
"filter": "hobbit"
}
}
]
}
}
}
}

View File

@@ -310,4 +310,11 @@
40S310
40S311
40S312
40S313
40S313
40S314
40S315
40S316
40S317
40S318
40S319
40S320

View File

@@ -0,0 +1,82 @@
package com.gempukku.lotro.cards.build;
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 java.util.Collection;
public class DelegateActionContext implements ActionContext {
private ActionContext delegate;
private String performingPlayer;
private LotroGame game;
private PhysicalCard source;
private EffectResult effectResult;
private Effect effect;
public DelegateActionContext(ActionContext delegate, String performingPlayer, LotroGame game, PhysicalCard source, EffectResult effectResult, Effect effect) {
this.delegate = delegate;
this.performingPlayer = performingPlayer;
this.game = game;
this.source = source;
this.effectResult = effectResult;
this.effect = effect;
}
@Override
public void setValueToMemory(String memory, String value) {
delegate.setValueToMemory(memory, value);
}
@Override
public String getValueFromMemory(String memory) {
return delegate.getValueFromMemory(memory);
}
@Override
public void setCardMemory(String memory, PhysicalCard card) {
delegate.setCardMemory(memory, card);
}
@Override
public void setCardMemory(String memory, Collection<? extends PhysicalCard> cards) {
delegate.setCardMemory(memory, cards);
}
@Override
public Collection<? extends PhysicalCard> getCardsFromMemory(String memory) {
return delegate.getCardsFromMemory(memory);
}
@Override
public PhysicalCard getCardFromMemory(String memory) {
return delegate.getCardFromMemory(memory);
}
@Override
public String getPerformingPlayer() {
return performingPlayer;
}
@Override
public LotroGame getGame() {
return game;
}
@Override
public PhysicalCard getSource() {
return source;
}
@Override
public EffectResult getEffectResult() {
return effectResult;
}
@Override
public Effect getEffect() {
return effect;
}
}

View File

@@ -60,6 +60,9 @@ public class EffectAppenderFactory {
effectAppenderProducers.put("play", new PlayCardFromHand());
effectAppenderProducers.put("cancelskirmish", new CancelSkirmish());
effectAppenderProducers.put("discardfromhand", new CancelSkirmish());
effectAppenderProducers.put("chooseandremovetwilight", new ChooseAndRemoveTwilight());
effectAppenderProducers.put("removetwilight", new RemoveTwilight());
effectAppenderProducers.put("stackcards", new StackCardsFromPlay());
}
public EffectAppender getEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {

View File

@@ -0,0 +1,50 @@
package com.gempukku.lotro.cards.build.field.effect.appender;
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.cards.build.field.effect.EffectAppender;
import com.gempukku.lotro.cards.build.field.effect.EffectAppenderProducer;
import com.gempukku.lotro.logic.actions.CostToEffectAction;
import com.gempukku.lotro.logic.decisions.DecisionResultInvalidException;
import com.gempukku.lotro.logic.decisions.IntegerAwaitingDecision;
import com.gempukku.lotro.logic.effects.PlayoutDecisionEffect;
import com.gempukku.lotro.logic.effects.RemoveTwilightEffect;
import com.gempukku.lotro.logic.timing.Effect;
import org.json.simple.JSONObject;
public class ChooseAndRemoveTwilight implements EffectAppenderProducer {
@Override
public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
FieldUtils.validateAllowedFields(effectObject, "memorize");
final String memorize = FieldUtils.getString(effectObject.get("memorize"), "memorize");
MultiEffectAppender result = new MultiEffectAppender();
result.addEffectAppender(
new DelayedAppender() {
@Override
protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
return new PlayoutDecisionEffect(actionContext.getPerformingPlayer(),
new IntegerAwaitingDecision(1, "How much twilight do you wish to remove",
0, actionContext.getGame().getGameState().getTwilightPool()) {
@Override
public void decisionMade(String result) throws DecisionResultInvalidException {
actionContext.setValueToMemory(memorize, String.valueOf(getValidatedResult(result)));
}
});
}
});
result.addEffectAppender(
new DelayedAppender() {
@Override
protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
int twilight = Integer.parseInt(actionContext.getValueFromMemory(memorize));
return new RemoveTwilightEffect(twilight);
}
});
return result;
}
}

View File

@@ -54,7 +54,9 @@ public class ConditionEffect implements EffectAppenderProducer {
// TODO, maybe check the requirements, and if met, check if the effect is playable?
@Override
public boolean isPlayableInFull(ActionContext actionContext) {
return true;
if (!checkConditions(actionContext))
return false;
return effectAppender.isPlayableInFull(actionContext);
}
};
}

View File

@@ -21,9 +21,10 @@ import org.json.simple.JSONObject;
public class PlayCardFromDiscard implements EffectAppenderProducer {
@Override
public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
FieldUtils.validateAllowedFields(effectObject, "filter");
FieldUtils.validateAllowedFields(effectObject, "filter", "removedTwilight");
final String filter = FieldUtils.getString(effectObject.get("filter"), "filter");
final int removedTwilight = FieldUtils.getInteger(effectObject.get("removedTwilight"), "removedTwilight", 0);
MultiEffectAppender result = new MultiEffectAppender();
result.setPlayabilityCheckedForEffect(true);
@@ -31,6 +32,7 @@ public class PlayCardFromDiscard implements EffectAppenderProducer {
result.addEffectAppender(
CardResolver.resolveCardsInDiscard(filter,
(actionContext) -> Filters.playable(actionContext.getGame()),
(actionContext) -> Filters.playable(actionContext.getGame(), removedTwilight, 0, false, false),
new ConstantEvaluator(1), "_temp", "you", "Choose card to play", environment));
result.addEffectAppender(
new DelayedAppender() {
@@ -46,6 +48,11 @@ public class PlayCardFromDiscard implements EffectAppenderProducer {
final LotroGame game = actionContext.getGame();
return !game.getModifiersQuerying().hasFlagActive(game, ModifierFlag.CANT_PLAY_FROM_DISCARD_OR_DECK);
}
@Override
public boolean isPlayabilityCheckedForEffect() {
return true;
}
});
return result;

View File

@@ -1,9 +1,6 @@
package com.gempukku.lotro.cards.build.field.effect.appender;
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.PlayerSource;
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;
@@ -44,7 +41,10 @@ public class PreventableAppenderProducer implements EffectAppenderProducer {
new YesNoDecision(text) {
@Override
protected void yes() {
costAppender.appendEffect(false, subAction, actionContext);
DelegateActionContext delegate = new DelegateActionContext(actionContext,
preventingPlayer, actionContext.getGame(), actionContext.getSource(), actionContext.getEffectResult(),
actionContext.getEffect());
costAppender.appendEffect(false, subAction, delegate);
}
@Override

View File

@@ -0,0 +1,36 @@
package com.gempukku.lotro.cards.build.field.effect.appender;
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.ValueSource;
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.ValueResolver;
import com.gempukku.lotro.logic.actions.CostToEffectAction;
import com.gempukku.lotro.logic.effects.RemoveTwilightEffect;
import com.gempukku.lotro.logic.timing.Effect;
import org.json.simple.JSONObject;
public class RemoveTwilight implements EffectAppenderProducer {
@Override
public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
FieldUtils.validateAllowedFields(effectObject, "amount");
final ValueSource amount = ValueResolver.resolveEvaluator(effectObject.get("amount"), 1, environment);
return new DelayedAppender() {
@Override
protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
int value = amount.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), null);
return new RemoveTwilightEffect(value);
}
@Override
public boolean isPlayableInFull(ActionContext actionContext) {
int value = amount.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), null);
return actionContext.getGame().getGameState().getTwilightPool() >= value;
}
};
}
}

View File

@@ -0,0 +1,56 @@
package com.gempukku.lotro.cards.build.field.effect.appender;
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.ValueSource;
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.cards.build.field.effect.appender.resolver.ValueResolver;
import com.gempukku.lotro.game.PhysicalCard;
import com.gempukku.lotro.logic.actions.CostToEffectAction;
import com.gempukku.lotro.logic.effects.StackCardFromPlayEffect;
import com.gempukku.lotro.logic.timing.Effect;
import org.json.simple.JSONObject;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
public class StackCardsFromPlay implements EffectAppenderProducer {
@Override
public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
FieldUtils.validateAllowedFields(effectObject, "filter", "where", "count");
final String filter = FieldUtils.getString(effectObject.get("filter"), "filter", "choose(any)");
final String where = FieldUtils.getString(effectObject.get("where"), "where");
final ValueSource valueSource = ValueResolver.resolveEvaluator(effectObject.get("count"), 1, environment);
MultiEffectAppender result = new MultiEffectAppender();
result.addEffectAppender(
CardResolver.resolveCard(where, "_temp1", "you", "Choose card to stack on", environment));
result.addEffectAppender(
CardResolver.resolveCards(filter, valueSource, "_temp2", "you", "Choose cards to stack", environment));
result.addEffectAppender(
new DelayedAppender() {
@Override
protected List<? extends Effect> createEffects(boolean cost, CostToEffectAction action, ActionContext actionContext) {
final PhysicalCard card = actionContext.getCardFromMemory("_temp1");
final Collection<? extends PhysicalCard> cardsInHand = actionContext.getCardsFromMemory("_temp2");
List<Effect> result = new LinkedList<>();
for (PhysicalCard physicalCard : cardsInHand) {
result.add(new StackCardFromPlayEffect(physicalCard, card));
}
return result;
}
});
return result;
}
}

View File

@@ -160,6 +160,10 @@ public class CardResolver {
}
public static EffectAppender resolveCardsInDiscard(String type, FilterableSource additionalFilter, ValueSource countSource, String memory, String choicePlayer, String choiceText, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
return resolveCardsInDiscard(type, additionalFilter, additionalFilter, countSource, memory, choicePlayer, choiceText, environment);
}
public static EffectAppender resolveCardsInDiscard(String type, FilterableSource choiceFilter, FilterableSource playabilityFilter, ValueSource countSource, String memory, String choicePlayer, String choiceText, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
if (type.startsWith("memory(") && type.endsWith(")")) {
final PlayerSource playerSource = PlayerResolver.resolvePlayer(choicePlayer, environment);
@@ -167,11 +171,11 @@ public class CardResolver {
return new DelayedAppender() {
@Override
public boolean isPlayableInFull(ActionContext actionContext) {
if (additionalFilter != null) {
if (playabilityFilter != null) {
int min = countSource.getMinimum(null);
String choicePlayerId = playerSource.getPlayer(actionContext);
final Collection<? extends PhysicalCard> cardsFromMemory = actionContext.getCardsFromMemory(sourceMemory);
Filterable filter = additionalFilter.getFilterable(actionContext);
Filterable filter = playabilityFilter.getFilterable(actionContext);
final LotroGame game = actionContext.getGame();
return Filters.filter(game.getGameState().getDiscard(choicePlayerId), game, filter, Filters.in(cardsFromMemory)).size() >= min;
}
@@ -199,8 +203,8 @@ public class CardResolver {
final Filterable filterable = filterableSource.getFilterable(actionContext);
String choicePlayerId = playerSource.getPlayer(actionContext);
Filterable additionalFilterable = Filters.any;
if (additionalFilter != null)
additionalFilterable = additionalFilter.getFilterable(actionContext);
if (playabilityFilter != null)
additionalFilterable = playabilityFilter.getFilterable(actionContext);
final LotroGame game = actionContext.getGame();
return Filters.filter(game.getGameState().getDiscard(choicePlayerId), game, filterable, additionalFilterable).size() >= min;
}
@@ -212,8 +216,8 @@ public class CardResolver {
final Filterable filterable = filterableSource.getFilterable(actionContext);
String choicePlayerId = playerSource.getPlayer(actionContext);
Filterable additionalFilterable = Filters.any;
if (additionalFilter != null)
additionalFilterable = additionalFilter.getFilterable(actionContext);
if (choiceFilter != null)
additionalFilterable = choiceFilter.getFilterable(actionContext);
return new ChooseCardsFromDiscardEffect(choicePlayerId, min, max, filterable, additionalFilterable) {
@Override
protected void cardsSelected(LotroGame game, Collection<PhysicalCard> cards) {

View File

@@ -148,13 +148,27 @@ public class FilterFactory {
});
parameterFilters.put("memory",
(parameter, filterFactory) -> (actionContext) -> Filters.in(actionContext.getCardsFromMemory(parameter)));
parameterFilters.put("maxTwilight",
(parameter, filterFactory) -> (actionContext) -> {
if (parameter.startsWith("memory(") && parameter.endsWith(")")) {
String memory = parameter.substring(parameter.indexOf("(") + 1, parameter.lastIndexOf(")"));
final int value = Integer.parseInt(actionContext.getValueFromMemory(memory));
return Filters.maxPrintedTwilightCost(value);
} else {
int value = Integer.parseInt(parameter);
return Filters.maxPrintedTwilightCost(value);
}
});
}
private void appendFilter(Filterable value) {
final String filterName = value.toString().toLowerCase().replace("_", " ");
final String optionalFilterName = value.toString().toLowerCase().replace("_", "-");
if (simpleFilters.containsKey(filterName))
throw new RuntimeException("Duplicate filter name: " + filterName);
simpleFilters.put(filterName, (actionContext) -> value);
if (!optionalFilterName.equals(filterName))
simpleFilters.put(optionalFilterName, (actionContext -> value));
}
public FilterableSource generateFilter(String value) throws InvalidCardDefinitionException {