Couple of Isengard cards

This commit is contained in:
marcin.sciesinski
2019-09-04 19:51:53 -07:00
parent d35667d670
commit d3a383cc0b
21 changed files with 517 additions and 615 deletions

View File

@@ -312,6 +312,355 @@
}
]
},
"40_133": {
"title": "Relentless Uruk",
"culture": "isengard",
"cost": 4,
"type": "minion",
"race": "uruk-hai",
"strength": 9,
"vitality": 2,
"site": 5,
"keyword": "damage+1",
"effects": {
"type": "modifier",
"modifier": {
"type": "addKeyword",
"condition": {
"type": "location",
"filter": "battleground"
},
"filter": "self",
"keyword": "fierce"
}
}
},
"40_134": {
"title": "*Saruman",
"subtitle": "Mind of Metal",
"culture": "isengard",
"cost": 4,
"type": "minion",
"race": "wizard",
"strength": 8,
"vitality": 8,
"site": 4,
"keyword": "cunning",
"effects": [
{
"type": "trigger",
"trigger": {
"type": "startOfPhase",
"phase": "maneuver"
},
"optional": true,
"effect": {
"type": "addTwilight",
"amount": {
"type": "forEachThreat"
}
}
},
{
"type": "activated",
"phase": "shadow",
"cost": {
"type": "exert",
"filter": "self"
},
"effect": {
"type": "playCardFromDiscard",
"filter": "choose(name(Saruman's Staff))"
}
}
]
},
"40_135": {
"title": "*Saruman",
"subtitle": "The White Wizard",
"culture": "isengard",
"cost": 4,
"type": "minion",
"race": "wizard",
"strength": 8,
"vitality": 4,
"site": 4,
"effects": {
"type": "activated",
"phase": "skirmish",
"cost": [
{
"type": "exert",
"filter": "choose(name(Saruman))"
},
{
"type": "discardStackedCards",
"on": "culture(isengard),artifact",
"filter": "choose(spell)"
}
],
"effect": {
"type": "preventable",
"player": "fp",
"effect": {
"type": "wound",
"filter": "choose(companion,inSkirmishAgainst(name(Saruman)))"
},
"cost": {
"type": "addThreats",
"player": "fp"
}
}
}
},
"40_136": {
"title": "Saruman's Ambition",
"culture": "isengard",
"cost": 0,
"type": "condition",
"keyword": "support area",
"effects": [
{
"type": "modifier",
"modifier": {
"type": "modifyCost",
"amount": -1,
"filter": "culture(isengard),event"
}
},
{
"type": "activated",
"phase": "skirmish",
"cost": {
"type": "discard",
"filter": "self"
},
"effect": {
"type": "modifyStrength",
"filter": "choose(uruk-hai)",
"amount": 2
}
}
]
},
"40_137": {
"title": "*Saruman's Staff",
"subtitle": "Instrument of War",
"culture": "isengard",
"cost": 2,
"type": "artifact",
"possession": "staff",
"strength": 2,
"vitality": 1,
"target": "name(Saruman)",
"effects": [
{
"type": "modifier",
"modifier": {
"type": "removeKeyword",
"filter": "bearer",
"keyword": "cunning"
}
},
{
"type": "modifier",
"modifier": {
"type": "addKeyword",
"filter": "bearer",
"keyword": "fierce"
}
},
{
"type": "activatedTrigger",
"trigger": {
"type": "aboutToTakeWound",
"filter": "bearer"
},
"cost": {
"type": "removeThreats"
},
"effect": {
"type": "preventWound",
"filter": "choose(bearer)"
}
}
]
},
"40_138": {
"title": "Seeking My Counsel",
"culture": "isengard",
"cost": 2,
"type": "event",
"keyword": "shadow",
"effects": {
"type": "event",
"cost": {
"type": "choice",
"texts": [
"Play Saruman from your draw deck",
"Play Saruman from your discard pile"
],
"effects": [
{
"type": "playCardFromDrawDeck",
"filter": "choose(name(Saruman))"
},
{
"type": "playCardFromDiscard",
"filter": "choose(name(Saruman))"
}
]
},
"effect": {
"type": "addThreats",
"amount": {
"type": "forRegionNumber"
}
}
}
},
"40_139": {
"title": "Sword of Orthanc",
"culture": "isengard",
"cost": 1,
"type": "possession",
"possession": "hand weapon",
"strength": 2,
"target": "uruk-hai",
"effects": {
"type": "modifier",
"modifier": {
"type": "cantTakeWounds",
"filter": "bearer",
"condition": {
"type": "not",
"condition": {
"type": "phase",
"phase": "skirmish"
}
}
}
}
},
"40_140": {
"title": "*Ten Thousand Strong",
"culture": "isengard",
"cost": 0,
"type": "condition",
"target": "site",
"effects": [
{
"type": "extraCost",
"cost": {
"type": "exert",
"filter": "choose(uruk-hai)"
}
},
{
"type": "modifier",
"modifier": {
"type": "addKeyword",
"filter": "uruk-hai",
"keyword": "fierce",
"condition": {
"type": "location",
"filter": "hasAttached(self)"
}
}
},
{
"type": "activated",
"phase": "shadow",
"condition": {
"type": "canSpot",
"filter": "uruk-hai"
},
"cost": {
"type": "discard",
"filter": "self"
},
"effect": {
"type": "playCardFromDiscard",
"filter": "choose(uruk-hai)"
}
}
]
},
"40_141": {
"title": "The Hour Grows Late",
"culture": "isengard",
"cost": 1,
"type": "event",
"keyword": [
"maneuver",
"spell"
],
"condition": {
"type": "canSpot",
"filter": "name(Saruman)"
},
"effects": {
"type": "event",
"cost": {
"type": "spot",
"filter": "choose(exhausted,companion)",
"memorize": "exhaustedCompanion"
},
"effect": {
"type": "addThreats",
"amount": {
"type": "forEachWound",
"filter": "memory(exhaustedCompanion)"
}
}
}
},
"40_142": {
"title": "*Throne of Orthanc",
"culture": "isengard",
"cost": 2,
"type": "artifact",
"keyword": "support area",
"effects": [
{
"type": "modifier",
"modifier": {
"type": "modifyCost",
"filter": "culture(isengard),event",
"amount": {
"type": "multiply",
"multiplier": -1,
"source": {
"type": "countStacked",
"on": "self",
"filter": "minion"
}
}
}
},
{
"type": "activated",
"phase": "regroup",
"effect": {
"type": "stackCards",
"filter": "choose(name(Saruman),not(exhausted))",
"where": "self"
}
},
{
"type": "activated",
"phase": "shadow",
"cost": {
"type": "removeThreats"
},
"effect": {
"type": "playCardFromStacked",
"filter": "choose(name(Saruman))",
"on": "self"
}
}
]
},
"40_314": {
"title": "Brute Force",
"culture": "isengard",

View File

@@ -1,41 +0,0 @@
package com.gempukku.lotro.cards.set40.isengard;
import com.gempukku.lotro.common.Culture;
import com.gempukku.lotro.common.Keyword;
import com.gempukku.lotro.common.Race;
import com.gempukku.lotro.game.PhysicalCard;
import com.gempukku.lotro.game.state.LotroGame;
import com.gempukku.lotro.logic.cardtype.AbstractMinion;
import com.gempukku.lotro.logic.modifiers.KeywordModifier;
import com.gempukku.lotro.logic.modifiers.Modifier;
import com.gempukku.lotro.logic.modifiers.condition.LocationCondition;
import java.util.Collections;
import java.util.List;
/**
* Title: Relentless Uruk
* Set: Second Edition
* Side: Shadow
* Culture: Isengard
* Twilight Cost: 4
* Type: Minion - Uruk-hai
* Strength: 9
* Vitality: 2
* Home: 5
* Card Number: 1C133
* Game Text: Damage +1. While at a battleground, this minion is fierce.
*/
public class Card40_133 extends AbstractMinion {
public Card40_133() {
super(4, 9, 2, 5, Race.URUK_HAI, Culture.ISENGARD, "Relentless Uruk");
addKeyword(Keyword.DAMAGE, 1);
}
@Override
public List<? extends Modifier> getInPlayModifiers(LotroGame game, PhysicalCard self) {
KeywordModifier modifier = new KeywordModifier(self, self,
new LocationCondition(Keyword.BATTLEGROUND), Keyword.FIERCE, 1);
return Collections.singletonList(modifier);
}
}

View File

@@ -1,69 +0,0 @@
package com.gempukku.lotro.cards.set40.isengard;
import com.gempukku.lotro.common.Culture;
import com.gempukku.lotro.common.Keyword;
import com.gempukku.lotro.common.Phase;
import com.gempukku.lotro.common.Race;
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.ActivateCardAction;
import com.gempukku.lotro.logic.actions.OptionalTriggerAction;
import com.gempukku.lotro.logic.cardtype.AbstractMinion;
import com.gempukku.lotro.logic.effects.AddTwilightEffect;
import com.gempukku.lotro.logic.effects.SelfExertEffect;
import com.gempukku.lotro.logic.effects.choose.ChooseAndPlayCardFromDiscardEffect;
import com.gempukku.lotro.logic.modifiers.evaluator.ForEachThreatEvaluator;
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;
/**
* Title: *Saruman, Mind of Metal
* Set: Second Edition
* Side: Shadow
* Culture: Isengard
* Twilight Cost: 4
* Type: Minion - Wizard
* Strength: 8
* Vitality: 4
* Home: 4
* Card Number: 1U134
* Game Text: Cunning. At the beginning of the maneuver phase, you may add (1) for each threat.
* Shadow: Exert Saruman to play Saruman's Staff from your discard pile.
*/
public class Card40_134 extends AbstractMinion {
public Card40_134() {
super(4, 8, 4, 4, Race.WIZARD, Culture.ISENGARD, "Saruman", "Mind of Metal", true);
addKeyword(Keyword.CUNNING);
}
@Override
public List<OptionalTriggerAction> getOptionalAfterTriggers(String playerId, LotroGame game, EffectResult effectResult, PhysicalCard self) {
if (TriggerConditions.startOfPhase(game, effectResult, Phase.MANEUVER)) {
OptionalTriggerAction action = new OptionalTriggerAction(self);
action.appendEffect(
new AddTwilightEffect(self, new ForEachThreatEvaluator()));
return Collections.singletonList(action);
}
return null;
}
@Override
public List<? extends ActivateCardAction> getPhaseActionsInPlay(String playerId, LotroGame game, PhysicalCard self) {
if (PlayConditions.canUseShadowCardDuringPhase(game, Phase.SHADOW, self, 0)
&& PlayConditions.canSelfExert(self, game)
&& PlayConditions.canPlayFromDiscard(playerId, game, Filters.name("Saruman's Staff"))) {
ActivateCardAction action = new ActivateCardAction(self);
action.appendCost(
new SelfExertEffect(action, self));
action.appendEffect(
new ChooseAndPlayCardFromDiscardEffect(playerId, game, Filters.name("Saruman's Staff")));
return Collections.singletonList(action);
}
return null;
}
}

View File

@@ -1,65 +0,0 @@
package com.gempukku.lotro.cards.set40.isengard;
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.GameUtils;
import com.gempukku.lotro.logic.actions.ActivateCardAction;
import com.gempukku.lotro.logic.actions.CostToEffectAction;
import com.gempukku.lotro.logic.cardtype.AbstractMinion;
import com.gempukku.lotro.logic.effects.AddThreatsEffect;
import com.gempukku.lotro.logic.effects.ChooseAndWoundCharactersEffect;
import com.gempukku.lotro.logic.effects.PreventableEffect;
import com.gempukku.lotro.logic.effects.SelfExertEffect;
import com.gempukku.lotro.logic.effects.choose.ChooseAndDiscardStackedCardsEffect;
import com.gempukku.lotro.logic.timing.Effect;
import com.gempukku.lotro.logic.timing.PlayConditions;
import java.util.Collections;
import java.util.List;
/**
* Title: *Saruman, The White Wizard
* Set: Second Edition
* Side: Shadow
* Culture: Isengard
* Twilight Cost: 4
* Type: Minion - Wizard
* Strength: 8
* Vitality: 4
* Home: 4
* Card Number: 1R135
* Game Text: Skirmish: Exert Saruman and discard a spell stacked on an [ISENGARD] artifact to wound a companion
* skirmishing Saruman. The Free Peoples player may add a threat to prevent this.
*/
public class Card40_135 extends AbstractMinion {
public Card40_135() {
super(4, 8, 4, 4, Race.WIZARD, Culture.ISENGARD, "Saruman", "The White Wizard", true);
}
@Override
public List<? extends ActivateCardAction> getPhaseActionsInPlay(String playerId, LotroGame game, final PhysicalCard self) {
if (PlayConditions.canUseShadowCardDuringPhase(game, Phase.SKIRMISH, self, 0)
&& PlayConditions.canExert(self, game, Filters.saruman)
&& PlayConditions.canDiscardFromStacked(self, game, playerId, 1, Filters.and(Culture.ISENGARD, CardType.ARTIFACT), Keyword.SPELL)) {
ActivateCardAction action = new ActivateCardAction(self);
action.appendCost(
new SelfExertEffect(action, self));
action.appendCost(
new ChooseAndDiscardStackedCardsEffect(action, playerId, 1, 1, Filters.and(Culture.ISENGARD, CardType.ARTIFACT),
Keyword.SPELL));
action.appendEffect(
new PreventableEffect(action,
new ChooseAndWoundCharactersEffect(action, playerId, 1, 1, CardType.COMPANION, Filters.inSkirmishAgainst(self)),
GameUtils.getFreePeoplePlayer(game), new PreventableEffect.PreventionCost() {
@Override
public Effect createPreventionCostForPlayer(CostToEffectAction subAction, String playerId) {
return new AddThreatsEffect(playerId, self, 1);
}
}));
return Collections.singletonList(action);
}
return null;
}
}

View File

@@ -1,51 +0,0 @@
package com.gempukku.lotro.cards.set40.isengard;
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.ActivateCardAction;
import com.gempukku.lotro.logic.cardtype.AbstractPermanent;
import com.gempukku.lotro.logic.effects.SelfDiscardEffect;
import com.gempukku.lotro.logic.effects.choose.ChooseAndAddUntilEOPStrengthBonusEffect;
import com.gempukku.lotro.logic.modifiers.Modifier;
import com.gempukku.lotro.logic.modifiers.TwilightCostModifier;
import com.gempukku.lotro.logic.timing.PlayConditions;
import java.util.Collections;
import java.util.List;
/**
* Title: Saruman's Ambition
* Set: Second Edition
* Side: Shadow
* Culture: Isengard
* Twilight Cost: 0
* Type: Condition - Support Area
* Card Number: 1C136
* Game Text: The twilight cost of each [ISENGARD] event is -1. Skirmish: Discard this condition to make an Uruk-hai strength +2.
*/
public class Card40_136 extends AbstractPermanent {
public Card40_136() {
super(Side.SHADOW, 0, CardType.CONDITION, Culture.ISENGARD, "Saruman's Ambition");
}
@Override
public List<? extends ActivateCardAction> getPhaseActionsInPlay(String playerId, LotroGame game, final PhysicalCard self) {
if (PlayConditions.canUseShadowCardDuringPhase(game, Phase.SKIRMISH, self, 0)) {
final ActivateCardAction action = new ActivateCardAction(self);
action.appendCost(new SelfDiscardEffect(self));
action.appendEffect(
new ChooseAndAddUntilEOPStrengthBonusEffect(action, self, playerId, 2, Race.URUK_HAI));
return Collections.singletonList(action);
}
return null;
}
@Override
public List<? extends Modifier> getInPlayModifiers(LotroGame game, PhysicalCard self) {
return Collections.singletonList(new TwilightCostModifier(self, Filters.and(Culture.ISENGARD, CardType.EVENT, Filters.owner(self.getOwner())), -1));
}
}

View File

@@ -1,77 +0,0 @@
package com.gempukku.lotro.cards.set40.isengard;
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.ActivateCardAction;
import com.gempukku.lotro.logic.cardtype.AbstractAttachable;
import com.gempukku.lotro.logic.effects.PreventCardEffect;
import com.gempukku.lotro.logic.effects.RemoveThreatsEffect;
import com.gempukku.lotro.logic.effects.WoundCharactersEffect;
import com.gempukku.lotro.logic.modifiers.KeywordModifier;
import com.gempukku.lotro.logic.modifiers.Modifier;
import com.gempukku.lotro.logic.modifiers.RemoveKeywordModifier;
import com.gempukku.lotro.logic.timing.Effect;
import com.gempukku.lotro.logic.timing.PlayConditions;
import com.gempukku.lotro.logic.timing.TriggerConditions;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Title: *Saruman's Staff, Instrument of War
* Set: Second Edition
* Side: Shadow
* Culture: Isengard
* Twilight Cost: 2
* Type: Artifact - Staff
* Strength: +2
* Vitality: +1
* Card Number: 1R137
* Game Text: Bearer must be Saruman. He loses cunning and is fierce.
* Response: If Saruman is about to take a wound, remove a threat to prevent that wound.
*/
public class Card40_137 extends AbstractAttachable {
public Card40_137() {
super(Side.SHADOW, CardType.ARTIFACT, 2, Culture.ISENGARD, PossessionClass.STAFF, "Saruman's Staff", "Instrument of War", true);
}
@Override
public Filterable getValidTargetFilter(String playerId, LotroGame game, PhysicalCard self) {
return Filters.saruman;
}
@Override
public List<? extends Modifier> getInPlayModifiers(LotroGame game, PhysicalCard self) {
RemoveKeywordModifier losesCunning = new RemoveKeywordModifier(self, Filters.hasAttached(self), Keyword.CUNNING);
KeywordModifier fierce = new KeywordModifier(self, Filters.hasAttached(self), Keyword.FIERCE);
return Arrays.asList(losesCunning, fierce);
}
@Override
public List<? extends ActivateCardAction> getOptionalInPlayBeforeActions(String playerId, LotroGame game, Effect effect, PhysicalCard self) {
if (TriggerConditions.isGettingWounded(effect, game, Filters.hasAttached(self))
&& PlayConditions.canRemoveThreat(game, self, 1)) {
WoundCharactersEffect woundEffect = (WoundCharactersEffect) effect;
ActivateCardAction action = new ActivateCardAction(self);
action.appendCost(
new RemoveThreatsEffect(self, 1));
action.appendEffect(
new PreventCardEffect(woundEffect, self.getAttachedTo()));
return Collections.singletonList(action);
}
return null;
}
@Override
public int getStrength() {
return 2;
}
@Override
public int getVitality() {
return 1;
}
}

View File

@@ -1,65 +0,0 @@
package com.gempukku.lotro.cards.set40.isengard;
import com.gempukku.lotro.common.Culture;
import com.gempukku.lotro.common.Phase;
import com.gempukku.lotro.common.Side;
import com.gempukku.lotro.filters.Filters;
import com.gempukku.lotro.game.PhysicalCard;
import com.gempukku.lotro.game.state.LotroGame;
import com.gempukku.lotro.logic.GameUtils;
import com.gempukku.lotro.logic.actions.PlayEventAction;
import com.gempukku.lotro.logic.cardtype.AbstractEvent;
import com.gempukku.lotro.logic.effects.AddThreatsEffect;
import com.gempukku.lotro.logic.effects.ChoiceEffect;
import com.gempukku.lotro.logic.effects.choose.ChooseAndPlayCardFromDeckEffect;
import com.gempukku.lotro.logic.effects.choose.ChooseAndPlayCardFromDiscardEffect;
import com.gempukku.lotro.logic.modifiers.evaluator.Evaluator;
import com.gempukku.lotro.logic.timing.Effect;
import com.gempukku.lotro.logic.timing.PlayConditions;
import java.util.ArrayList;
import java.util.List;
/**
* Title: Seeking My Counsel
* Set: Second Edition
* Side: Shadow
* Culture: Isengard
* Twilight Cost: 2
* Type: Event - Shadow
* Card Number: 1R138
* Game Text: Play Saruman from your draw deck or discard pile to add X threats, where X is the fellowship's current region number.
*/
public class Card40_138 extends AbstractEvent {
public Card40_138() {
super(Side.SHADOW, 2, Culture.ISENGARD, "Seeking My Counsel", Phase.SHADOW);
}
@Override
public boolean checkPlayRequirements(LotroGame game, PhysicalCard self) {
return (PlayConditions.canPlayFromDeck(self.getOwner(), game, Filters.saruman)
|| PlayConditions.canPlayFromDiscard(self.getOwner(), game, Filters.saruman));
}
@Override
public PlayEventAction getPlayEventCardAction(String playerId, LotroGame game, PhysicalCard self) {
PlayEventAction action = new PlayEventAction(self);
List<Effect> possibleCosts = new ArrayList<Effect>(2);
possibleCosts.add(
new ChooseAndPlayCardFromDeckEffect(playerId, Filters.saruman));
possibleCosts.add(
new ChooseAndPlayCardFromDiscardEffect(playerId, game, Filters.saruman));
action.appendCost(
new ChoiceEffect(
action, playerId, possibleCosts));
action.appendEffect(
new AddThreatsEffect(playerId, self,
new Evaluator() {
@Override
public int evaluateExpression(LotroGame game, PhysicalCard cardAffected) {
return GameUtils.getRegion(game);
}
}));
return action;
}
}

View File

@@ -1,52 +0,0 @@
package com.gempukku.lotro.cards.set40.isengard;
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.cardtype.AbstractAttachable;
import com.gempukku.lotro.logic.modifiers.CantTakeWoundsModifier;
import com.gempukku.lotro.logic.modifiers.Modifier;
import com.gempukku.lotro.logic.modifiers.condition.AndCondition;
import com.gempukku.lotro.logic.modifiers.condition.LocationCondition;
import com.gempukku.lotro.logic.modifiers.condition.NotCondition;
import com.gempukku.lotro.logic.modifiers.condition.PhaseCondition;
import java.util.Collections;
import java.util.List;
/**
* Title: Sword of Orthanc
* Set: Second Edition
* Side: Shadow
* Culture: Isengard
* Twilight Cost: 1
* Type: Possession - Hand Weapon
* Strength: +2
* Card Number: 1C139
* Game Text: Bearer must be an Uruk-hai. While at a battleground, bearer may only take wounds during skirmishes.
*/
public class Card40_139 extends AbstractAttachable {
public Card40_139() {
super(Side.SHADOW, CardType.POSSESSION, 1, Culture.ISENGARD, PossessionClass.HAND_WEAPON, "Sword of Orthanc");
}
@Override
public Filterable getValidTargetFilter(String playerId, LotroGame game, PhysicalCard self) {
return Race.URUK_HAI;
}
@Override
public int getStrength() {
return 2;
}
@Override
public List<? extends Modifier> getInPlayModifiers(LotroGame game, PhysicalCard self) {
CantTakeWoundsModifier modifier = new CantTakeWoundsModifier(self,
new AndCondition(
new NotCondition(new PhaseCondition(Phase.SKIRMISH)),
new LocationCondition(Keyword.BATTLEGROUND)), Filters.hasAttached(self));
return Collections.singletonList(modifier);
}
}

View File

@@ -1,74 +0,0 @@
package com.gempukku.lotro.cards.set40.isengard;
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.ActivateCardAction;
import com.gempukku.lotro.logic.cardtype.AbstractAttachable;
import com.gempukku.lotro.logic.effects.SelfDiscardEffect;
import com.gempukku.lotro.logic.effects.choose.ChooseAndPlayCardFromDiscardEffect;
import com.gempukku.lotro.logic.modifiers.AbstractExtraPlayCostModifier;
import com.gempukku.lotro.logic.modifiers.KeywordModifier;
import com.gempukku.lotro.logic.modifiers.Modifier;
import com.gempukku.lotro.logic.modifiers.condition.LocationCondition;
import com.gempukku.lotro.logic.modifiers.cost.ExertExtraPlayCostModifier;
import com.gempukku.lotro.logic.timing.PlayConditions;
import java.util.Collections;
import java.util.List;
/**
* Title: *Ten Thousand Strong
* Set: Second Edition
* Side: Shadow
* Culture: Isengard
* Twilight Cost: 0
* Type: Condition - Site
* Card Number: 1R140
* Game Text: To play, exert an Uruk-hai. Uruk-hai are fierce while at this site.
* Shadow: Spot an Uruk-hai and discard this condition to play an Uruk-hai from your discard pile.
*/
public class Card40_140 extends AbstractAttachable {
public Card40_140() {
super(Side.SHADOW, CardType.CONDITION, 0, Culture.ISENGARD, null, "Ten Thousand Strong", null, true);
}
@Override
public boolean checkPlayRequirements(LotroGame game, PhysicalCard self) {
return PlayConditions.canExert(self, game, Race.URUK_HAI);
}
@Override
public Filterable getValidTargetFilter(String playerId, LotroGame game, PhysicalCard self) {
return CardType.SITE;
}
@Override
public List<? extends AbstractExtraPlayCostModifier> getExtraCostToPlay(LotroGame game, PhysicalCard self) {
return Collections.singletonList(
new ExertExtraPlayCostModifier(self, self, null, Race.URUK_HAI));
}
@Override
public List<? extends Modifier> getInPlayModifiers(LotroGame game, PhysicalCard self) {
KeywordModifier modifier = new KeywordModifier(self, Race.URUK_HAI, new LocationCondition(Filters.hasAttached(self)), Keyword.FIERCE, 1);
return Collections.singletonList(modifier);
}
@Override
public List<? extends ActivateCardAction> getPhaseActionsInPlay(String playerId, LotroGame game, PhysicalCard self) {
if (PlayConditions.canUseShadowCardDuringPhase(game, Phase.SHADOW, self, 0)
&& PlayConditions.canSpot(game, Race.URUK_HAI)
&& PlayConditions.canSelfDiscard(self, game)
&& PlayConditions.canPlayFromDiscard(playerId, game, Race.URUK_HAI)) {
ActivateCardAction action = new ActivateCardAction(self);
action.appendCost(
new SelfDiscardEffect(self));
action.appendEffect(
new ChooseAndPlayCardFromDiscardEffect(playerId, game, Race.URUK_HAI));
return Collections.singletonList(action);
}
return null;
}
}

View File

@@ -1,49 +0,0 @@
package com.gempukku.lotro.cards.set40.isengard;
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.effects.AddThreatsEffect;
import com.gempukku.lotro.logic.effects.ChooseActiveCardEffect;
import com.gempukku.lotro.logic.timing.PlayConditions;
/**
* Title: The Hour Grows Late
* Set: Second Edition
* Side: Shadow
* Culture: Isengard
* Twilight Cost: 1
* Type: Event - Maneuver
* Card Number: 1U141
* Game Text: Spell. Spot Saruman and an exhausted companion to add a threat for each wound on that companion.
*/
public class Card40_141 extends AbstractEvent {
public Card40_141() {
super(Side.SHADOW, 1, Culture.ISENGARD, "The Hour Grows Late", Phase.MANEUVER);
addKeyword(Keyword.SPELL);
}
@Override
public boolean checkPlayRequirements(LotroGame game, PhysicalCard self) {
return PlayConditions.canSpot(game, Filters.saruman)
&& PlayConditions.canSpot(game, CardType.COMPANION, Filters.exhausted);
}
@Override
public PlayEventAction getPlayEventCardAction(final String playerId, LotroGame game, final PhysicalCard self) {
final PlayEventAction action = new PlayEventAction(self);
action.appendEffect(
new ChooseActiveCardEffect(self, playerId, "Choose exhausted companion", CardType.COMPANION, Filters.exhausted) {
@Override
protected void cardSelected(LotroGame game, PhysicalCard card) {
final int wounds = game.getGameState().getWounds(card);
action.appendEffect(
new AddThreatsEffect(playerId, self, wounds));
}
});
return action;
}
}

View File

@@ -1,69 +0,0 @@
package com.gempukku.lotro.cards.set40.isengard;
import com.gempukku.lotro.common.CardType;
import com.gempukku.lotro.common.Culture;
import com.gempukku.lotro.common.Phase;
import com.gempukku.lotro.common.Side;
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.ActivateCardAction;
import com.gempukku.lotro.logic.cardtype.AbstractPermanent;
import com.gempukku.lotro.logic.effects.RemoveThreatsEffect;
import com.gempukku.lotro.logic.effects.choose.ChooseAndPlayCardFromStackedEffect;
import com.gempukku.lotro.logic.effects.choose.ChooseAndStackCardFromPlayEffect;
import com.gempukku.lotro.logic.modifiers.Modifier;
import com.gempukku.lotro.logic.modifiers.TwilightCostModifier;
import com.gempukku.lotro.logic.modifiers.evaluator.CountStackedEvaluator;
import com.gempukku.lotro.logic.modifiers.evaluator.NegativeEvaluator;
import com.gempukku.lotro.logic.timing.PlayConditions;
import java.util.Collections;
import java.util.List;
/**
* Title: *Throne of Orthanc
* Set: Second Edition
* Side: Shadow
* Culture: Isengard
* Twilight Cost: 2
* Type: Artifact - Support Area
* Card Number: 1R142
* Game Text: The twilight cost of each [ISENGARD] event is -1 for each minion stacked on this artifact.
* Regroup: If Saruman is not exhausted, stack him on this artifact.
* Shadow: Remove a threat to play Saruman stacked here as if from hand.
*/
public class Card40_142 extends AbstractPermanent {
public Card40_142() {
super(Side.SHADOW, 2, CardType.ARTIFACT, Culture.ISENGARD, "Throne of Orthanc", null, true);
}
@Override
public List<? extends Modifier> getInPlayModifiers(LotroGame game, PhysicalCard self) {
TwilightCostModifier modifier = new TwilightCostModifier(self, Filters.and(Culture.ISENGARD, CardType.EVENT), null,
new NegativeEvaluator(new CountStackedEvaluator(self, CardType.MINION)));
return Collections.singletonList(modifier);
}
@Override
public List<? extends ActivateCardAction> getPhaseActionsInPlay(String playerId, LotroGame game, PhysicalCard self) {
if (PlayConditions.canUseShadowCardDuringPhase(game, Phase.SHADOW, self, 0)
&& PlayConditions.canRemoveThreat(game, self, 1)
&& PlayConditions.canPlayFromStacked(playerId, game, self, Filters.saruman)) {
ActivateCardAction action = new ActivateCardAction(self);
action.appendCost(
new RemoveThreatsEffect(self, 1));
action.appendEffect(
new ChooseAndPlayCardFromStackedEffect(playerId, self, Filters.saruman));
return Collections.singletonList(action);
}
if (PlayConditions.canUseShadowCardDuringPhase(game, Phase.REGROUP, self, 1)
&& PlayConditions.canSpot(game, Filters.saruman, Filters.not(Filters.exhausted))) {
ActivateCardAction action = new ActivateCardAction(self);
action.appendEffect(
new ChooseAndStackCardFromPlayEffect(action, playerId, self, Filters.saruman, Filters.not(Filters.exhausted)));
return Collections.singletonList(action);
}
return null;
}
}

View File

@@ -51,6 +51,7 @@ public class EffectAppenderFactory {
effectAppenderProducers.put("play", new PlayCardFromHand());
effectAppenderProducers.put("playcardfromdiscard", new PlayCardFromDiscard());
effectAppenderProducers.put("playcardfromdrawdeck", new PlayCardFromDrawDeck());
effectAppenderProducers.put("playcardfromstacked", new PlayCardFromStacked());
effectAppenderProducers.put("reducearcherytotal", new ReduceArcheryTotal());
effectAppenderProducers.put("revealtopcardsofdrawdeck", new RevealTopCardsOfDrawDeck());
effectAppenderProducers.put("optional", new Optional());

View File

@@ -0,0 +1,61 @@
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.FilterableSource;
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.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.PlayUtils;
import com.gempukku.lotro.logic.actions.CostToEffectAction;
import com.gempukku.lotro.logic.effects.StackActionEffect;
import com.gempukku.lotro.logic.modifiers.evaluator.ConstantEvaluator;
import com.gempukku.lotro.logic.timing.Effect;
import com.gempukku.lotro.logic.timing.UnrespondableEffect;
import org.json.simple.JSONObject;
import java.util.Collection;
public class PlayCardFromStacked implements EffectAppenderProducer {
@Override
public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
FieldUtils.validateAllowedFields(effectObject, "filter", "on");
final String filter = FieldUtils.getString(effectObject.get("filter"), "filter");
final String onFilter = FieldUtils.getString(effectObject.get("on"), "on");
final FilterableSource onFilterableSource = (onFilter != null) ? environment.getFilterFactory().generateFilter(onFilter, environment) : null;
MultiEffectAppender result = new MultiEffectAppender();
result.setPlayabilityCheckedForEffect(true);
result.addEffectAppender(
CardResolver.resolveStackedCards(filter, actionContext -> Filters.playable(actionContext.getGame()),
new ConstantEvaluator(1), onFilterableSource, "_temp", "you", "Choose card to play", environment));
result.addEffectAppender(
new DelayedAppender() {
@Override
protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
final Collection<? extends PhysicalCard> cardsToPlay = actionContext.getCardsFromMemory("_temp");
if (cardsToPlay.size() == 1) {
final CostToEffectAction playCardAction = PlayUtils.getPlayCardAction(actionContext.getGame(), cardsToPlay.iterator().next(), 0, Filters.any, false);
return new StackActionEffect(playCardAction);
} else {
return new UnrespondableEffect() {
@Override
protected void doPlayEffect(LotroGame game) {
// do nothing
}
};
}
}
});
return result;
}
}

