Set 2 Elven cards in new system

This commit is contained in:
marcin.sciesinski
2019-10-26 17:16:06 -07:00
parent 3691f21132
commit f91842c44a
10 changed files with 255 additions and 290 deletions

View File

@@ -0,0 +1,183 @@
{
"2_16": {
"title": "A Blended Race",
"culture": "elven",
"cost": 1,
"type": "condition",
"condition": {
"type": "canSpot",
"filter": "elf"
},
"keyword": "support area",
"effects": [
{
"type": "modifier",
"modifier": {
"type": "modifyStrength",
"filter": "uruk-hai",
"amount": -2
}
},
{
"type": "modifier",
"modifier": {
"type": "removeKeyword",
"filter": "uruk-hai",
"keyword": "damage"
}
},
{
"type": "trigger",
"trigger": {
"type": "startOfPhase",
"phase": "regroup"
},
"effect": {
"type": "discard",
"filter": "self"
}
}
]
},
"2_17": {
"title": "Dismay Our Enemies",
"culture": "elven",
"cost": 0,
"type": "event",
"keyword": "response",
"effects": {
"type": "responseEvent",
"trigger": {
"type": "winsSkirmish",
"filter": "elf,archer"
},
"effect": {
"type": "preventable",
"player": "shadowPlayer",
"effect": {
"type": "discard",
"player": "shadowPlayer",
"filter": "choose(minion)"
},
"text": "Would you like to remove (3) to prevent discarding a minion?",
"cost": {
"type": "removeTwilight",
"amount": 3
}
}
}
},
"2_18": {
"title": "Hosts of the Last Alliance",
"culture": "elven",
"cost": 2,
"type": "condition",
"keyword": [
"tale",
"support area"
],
"effects": [
{
"type": "modifier",
"modifier": {
"type": "modifyArcheryTotal",
"side": "shadow",
"condition": {
"type": "canSpot",
"filter": "elf,companion"
},
"amount": -1
}
},
{
"type": "activatedTrigger",
"trigger": {
"type": "aboutToTakeWound",
"filter": "elf"
},
"cost": {
"type": "discard",
"filter": "self"
},
"effect": {
"type": "preventWound",
"filter": "choose(elf)"
}
}
]
},
"2_19": {
"title": "Release the Angry Flood",
"culture": "elven",
"cost": 1,
"type": "event",
"keyword": "maneuver",
"effects": {
"type": "event",
"cost": {
"type": "exert",
"filter": "choose(elf)"
},
"effect": {
"type": "wound",
"filter": "all(nazgul)",
"times": {
"type": "condition",
"condition": {
"type": "location",
"filter": "river"
},
"true": 2,
"false": 1
}
}
}
},
"2_20": {
"title": "Secret Sentinels",
"culture": "elven",
"cost": 2,
"type": "event",
"keyword": "maneuver",
"effects": {
"type": "event",
"cost": {
"type": "exert",
"filter": "choose(elf,ally)"
},
"effect": [
{
"type": "memorizeNumber",
"memory": "discardCount",
"amount": 1
},
{
"type": "conditional",
"condition": {
"type": "canSpot",
"filter": "orc"
},
"effect": {
"type": "chooseYesOrNo",
"text": "Would you like to spot an Orc?",
"memorize": "discardCount",
"yes": "2",
"no": "1"
}
},
{
"type": "discard",
"filter": "choose(condition)",
"count": {
"type": "range",
"from": 1,
"to": {
"type": "fromMemory",
"memory": "discardCount"
}
}
}
]
}
}
}

View File

@@ -1,59 +0,0 @@
package com.gempukku.lotro.cards.set2.elven;
import com.gempukku.lotro.common.*;
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.RequiredTriggerAction;
import com.gempukku.lotro.logic.cardtype.AbstractPermanent;
import com.gempukku.lotro.logic.effects.SelfDiscardEffect;
import com.gempukku.lotro.logic.modifiers.Modifier;
import com.gempukku.lotro.logic.modifiers.RemoveKeywordModifier;
import com.gempukku.lotro.logic.modifiers.StrengthModifier;
import com.gempukku.lotro.logic.timing.EffectResult;
import com.gempukku.lotro.logic.timing.TriggerConditions;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* Set: Mines of Moria
* Side: Free
* Culture: Elven
* Twilight Cost: 1
* Type: Condition
* Game Text: To play, spot an Elf. Plays to your support area. Each Uruk-hai is strength -2 and loses all damage
* bonuses. Discard this condition during the regroup phase.
*/
public class Card2_016 extends AbstractPermanent {
public Card2_016() {
super(Side.FREE_PEOPLE, 1, CardType.CONDITION, Culture.ELVEN, "A Blended Race");
}
@Override
public boolean checkPlayRequirements(LotroGame game, PhysicalCard self) {
return Filters.canSpot(game, Race.ELF);
}
@Override
public List<? extends Modifier> getInPlayModifiers(LotroGame game, PhysicalCard self) {
List<Modifier> modifiers = new LinkedList<Modifier>();
modifiers.add(
new StrengthModifier(self, Race.URUK_HAI, -2));
modifiers.add(
new RemoveKeywordModifier(self, Race.URUK_HAI, Keyword.DAMAGE));
return modifiers;
}
@Override
public List<RequiredTriggerAction> getRequiredAfterTriggers(LotroGame game, EffectResult effectResult, PhysicalCard self) {
if (TriggerConditions.startOfPhase(game, effectResult, Phase.REGROUP)) {
RequiredTriggerAction action = new RequiredTriggerAction(self);
action.appendEffect(
new SelfDiscardEffect(self));
return Collections.singletonList(action);
}
return null;
}
}

View File

@@ -1,69 +0,0 @@
package com.gempukku.lotro.cards.set2.elven;
import com.gempukku.lotro.common.*;
import com.gempukku.lotro.filters.Filters;
import com.gempukku.lotro.game.PhysicalCard;
import com.gempukku.lotro.game.state.LotroGame;
import com.gempukku.lotro.logic.PlayUtils;
import com.gempukku.lotro.logic.actions.CostToEffectAction;
import com.gempukku.lotro.logic.actions.PlayEventAction;
import com.gempukku.lotro.logic.cardtype.AbstractResponseEvent;
import com.gempukku.lotro.logic.effects.PreventableEffect;
import com.gempukku.lotro.logic.effects.RemoveTwilightEffect;
import com.gempukku.lotro.logic.effects.choose.ChooseAndDiscardCardsFromPlayEffect;
import com.gempukku.lotro.logic.effects.choose.ChooseOpponentEffect;
import com.gempukku.lotro.logic.timing.Effect;
import com.gempukku.lotro.logic.timing.EffectResult;
import com.gempukku.lotro.logic.timing.PlayConditions;
import com.gempukku.lotro.logic.timing.TriggerConditions;
import java.util.Collections;
import java.util.List;
/**
* Set: Mines of Moria
* Side: Free
* Culture: Elven
* Twilight Cost: 0
* Type: Event
* Game Text: Response: If an Elf archer wins a skirmish, make an opponent choose a minion to discard. That opponent
* may remove (3) to prevent this.
*/
public class Card2_017 extends AbstractResponseEvent {
public Card2_017() {
super(Side.FREE_PEOPLE, 0, Culture.ELVEN, "Dismay Our Enemies");
}
@Override
public List<PlayEventAction> getPlayResponseEventAfterActions(String playerId, LotroGame game, EffectResult effectResult, final PhysicalCard self) {
if (TriggerConditions.winsSkirmish(game, effectResult, Filters.and(Race.ELF, Keyword.ARCHER))
&& PlayConditions.canPlayCardDuringPhase(game, (Phase) null, self)
&& PlayUtils.checkPlayRequirements(game, self, Filters.any, 0, 0, false, false)) {
final PlayEventAction action = new PlayEventAction(self);
action.appendEffect(
new ChooseOpponentEffect(playerId) {
@Override
protected void opponentChosen(String opponentId) {
action.appendEffect(
new PreventableEffect(action,
new ChooseAndDiscardCardsFromPlayEffect(action, opponentId, 1, 1, CardType.MINION) {
@Override
public String getText(LotroGame game) {
return "Choose minion to discard";
}
},
Collections.singletonList(opponentId),
new PreventableEffect.PreventionCost() {
@Override
public Effect createPreventionCostForPlayer(CostToEffectAction subAction, String playerId) {
return new RemoveTwilightEffect(3);
}
}
));
}
});
return Collections.singletonList(action);
}
return null;
}
}