View File

@@ -23,8 +23,15 @@ import java.util.LinkedList;
import java.util.List;
public class CardResolver {
public static EffectAppender resolveStackedCards(String type, ValueSource countSource, FilterableSource stackedOn,
String memory, String choicePlayer, String choiceText, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
return resolveStackedCards(type, null, countSource, stackedOn, memory, choicePlayer, choiceText, environment);
}
public static EffectAppender resolveStackedCards(String type, FilterableSource additionalFilter, ValueSource countSource, FilterableSource stackedOn,
String memory, String choicePlayer, String choiceText, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
if (type.startsWith("memory(") && type.endsWith(")")) {
String sourceMemory = type.substring(type.indexOf("(") + 1, type.lastIndexOf(")"));
return new DelayedAppender() {
@@ -54,12 +61,16 @@ public class CardResolver {
final Filterable filterable = filterableSource.getFilterable(actionContext);
final Filterable stackedOnFilter = stackedOn.getFilterable(actionContext);
Filterable additionalFilterable = Filters.any;
if (additionalFilter != null)
additionalFilterable = additionalFilter.getFilterable(actionContext);
List<PhysicalCard> choice = new LinkedList<>();
final LotroGame game = actionContext.getGame();
for (PhysicalCard stackedOn : Filters.filterActive(game, stackedOnFilter)) {
final List<PhysicalCard> stackedCards = game.getGameState().getStackedCards(stackedOn);
choice.addAll(Filters.filter(stackedCards, game, filterable));
choice.addAll(Filters.filter(stackedCards, game, filterable, additionalFilterable));
}
return choice.size() >= min;
@@ -73,7 +84,11 @@ public class CardResolver {
int min = countSource.getMinimum(actionContext);
int max = countSource.getMaximum(actionContext);
return new ChooseStackedCardsEffect(action, choicePlayerId, min, max, stackedOnFilter, filterable) {
Filterable additionalFilterable = Filters.any;
if (additionalFilter != null)
additionalFilterable = additionalFilter.getFilterable(actionContext);
return new ChooseStackedCardsEffect(action, choicePlayerId, min, max, stackedOnFilter, Filters.and(filterable, additionalFilterable)) {
@Override
protected void cardsChosen(LotroGame game, Collection<PhysicalCard> stackedCards) {
actionContext.setCardMemory(memory, stackedCards);

View File

@@ -7,6 +7,7 @@ import com.gempukku.lotro.common.Keyword;
import com.gempukku.lotro.filters.Filters;
import com.gempukku.lotro.game.PhysicalCard;
import com.gempukku.lotro.game.state.LotroGame;
import com.gempukku.lotro.logic.GameUtils;
import com.gempukku.lotro.logic.modifiers.evaluator.*;
import org.json.simple.JSONObject;
@@ -60,12 +61,16 @@ public class ValueResolver {
}
return trueValue;
};
} else if (type.equalsIgnoreCase("forRegionNumber")) {
return (actionContext) -> (Evaluator) (game, cardAffected) -> GameUtils.getRegion(actionContext.getGame());
} else if (type.equalsIgnoreCase("forEachInMemory")) {
final String memory = FieldUtils.getString(object.get("memory"), "memory");
return (actionContext) -> {
final int count = actionContext.getCardsFromMemory(memory).size();
return new ConstantEvaluator(count);
};
} else if (type.equalsIgnoreCase("forEachThreat")) {
return actionContext -> new ForEachThreatEvaluator();
} else if (type.equalsIgnoreCase("forEachWound")) {
final String filter = FieldUtils.getString(object.get("filter"), "filter");
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment);
@@ -90,12 +95,14 @@ public class ValueResolver {
return (actionContext) -> new LimitEvaluator(valueSource.getEvaluator(actionContext), limit);
} else if (type.equalsIgnoreCase("countStacked")) {
final String on = FieldUtils.getString(object.get("on"), "on");
final String filter = FieldUtils.getString(object.get("filter"), "filter", "any");
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment);
final FilterableSource onFilter = environment.getFilterFactory().generateFilter(on, environment);
return (actionContext) -> {
final Filterable on1 = onFilter.getFilterable(actionContext);
return new CountStackedEvaluator(on1, Filters.any);
return new CountStackedEvaluator(on1, filterableSource.getFilterable(actionContext));
};
} else if (type.equalsIgnoreCase("forEachYouCanSpot")) {
final String filter = FieldUtils.getString(object.get("filter"), "filter");

View File

@@ -36,6 +36,7 @@ public class FilterFactory {
simpleFilters.put("weapon", (actionContext) -> Filters.weapon);
simpleFilters.put("wounded", (actionContext) -> Filters.wounded);
simpleFilters.put("unwounded", (actionContext) -> Filters.unwounded);
simpleFilters.put("exhausted", (actionContext) -> Filters.exhausted);
simpleFilters.put("inskirmish", (actionContext) -> Filters.inSkirmish);
simpleFilters.put("inplay", (actionContext) -> Filters.inPlay);
simpleFilters.put("notassignedtoskirmish",

View File

@@ -0,0 +1,25 @@
package com.gempukku.lotro.cards.build.field.effect.modifier;
import com.gempukku.lotro.cards.build.*;
import com.gempukku.lotro.cards.build.field.FieldUtils;
import com.gempukku.lotro.logic.modifiers.CantTakeWoundsModifier;
import org.json.simple.JSONObject;
public class CantTakeWounds implements ModifierSourceProducer {
@Override
public ModifierSource getModifierSource(JSONObject object, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
FieldUtils.validateAllowedFields(object, "filter", "condition");
final JSONObject[] conditionArray = FieldUtils.getObjectArray(object.get("condition"), "condition");
final String filter = FieldUtils.getString(object.get("filter"), "filter", "self");
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment);
final Requirement[] requirements = environment.getRequirementFactory().getRequirements(conditionArray, environment);
return (actionContext) -> {
return new CantTakeWoundsModifier(actionContext.getSource(),
new RequirementCondition(requirements, actionContext),
filterableSource.getFilterable(actionContext));
};
}
}

View File

@@ -14,10 +14,12 @@ public class ModifierSourceFactory {
public ModifierSourceFactory() {
modifierProducers.put("addkeyword", new AddKeyword());
modifierProducers.put("removekeyword", new RemoveKeyword());
modifierProducers.put("archerytotal", new ArcheryTotal());
modifierProducers.put("cantbeexerted", new CantBeExerted());
modifierProducers.put("cantbeoverwhelmedmultiplier", new CantBeOverwhelmedMultiplier());
modifierProducers.put("canttakemorewoundsthan", new CantTakeMoreWoundsThan());
modifierProducers.put("canttakewounds", new CantTakeWounds());
modifierProducers.put("modifycost", new ModifyCost());
modifierProducers.put("modifyroamingpenalty", new ModifyRoamingPenalty());
modifierProducers.put("modifystrength", new ModifyStrength());

View File

@@ -0,0 +1,32 @@
package com.gempukku.lotro.cards.build.field.effect.modifier;
import com.gempukku.lotro.cards.build.*;
import com.gempukku.lotro.cards.build.field.FieldUtils;
import com.gempukku.lotro.common.Keyword;
import com.gempukku.lotro.logic.modifiers.Modifier;
import com.gempukku.lotro.logic.modifiers.RemoveKeywordModifier;
import org.json.simple.JSONObject;
public class RemoveKeyword implements ModifierSourceProducer {
@Override
public ModifierSource getModifierSource(JSONObject object, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
FieldUtils.validateAllowedFields(object, "filter", "condition", "keyword");
final JSONObject[] conditionArray = FieldUtils.getObjectArray(object.get("condition"), "condition");
final String filter = FieldUtils.getString(object.get("filter"), "filter", "self");
Keyword keyword = FieldUtils.getEnum(Keyword.class, object.get("keyword"), "keyword");
final FilterableSource filterableSource = environment.getFilterFactory().generateFilter(filter, environment);
final Requirement[] requirements = environment.getRequirementFactory().getRequirements(conditionArray, environment);
return new ModifierSource() {
@Override
public Modifier getModifier(ActionContext actionContext) {
return new RemoveKeywordModifier(actionContext.getSource(),
filterableSource.getFilterable(actionContext),
new RequirementCondition(requirements, actionContext), keyword);
}
};
}
}

View File

@@ -0,0 +1,20 @@
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 com.gempukku.lotro.cards.build.field.FieldUtils;
import org.json.simple.JSONObject;
public class NotRequirementProducer implements RequirementProducer {
@Override
public Requirement getPlayRequirement(JSONObject object, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
FieldUtils.validateAllowedFields(object, "condition");
final Requirement condition = environment.getRequirementFactory().getRequirement((JSONObject) object.get("condition"), environment);
return (actionContext) -> {
return !condition.accepts(actionContext);
};
}
}

View File

@@ -13,6 +13,7 @@ public class RequirementFactory {
private Map<String, RequirementProducer> requirementProducers = new HashMap<>();
public RequirementFactory() {
requirementProducers.put("not", new NotRequirementProducer());
requirementProducers.put("canspot", new CanSpot());
requirementProducers.put("canspotburdens", new CanSpotBurdens());
requirementProducers.put("controlssite", new ControlsSite());