View File

@@ -1,56 +0,0 @@
package com.gempukku.lotro.cards.set2.elven;
import com.gempukku.lotro.common.*;
import com.gempukku.lotro.game.PhysicalCard;
import com.gempukku.lotro.game.state.LotroGame;
import com.gempukku.lotro.logic.actions.ActivateCardAction;
import com.gempukku.lotro.logic.cardtype.AbstractPermanent;
import com.gempukku.lotro.logic.effects.PreventableCardEffect;
import com.gempukku.lotro.logic.effects.SelfDiscardEffect;
import com.gempukku.lotro.logic.effects.WoundCharactersEffect;
import com.gempukku.lotro.logic.effects.choose.ChooseAndPreventCardEffect;
import com.gempukku.lotro.logic.modifiers.ArcheryTotalModifier;
import com.gempukku.lotro.logic.modifiers.Modifier;
import com.gempukku.lotro.logic.modifiers.SpotCondition;
import com.gempukku.lotro.logic.timing.Effect;
import com.gempukku.lotro.logic.timing.TriggerConditions;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* Set: Mines of Moria
* Side: Free
* Culture: Elven
* Twilight Cost: 2
* Type: Condition
* Game Text: Tale. Plays to your support area. While you can spot an Elf companion, the minion archery total is -1.
* Response: If an Elf is about to take a wound, discard this condition to prevent that wound.
*/
public class Card2_018 extends AbstractPermanent {
public Card2_018() {
super(Side.FREE_PEOPLE, 2, CardType.CONDITION, Culture.ELVEN, "Hosts of the Last Alliance");
addKeyword(Keyword.TALE);
}
@Override
public List<? extends Modifier> getInPlayModifiers(LotroGame game, PhysicalCard self) {
return Collections.singletonList(new ArcheryTotalModifier(self, Side.SHADOW, new SpotCondition(Race.ELF, CardType.COMPANION), -1));
}
@Override
public List<? extends ActivateCardAction> getOptionalInPlayBeforeActions(String playerId, LotroGame game, Effect effect, PhysicalCard self) {
if (TriggerConditions.isGettingWounded(effect, game, Race.ELF)) {
final WoundCharactersEffect woundEffect = (WoundCharactersEffect) effect;
Collection<PhysicalCard> woundedCharacters = woundEffect.getAffectedCardsMinusPrevented(game);
final ActivateCardAction action = new ActivateCardAction(self);
action.appendCost(
new SelfDiscardEffect(self));
action.appendEffect(
new ChooseAndPreventCardEffect(self, (PreventableCardEffect) effect, playerId, "Choose an Elf", Race.ELF));
return Collections.singletonList(action);
}
return null;
}
}

View File

@@ -1,42 +0,0 @@
package com.gempukku.lotro.cards.set2.elven;
import com.gempukku.lotro.common.*;
import com.gempukku.lotro.game.PhysicalCard;
import com.gempukku.lotro.game.state.LotroGame;
import com.gempukku.lotro.logic.actions.PlayEventAction;
import com.gempukku.lotro.logic.cardtype.AbstractEvent;
import com.gempukku.lotro.logic.effects.WoundCharactersEffect;
import com.gempukku.lotro.logic.effects.choose.ChooseAndExertCharactersEffect;
import com.gempukku.lotro.logic.timing.PlayConditions;
/**
* Set: Mines of Moria
* Side: Free
* Culture: Elven
* Twilight Cost: 1
* Type: Event
* Game Text: Maneuver: Exert an Elf to wound each Nazgul once (or twice if at a river).
*/
public class Card2_019 extends AbstractEvent {
public Card2_019() {
super(Side.FREE_PEOPLE, 1, Culture.ELVEN, "Release the Angry Flood", Phase.MANEUVER);
}
@Override
public boolean checkPlayRequirements(LotroGame game, PhysicalCard self) {
return PlayConditions.canExert(self, game, Race.ELF);
}
@Override
public PlayEventAction getPlayEventCardAction(String playerId, LotroGame game, PhysicalCard self) {
PlayEventAction action = new PlayEventAction(self);
action.appendCost(
new ChooseAndExertCharactersEffect(action, playerId, 1, 1, Race.ELF));
action.appendEffect(
new WoundCharactersEffect(self, Race.NAZGUL));
if (PlayConditions.location(game, Keyword.RIVER))
action.appendEffect(
new WoundCharactersEffect(self, Race.NAZGUL));
return action;
}
}

View File

@@ -1,59 +0,0 @@
package com.gempukku.lotro.cards.set2.elven;
import com.gempukku.lotro.common.*;
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.PlayEventAction;
import com.gempukku.lotro.logic.cardtype.AbstractEvent;
import com.gempukku.lotro.logic.decisions.MultipleChoiceAwaitingDecision;
import com.gempukku.lotro.logic.effects.PlayoutDecisionEffect;
import com.gempukku.lotro.logic.effects.choose.ChooseAndDiscardCardsFromPlayEffect;
import com.gempukku.lotro.logic.effects.choose.ChooseAndExertCharactersEffect;
import com.gempukku.lotro.logic.timing.PlayConditions;
/**
* Set: Mines of Moria
* Side: Free
* Culture: Elven
* Twilight Cost: 2
* Type: Event
* Game Text: Maneuver: Exert an Elf ally to discard a condition (or 2 conditions if you spot an Orc).
*/
public class Card2_020 extends AbstractEvent {
public Card2_020() {
super(Side.FREE_PEOPLE, 2, Culture.ELVEN, "Secret Sentinels", Phase.MANEUVER);
}
@Override
public boolean checkPlayRequirements(LotroGame game, PhysicalCard self) {
return PlayConditions.canExert(self, game, Race.ELF, CardType.ALLY);
}
@Override
public PlayEventAction getPlayEventCardAction(final String playerId, LotroGame game, PhysicalCard self) {
final PlayEventAction action = new PlayEventAction(self);
action.appendCost(
new ChooseAndExertCharactersEffect(action, playerId, 1, 1, Race.ELF, CardType.ALLY));
if (Filters.canSpot(game, Race.ORC))
action.appendEffect(
new PlayoutDecisionEffect(playerId,
new MultipleChoiceAwaitingDecision(1, "Do you wish to spot an Orc?", new String[]{"Yes", "No"}) {
@Override
protected void validDecisionMade(int index, String result) {
if (result.equals("Yes")) {
action.appendEffect(
new ChooseAndDiscardCardsFromPlayEffect(action, playerId, 2, 2, CardType.CONDITION));
} else {
action.appendEffect(
new ChooseAndDiscardCardsFromPlayEffect(action, playerId, 1, 1, CardType.CONDITION));
}
}
}));
else
action.appendEffect(
new ChooseAndDiscardCardsFromPlayEffect(action, playerId, 1, 1, CardType.CONDITION));
return action;
}
}

View File

@@ -110,6 +110,7 @@ public class EffectAppenderFactory {
effectAppenderProducers.put("removecardsindiscardfromgame", new RemoveCardsInDiscardFromGame());
effectAppenderProducers.put("makeselfringbearer", new MakeSelfRingBearer());
effectAppenderProducers.put("choosearace", new ChooseARace());
effectAppenderProducers.put("chooseyesorno", new ChooseYesOrNo());
effectAppenderProducers.put("chooseakeyword", new ChooseAKeyword());
effectAppenderProducers.put("storewhileinzone", new StoreWhileInZone());
effectAppenderProducers.put("resetwhileinzonedata", new ResetWhileInZoneData());

View File

@@ -0,0 +1,45 @@
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.YesNoDecision;
import com.gempukku.lotro.logic.effects.PlayoutDecisionEffect;
import com.gempukku.lotro.logic.timing.Effect;
import org.json.simple.JSONObject;
public class ChooseYesOrNo implements EffectAppenderProducer {
@Override
public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
FieldUtils.validateAllowedFields(effectObject, "text", "memorize", "yes", "no");
final String text = FieldUtils.getString(effectObject.get("text"), "text");
if (text == null)
throw new InvalidCardDefinitionException("Text is required for Yes or No decision");
final String memorize = FieldUtils.getString(effectObject.get("memorize"), "memorize");
final String yesAnswer = FieldUtils.getString(effectObject.get("yes"), "yes");
final String noAnswer = FieldUtils.getString(effectObject.get("no"), "no");
return new DelayedAppender() {
@Override
protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
return new PlayoutDecisionEffect(actionContext.getPerformingPlayer(),
new YesNoDecision(text) {
@Override
protected void yes() {
actionContext.setValueToMemory(memorize, yesAnswer);
}
@Override
protected void no() {
actionContext.setValueToMemory(memorize, noAnswer);
}
});
}
};
}
}

View File

@@ -27,7 +27,7 @@ public class Wound implements EffectAppenderProducer {
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 ValueSource times = ValueResolver.resolveEvaluator(effectObject.get("times"), 1, environment);
final String filter = FieldUtils.getString(effectObject.get("filter"), "filter");
final String memory = FieldUtils.getString(effectObject.get("memorize"), "memorize", "_temp");
@@ -35,15 +35,16 @@ public class Wound implements EffectAppenderProducer {
result.addEffectAppender(
CardResolver.resolveCards(filter,
(actionContext) -> Filters.canTakeWounds(actionContext.getSource(), times),
(actionContext) -> Filters.canTakeWounds(actionContext.getSource(), times.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), null)),
valueSource, memory, player, "Choose cards to wound", environment));
result.addEffectAppender(
new DelayedAppender() {
@Override
protected List<? extends Effect> createEffects(boolean cost, CostToEffectAction action, ActionContext actionContext) {
final Collection<? extends PhysicalCard> cardsFromMemory = actionContext.getCardsFromMemory(memory);
final int timesCount = times.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), null);
List<Effect> result = new LinkedList<>();
for (int i = 0; i < times; i++)
for (int i = 0; i < timesCount; i++)
result.add(new WoundCharactersEffect(actionContext.getSource(), Filters.in(cardsFromMemory)));
return result;
}

View File

@@ -57,7 +57,27 @@ public class ValueResolver {
if (value instanceof JSONObject) {
JSONObject object = (JSONObject) value;
final String type = FieldUtils.getString(object.get("type"), "type");
if (type.equalsIgnoreCase("condition")) {
if (type.equalsIgnoreCase("range")) {
FieldUtils.validateAllowedFields(object, "from", "to");
ValueSource fromValue = resolveEvaluator(object.get("from"), environment);
ValueSource toValue = resolveEvaluator(object.get("to"), environment);
return new ValueSource() {
@Override
public Evaluator getEvaluator(ActionContext actionContext) {
throw new RuntimeException("Evaluator has resolved to range");
}
@Override
public int getMinimum(ActionContext actionContext) {
return fromValue.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), null);
}
@Override
public int getMaximum(ActionContext actionContext) {
return toValue.getEvaluator(actionContext).evaluateExpression(actionContext.getGame(), null);
}
};
} else if (type.equalsIgnoreCase("condition")) {
FieldUtils.validateAllowedFields(object, "condition", "true", "false");
final JSONObject[] conditionArray = FieldUtils.getObjectArray(object.get("condition"), "condition");
final Requirement[] conditions = environment.getRequirementFactory().getRequirements(conditionArray, environment);
@@ -238,7 +258,7 @@ public class ValueResolver {
final ValueSource valueSource = ValueResolver.resolveEvaluator(object.get("source"), 0, environment);
return (actionContext) -> new MultiplyEvaluator(multiplier, valueSource.getEvaluator(actionContext));
} else if (type.equalsIgnoreCase("cardAffectedLimitPerPhase")) {
FieldUtils.validateAllowedFields(object, "limit", "source","prefix");
FieldUtils.validateAllowedFields(object, "limit", "source", "prefix");
final int limit = FieldUtils.getInteger(object.get("limit"), "limit");
final String prefix = FieldUtils.getString(object.get("prefix"), "prefix", "");
final ValueSource valueSource = ValueResolver.resolveEvaluator(object.get("source"), 0, environment);