V2 Moria + Rohan

- Addied triggers for keying to adding and removing culture tokens
- Added player parameter to PlayCardFromDiscard; this could probably stand to go on the other PlayCardFromX effects as well
This commit is contained in:
Christian 'ketura' McCarty
2024-06-03 00:26:14 -05:00
parent 11b32a1543
commit c2be403bc6
18 changed files with 704 additions and 126 deletions

View File

@@ -30,17 +30,33 @@
Fierce
Damage+2
]
/*requires: {
}
effects: [
{
type: Trigger
trigger: {
type: TakesWound
filter: minion
}
effect: {
type: AddThreats
amount: 1
}
}
{
type: Trigger
optional: true
trigger: {
type: UsesSpecialAbility
phase: skirmish
filter: InSkirmishAgainst(self)
}
effect: {
type: Wound
select: choose(InSkirmishAgainst(self))
times: 1
}
}
]*/
]
gametext: Fierce. Damage +2.<br>Each time a minion takes a wound, add a threat.<br>Each time the Free Peoples player uses a skirmish special ability during a skirmish involving the Balrog, you may wound a companion it is skirmishing.
lore: ""
promotext: ""
@@ -74,17 +90,60 @@
twilight: 0
type: Condition
keywords: Support Area
/*requires: {
}
effects: [
{
type: Trigger
optional: true
trigger: {
type: Moves
}
cost: {
type: RevealCardsFromHand
select: choose(name(The Balrog))
}
effect: {
type: AddThreats
amount: 1
}
}
{
type: Activated
phase: Shadow
requires: [
{
type: CanPlayFromDiscard
filter: name(The Balrog)
}
{
type: CanSpotThreats
}
]
cost: [
{
type: ChooseANumber
text: Choose how many threats to remove
from: 1
to: {
type: ForEachThreat
}
memorize: removedThreats
}
{
type: RemoveThreats
amount: memory(removedThreats)
}
]
effect: {
type: PlayCardFromDiscard
select: choose(name(The Balrog))
discount: {
type: FromMemory
memory: removedThreats
multiplier: -1
}
}
}
]*/
]
gametext: Each time the fellowship moves, you may reveal The Balrog from your hand to add a threat.<br>Shadow: Remove X threats to play the Balrog from your discard pile, its twilight cost is -1 for each threat removed.
lore: "'Far, far below the deepest delving of the Dwarves, the world is gnawed by nameless things.'"
promotext: ""
@@ -118,22 +177,39 @@
twilight: 1
type: Event
timewords: Regroup
/*requires: {
}
*/
effects: {
type: event
cost: {
type: SendMessage
text: Placeholder effect for development.
},
effect: [
cost: [
{
type: SendMessage
text: Placeholder effect for development.
type: ChooseANumber
text: Choose how many {moria} minions to discard
from: 1
to: {
type: ForEachYouCanSpot
filter: culture(moria), minion
}
memorize: discardedMinions
}
{
type: Discard
select: choose(culture(Moria), minion)
count: memory(discardedMinions)
}
]
effect: {
type: Preventable
text: Would you like to exert {discardedMinions} companions to prevent adding {discardedMinions} threats?
player: freeps
cost: {
type: Exert
select: choose(companion)
count: memory(discardedMinions)
}
effect: {
type: AddThreats
amount: memory(discardedMinions)
}
}
}
gametext: Discard X [Moria] minions to add X threats. The Free Peoples player may exert X companions to prevent this.
lore: "'There was none to see, or perhaps in after ages songs would still be sung of the Battle of the Peak.'"
@@ -168,17 +244,23 @@
twilight: 0
type: Condition
keywords: Support Area
/*requires: {
}
effects: [
{
type: Trigger
trigger: {
type: WinsSkirmish
filter: unique, culture(moria), minion
}
cost: {
type: RemoveThreats
amount: 1
}
effect: {
type: Exert
select: choose(companion)
}
}
{
}
]*/
]
gametext: Each time a unique [moria] minion wins a skirmish, you may remove a threat to exert a companion.
lore: "'His fire was quenched, but now he was a thing of slime, stronger than a strangling snake.'"
promotext: ""
@@ -212,18 +294,59 @@
twilight: 1
type: Condition
keywords: Support Area
/*requires: {
}
effects: [
{
type: Trigger
trigger: {
type: WinsSkirmish
filter: unique, culture(moria), minion
}
effect: {
type: StackCardsFromPlay
select: choose(your,culture(moria),minion,inSkirmish)
where: self
}
}
{
type: activated
phase: shadow
requires: [
{
type: HasCardStacked
filter: playable, unique, culture(moria), minion
on: self
}
]
effect: [
{
type: ChooseCardsFromSingleStack
select: choose(playable, unique, culture(moria), minion)
count: 1
on: self
memorize: chosenMinion
text: Choose a minion to play.
}
{
type: MemorizeNumber
amount: {
type: ForEachStacked
filter: not(memory(chosenMinion))
on: self
multiplier: -1
}
memory: stackedDiscount
}
{
type: PlayCardFromStacked
select: memory(chosenMinion)
on: self
discount: memory(stackedDiscount)
assumePlayable: true
}
]
}
]*/
gametext: Each time a [moria] minion wins a skirmish, you may stack it here.<br>Shadow: Play a unique minion stacked here, it is twilight cost -1 for each card stacked here. Discard this condition.
]
gametext: Each time a [moria] minion wins a skirmish, you may stack it here.<br>Shadow: Play a unique minion stacked here, it is twilight cost -1 for each other card stacked here. Discard this condition.
lore: "'...I found myself suddenly faced by something that I have not met before.'"
promotext: ""
alts: {

View File

@@ -28,17 +28,19 @@
signet: Theoden
resistance: 6
keywords: Valiant
/*requires: {
}
effects: [
{
type: Modifier
modifier: {
type: ModifyStrength
filter: self
amount: {
type: ForEachYouCanSpot
filter: valiant, companion, AssignedToSkirmish(any)
}
}
}
{
}
]*/
]
gametext: Valiant.<br>Theoden is strength +1 for each valiant companion assigned to a skirmish.
lore: "His beard was laid like snow upon his knees; but his eyes still burned with a bright light, glinting as he gazed..."
promotext: ""
@@ -77,17 +79,28 @@
vitality: 3
signet: Gandalf
resistance: 6
/*requires: {
}
effects: [
{
type: Trigger
trigger: {
type: Played
filter: self
}
effect: {
type: RemoveCardsInDeadPileFromGame
count: 3
select: choose(culture(Rohan), companion, not(unique))
}
}
{
type: Modifier
modifier: {
type: AddKeyword
keyword: valiant
filter: exhausted, companion
}
}
]*/
]
gametext: When you play Erkenbrand, remove up to 3 non-unique [rohan] companions in the dead pile from the game. <br>Each exhausted companion gains <b>valiant</b>.
lore: "'He was a mighty man. In him lived again the valour of Helm the Hammerhand.'"
promotext: ""
@@ -124,17 +137,68 @@
race: Man
strength: 3
vitality: 3
/*requires: {
}
effects: [
{
type: ToPlay
requires: [
{
type: CanSpot
filter: name(Theoden)
}
{
type: CanSpot
filter: culture(Rohan), Man
count: 3
}
]
}
{
type: Activated
phase: Skirmish
requires: [
{
type: PerPhaseLimit
limit: 1
}
{
type: CanSpot
filter: InSkirmish, Hobbit, companion
}
]
cost: {
type: Spot
select: choose(InSkirmish, Hobbit, companion)
memorize: guardedHobbit
}
effect: [
{
type: ModifyStrength
select: memory(guardedHobbit)
amount: {
type: forEachStrength
filter: self
}
}
{
type: AddKeyword
keyword: valiant
select: memory(guardedHobbit)
}
{
type: AddTrigger
optional: false
trigger: {
type: SkirmishAboutToEnd
involving: memory(guardedHobbit)
}
effect: {
type: Wound
select: self
}
}
]
}
]*/
]
gametext: To play, spot Theoden (or 3 [rohan] Men).<br>Skirmish: If a Hobbit companion is skirmishing, add this ally's strength to that Hobbit and make that Hobbit gain <b>valiant</b> until the regroup phase (limit once per phase). At the end of that skirmish, wound this ally.
lore: ""
promotext: ""
@@ -168,17 +232,52 @@
twilight: 1
type: Condition
keywords: Support Area
/*requires: {
}
effects: [
{
type: Trigger
trigger: {
type: Killed
filter: minion
}
cost: {
type: Spot
filter: valiant, companion
count: 2
}
effect: {
type: AddCultureTokens
culture: rohan
select: self
}
}
{
type: Trigger
trigger: {
type: AddsCultureToken
on: self
}
requires: {
type: CanSpotCultureTokens
filter: self
amount: 3
}
cost: {
type: RemoveAllTokens
}
effect: [
{
type: PlayCardFromDiscard
select: choose(culture(rohan), or(condition, event))
}
{
type: PlayCardFromDiscard
player: shadow
optional: true
select: choose(minion)
}
]
}
]*/
]
gametext: Each time a minion is killed, spot 2 valiant companions to add a [rohan] token here.<br>Each time there are 3 [rohan] tokens here, remove all tokens here to play a [rohan] condition or event from your discard pile. The Shadow player may then play a minion from their discard pile.
lore: ""
promotext: ""
@@ -212,17 +311,53 @@
twilight: 1
type: Condition
keywords: Support Area
/*requires: {
}
effects: [
{
type: Trigger
trigger: [
{
type: Discarded
filter: culture(rohan), or(item, ally)
}
{
type: Killed
filter: culture(rohan), ally
}
]
effect: {
type: AddCultureTokens
culture: rohan
count: 1
select: self
}
}
{
type: Trigger
optional: true
trigger: {
type: Exerted
filter: minion
source: side(freeps)
memorize: hurtMinion
}
cost: [
{
type: RemoveCultureTokens
count: 1
select: self
}
{
type: Exert
select: choose(valiant, companion)
times: 1
}
]
effect: {
type: Wound
select: memory(hurtMinion)
}
}
]*/
]
gametext: Each time a [rohan] item or [rohan] ally is discarded or killed, add a [rohan] token here.<br>Each time a minion is exerted by a Free Peoples card, you may remove a [rohan] token here and exert a valiant companion to wound that minion.
lore: ""
promotext: ""
@@ -256,17 +391,65 @@
twilight: 2
type: Condition
keywords: Support Area
/*requires: {
}
effects: [
{
type: Activated
phase: Maneuver
cost: {
type: Spot
filter: valiant, companion
count: 3
}
effect: [
{
type: DiscardFromHand
forced: false
select: all(any)
memorize: discardedHand
}
{
type: Repeat
times: {
type: ForEachInMemory
memory: discardedHand
filter: side(freeps)
}
effect: {
type: Exert
select: choose(minion)
}
}
{
type: Repeat
times: {
type: ForEachInMemory
memory: discardedHand
filter: side(shadow)
}
effect: {
type: Heal
select: choose(companion,or(valiant,culture(rohan)))
}
}
{
type: addModifier
modifier: {
type: CantUseSpecialAbilities
player: you
phase: maneuver
}
}
{
type: addModifier
modifier: {
type: CantPlayPhaseEvents
player: you
phase: maneuver
}
}
]
}
{
}
]*/
]
gametext: Maneuver: Spot 3 valiant companions to discard your hand. For every Shadow card discarded, exert a minion. For every Free Peoples card discarded, heal a valiant or [rohan] companion. You may not make any more Maneuver actions.
lore: ""
promotext: ""
@@ -303,17 +486,36 @@
strength: 2
itemclass: Hand weapon
target: culture(rohan),companion
/*requires: {
}
effects: [
{
type: Modifier
modifier: {
type: AddKeyword
keyword: damage+1
requires: {
type: CanSpot
filter: bearer, name(Eomer)
}
filter: bearer
}
}
{
type: Trigger
trigger: {
type: WinsSkirmish
filter: bearer
}
requires: {
type: CanSpot
filter: bearer, name(Eomer)
}
effect: {
type: ReinforceTokens
culture: rohan
select: choose(any)
}
}
]*/
]
gametext: Bearer must be a [rohan] companion.<br>If bearer is Eomer, he is damage +1.<br>If bearer is Eomer, each time he wins a skirmish, you may reinforce a [rohan] token.
lore: "The swords flashed from the sheath as one."
promotext: ""
@@ -347,20 +549,27 @@
twilight: 2
type: Event
timewords: Assignment
/*requires: {
}
*/
effects: {
type: event
cost: {
type: SendMessage
text: Placeholder effect for development.
type: Exert
select: choose(valiant, companion)
memorize: exertedComp
},
effect: [
{
type: SendMessage
text: Placeholder effect for development.
type: AddKeyword
keyword: defender+1
select: memory(exertedComp)
}
{
type: ModifyStrength
amount: {
type: ForEachYouCanSpot
filter: InSkirmishAgainst(memory(exertedComp))
}
select: memory(exertedComp)
until: start(regroup)
}
]
}
@@ -397,24 +606,44 @@
twilight: 0
type: Event
timewords: Skirmish
/*requires: {
}
*/
effects: {
type: event
requires: [
{
type: CanSpot
filter: valiant, companion, not(AssignedToSkirmish(any))
}
{
type: CanSpot
filter: unbound, companion, InSkirmish
}
]
cost: {
type: SendMessage
text: Placeholder effect for development.
type: Spot
select: choose(valiant, companion, not(AssignedToSkirmish(any)))
memorize: rescuer
},
effect: [
{
type: SendMessage
text: Placeholder effect for development.
type: If
check: {
type: CanSpot
filter: name(Theoden), InSkirmish
}
true: {
type: AddKeyword
keyword: damage+1
select: memory(rescuer)
}
}
{
type: ReplaceInSkirmish
filter: unbound, companion
with: memory(rescuer)
}
]
}
gametext: Spot a valiant companion to have that companion replace a minion assigned to skirmish an unbound companion (and make them damage +1 if that unbound companion is Theoden).
gametext: Spot a valiant companion to have them replace an unbound companion in a skirmish (and make them damage +1 if that unbound companion is Theoden).
lore: "'Helm for Théoden King!'"
promotext: ""
alts: {
@@ -448,17 +677,48 @@
type: Condition
strength: 2
target: culture(rohan),companion
/*requires: {
}
effects: [
{
type: Modifier
modifier: {
type: AddKeyword
keyword: valiant
filter: bearer
}
}
{
type: Trigger
trigger: {
type: StartOfPhase
phase: regroup
}
effect: [
{
type: Memorize
filter: bearer
memory: DNTHBearer
}
{
type: Choice
texts: [
Wound {DNTHBearer}
Discard {self}
]
effects: [
{
type: Wound
select: bearer
}
{
type: Discard
select: self
}
]
}
]
}
]*/
]
gametext: Bearer must be a [rohan] companion.<br> Bearer is <b>valiant</b>.<br>At the start of the regroup phase, wound bearer or discard this condition.
lore: ""
promotext: ""
@@ -498,14 +758,46 @@
*/
effects: {
type: event
cost: {
type: SendMessage
text: Placeholder effect for development.
},
requires: {
type: CanSpot
filter: HasCultureTokenCount(2,rohan)
}
cost: [
{
type: MemorizeNumber
amount: {
type: ForEachYouCanSpot
filter: HasCultureTokenCount(2,rohan)
}
memory: availableConditions
}
{
type: ChooseANumber
text: Choose how many {rohan} conditions to remove 2 tokens from.
from: 1
to: memory(availableConditions)
memorize: chosenNumber
}
{
type: Repeat
times: memory(chosenNumber)
effect: {
type: RemoveCultureTokens
select: choose(HasCultureTokenCount(2,rohan))
count: 2
}
}
]
effect: [
{
type: SendMessage
text: Placeholder effect for development.
type: ModifyStrength
select: choose(valiant, companion)
count: 3
until: start(regroup)
amount: {
type: FromMemory
memory: chosenNumber
}
}
]
}

View File

@@ -60,7 +60,7 @@ public class AddCultureTokens implements EffectAppenderProducer {
List<Effect> result = new LinkedList<>();
for (PhysicalCard card : cardsFromMemory)
result.add(new AddTokenEffect(actionContext.getSource(), card, Token.findTokenForCulture(culture), tokenCount));
result.add(new AddTokenEffect(actionContext.getPerformingPlayer(), actionContext.getSource(), card, Token.findTokenForCulture(culture), tokenCount));
return result;
}

View File

@@ -27,8 +27,9 @@ import java.util.Collection;
public class PlayCardFromDiscard implements EffectAppenderProducer {
@Override
public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
FieldUtils.validateAllowedFields(effectObject, "select", "on", "discount", "removedTwilight", "optional", "extraEffects", "memorize");
FieldUtils.validateAllowedFields(effectObject, "player", "select", "on", "discount", "removedTwilight", "optional", "extraEffects", "memorize");
final String player = FieldUtils.getString(effectObject.get("player"), "player", "you");
final String select = FieldUtils.getString(effectObject.get("select"), "select");
final String onFilter = FieldUtils.getString(effectObject.get("on"), "on");
final ValueSource costModifierSource = ValueResolver.resolveEvaluator(effectObject.get("discount"), 0, environment);
@@ -68,7 +69,7 @@ public class PlayCardFromDiscard implements EffectAppenderProducer {
return Filters.playable(actionContext.getGame(), removedTwilight, costModifier, false, false, true);
},
actionContext -> countEvaluator, memorize, "you", "Choose card to play", environment));
actionContext -> countEvaluator, memorize, player, "Choose card to play from discard", environment));
result.addEffectAppender(
new DelayedAppender() {
@Override

View File

@@ -62,11 +62,11 @@ public class ReinforceTokens implements EffectAppenderProducer {
List<Effect> result = new LinkedList<>();
for (PhysicalCard card : cardsFromMemory) {
if (token != null) {
result.add(new AddTokenEffect(actionContext.getSource(), card, token, tokenCount));
result.add(new AddTokenEffect(actionContext.getPerformingPlayer(), actionContext.getSource(), card, token, tokenCount));
} else {
Token tokenOnCard = getFirstCultureToken(actionContext.getGame().getGameState().getTokens(card));
if (tokenOnCard != null) {
result.add(new AddTokenEffect(actionContext.getSource(), card, tokenOnCard, tokenCount));
result.add(new AddTokenEffect(actionContext.getPerformingPlayer(), actionContext.getSource(), card, tokenOnCard, tokenCount));
}
}
}

View File

@@ -70,9 +70,9 @@ public class RemoveCultureTokens implements EffectAppenderProducer {
List<Effect> result = new LinkedList<>();
for (PhysicalCard card : cardsFromMemory) {
if (token != null)
result.add(new RemoveTokenEffect(actionContext.getSource(), card, token, tokenCount));
result.add(new RemoveTokenEffect(actionContext.getPerformingPlayer(), actionContext.getSource(), card, token, tokenCount));
else {
result.add(new RemoveTokenEffect(actionContext.getSource(), card, getCultureTokenOnCard(game, card), tokenCount));
result.add(new RemoveTokenEffect(actionContext.getPerformingPlayer(), actionContext.getSource(), card, getCultureTokenOnCard(game, card), tokenCount));
}
}

View File

@@ -43,7 +43,7 @@ public class RemoveTokensCumulative implements EffectAppenderProducer {
protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
PhysicalCard cardFromMemory = actionContext.getCardFromMemory(memory);
if (cardFromMemory != null) {
return new RemoveTokenEffect(actionContext.getSource(), cardFromMemory, token, 1);
return new RemoveTokenEffect(actionContext.getPerformingPlayer(), actionContext.getSource(), cardFromMemory, token, 1);
} else {
return null;
}

View File

@@ -0,0 +1,36 @@
package com.gempukku.lotro.cards.build.field.effect.trigger;
import com.gempukku.lotro.cards.build.*;
import com.gempukku.lotro.cards.build.field.FieldUtils;
import com.gempukku.lotro.cards.build.field.effect.appender.resolver.PlayerResolver;
import com.gempukku.lotro.logic.timing.TriggerConditions;
import org.json.simple.JSONObject;
public class AddsCultureToken implements TriggerCheckerProducer {
@Override
public TriggerChecker getTriggerChecker(JSONObject value, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
FieldUtils.validateAllowedFields(value, "filter", "on", "player");
String filter = FieldUtils.getString(value.get("filter"), "filter", "any");
String onFilter = FieldUtils.getString(value.get("on"), "on", "any");
String player = FieldUtils.getString(value.get("player"), "player");
final FilterableSource sourceFilter = environment.getFilterFactory().generateFilter(filter, environment);
final FilterableSource onSourceFilter = environment.getFilterFactory().generateFilter(onFilter, environment);
PlayerSource playerSource = player != null ? PlayerResolver.resolvePlayer(player, environment) : null;
return new TriggerChecker() {
@Override
public boolean accepts(ActionContext actionContext) {
String playerId = playerSource != null ? playerSource.getPlayer(actionContext) : null;
return TriggerConditions.addedCultureToken(actionContext.getGame(), playerId, actionContext.getEffectResult(),
onSourceFilter.getFilterable(actionContext), sourceFilter.getFilterable(actionContext));
}
@Override
public boolean isBefore() {
return false;
}
};
}
}

View File

@@ -0,0 +1,36 @@
package com.gempukku.lotro.cards.build.field.effect.trigger;
import com.gempukku.lotro.cards.build.*;
import com.gempukku.lotro.cards.build.field.FieldUtils;
import com.gempukku.lotro.cards.build.field.effect.appender.resolver.PlayerResolver;
import com.gempukku.lotro.logic.timing.TriggerConditions;
import org.json.simple.JSONObject;
public class RemovesCultureToken implements TriggerCheckerProducer {
@Override
public TriggerChecker getTriggerChecker(JSONObject value, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
FieldUtils.validateAllowedFields(value, "filter", "on", "player");
String player = FieldUtils.getString(value.get("player"), "player");
String onFilter = FieldUtils.getString(value.get("on"), "on", "any");
String filter = FieldUtils.getString(value.get("filter"), "filter", "any");
PlayerSource playerSource = (player != null) ? PlayerResolver.resolvePlayer(player, environment) : null;
final FilterableSource sourceFilter = environment.getFilterFactory().generateFilter(filter, environment);
final FilterableSource onSourceFilter = environment.getFilterFactory().generateFilter(onFilter, environment);
return new TriggerChecker() {
@Override
public boolean accepts(ActionContext actionContext) {
String playerId = playerSource != null ? playerSource.getPlayer(actionContext) : null;
return TriggerConditions.removedCultureToken(actionContext.getGame(), playerId, actionContext.getEffectResult(),
onSourceFilter.getFilterable(actionContext), sourceFilter.getFilterable(actionContext));
}
@Override
public boolean isBefore() {
return false;
}
};
}
}

View File

@@ -36,6 +36,7 @@ public class TriggerCheckerFactory {
triggerCheckers.put("abouttotakecontrolofsite", new AboutToTakeControlOfSite());
triggerCheckers.put("abouttotakewound", new AboutToTakeWound());
triggerCheckers.put("addsburden", new AddsBurden());
triggerCheckers.put("addsculturetoken", new AddsCultureToken());
triggerCheckers.put("addsthreat", new AddsThreat());
triggerCheckers.put("afterallskirmishes", new AfterAllSkirmishes());
triggerCheckers.put("assignedagainst", new AssignedAgainst());
@@ -62,6 +63,7 @@ public class TriggerCheckerFactory {
triggerCheckers.put("reconciles", new Reconciles());
triggerCheckers.put("removedfromplay", new RemovedFromPlay());
triggerCheckers.put("removesburden", new RemovesBurden());
triggerCheckers.put("removesculturetoken", new RemovesCultureToken());
triggerCheckers.put("replacessite", new ReplacesSite());
triggerCheckers.put("revealscardfromtopofdrawdeck", new RevealsCardFromTopOfDrawDeck());
triggerCheckers.put("revealedcardfromhand", new RevealedCardFromHand());

View File

@@ -7,14 +7,18 @@ import com.gempukku.lotro.logic.GameUtils;
import com.gempukku.lotro.logic.modifiers.ModifierFlag;
import com.gempukku.lotro.logic.timing.AbstractEffect;
import com.gempukku.lotro.logic.timing.Effect;
import com.gempukku.lotro.logic.timing.results.AddBurdenResult;
import com.gempukku.lotro.logic.timing.results.AddCultureTokenResult;
public class AddTokenEffect extends AbstractEffect {
private final String _performingPlayer;
private final PhysicalCard _source;
private final PhysicalCard _target;
private final Token _token;
private final int _count;
public AddTokenEffect(PhysicalCard source, PhysicalCard target, Token token, int count) {
public AddTokenEffect(String performingPlayer, PhysicalCard source, PhysicalCard target, Token token, int count) {
_performingPlayer = performingPlayer;
_source = source;
_target = target;
_token = token;
@@ -47,6 +51,9 @@ public class AddTokenEffect extends AbstractEffect {
game.getGameState().sendMessage(GameUtils.getCardLink(_source) + " added " + _count + " " + _token + " token" + ((_count > 1) ? "s" : "") + " to " + GameUtils.getCardLink(_target));
}
for (int i = 0; i < _count; i++)
game.getActionsEnvironment().emitEffectResult(new AddCultureTokenResult(_performingPlayer, _source, _target));
return new FullEffectResult(true);
}
return new FullEffectResult(false);

View File

@@ -7,14 +7,18 @@ import com.gempukku.lotro.logic.GameUtils;
import com.gempukku.lotro.logic.modifiers.ModifierFlag;
import com.gempukku.lotro.logic.timing.AbstractEffect;
import com.gempukku.lotro.logic.timing.Effect;
import com.gempukku.lotro.logic.timing.results.AddCultureTokenResult;
import com.gempukku.lotro.logic.timing.results.RemoveCultureTokenResult;
public class RemoveTokenEffect extends AbstractEffect {
private final String _performingPlayer;
private final PhysicalCard _source;
private final PhysicalCard _target;
private final Token _token;
private final int _count;
public RemoveTokenEffect(PhysicalCard source, PhysicalCard target, Token token, int count) {
public RemoveTokenEffect(String performingPlayer, PhysicalCard source, PhysicalCard target, Token token, int count) {
_performingPlayer = performingPlayer;
_source = source;
_target = target;
_token = token;
@@ -47,6 +51,9 @@ public class RemoveTokenEffect extends AbstractEffect {
game.getGameState().sendMessage(GameUtils.getCardLink(_source) + " removed " + removeTokens + " " + _token + " token" + ((removeTokens > 1) ? "s" : "") + " from " + GameUtils.getCardLink(_target));
}
for (int i = 0; i < _count; i++)
game.getActionsEnvironment().emitEffectResult(new RemoveCultureTokenResult(_performingPlayer, _source, _target));
return new FullEffectResult(removeTokens == _count);
} else {
return new FullEffectResult(false);

View File

@@ -46,7 +46,7 @@ public abstract class EffectResult {
PUT_ON_THE_ONE_RING,
REMOVE_BURDEN, ADD_BURDEN, ADD_THREAT,
REMOVE_BURDEN, ADD_BURDEN, ADD_THREAT, ADD_CULTURE_TOKEN, REMOVE_CULTURE_TOKEN,
FOR_EACH_REVEALED_FROM_HAND, FOR_EACH_REVEALED_FROM_TOP_OF_DECK,

View File

@@ -59,6 +59,28 @@ public class TriggerConditions {
return false;
}
public static boolean addedCultureToken(LotroGame game, String playerId, EffectResult effectResult, Filterable from, Filterable... targetFilters) {
if (effectResult.getType() == EffectResult.Type.ADD_CULTURE_TOKEN) {
var tokenResult = (AddCultureTokenResult) effectResult;
if (playerId != null && !playerId.equals(tokenResult.getPerformingPlayer()))
return false;
return Filters.accepts(game, from, tokenResult.getSource())
&& Filters.and(targetFilters).accepts(game, tokenResult.getSource());
}
return false;
}
public static boolean removedCultureToken(LotroGame game, String playerId, EffectResult effectResult, Filterable from, Filterable... targetFilters) {
if (effectResult.getType() == EffectResult.Type.REMOVE_CULTURE_TOKEN) {
var tokenResult = (RemoveCultureTokenResult) effectResult;
if (playerId != null && !playerId.equals(tokenResult.getPerformingPlayer()))
return false;
return Filters.accepts(game, from, tokenResult.getSource())
&& Filters.and(targetFilters).accepts(game, tokenResult.getSource());
}
return false;
}
public static boolean addedThreat(LotroGame game, EffectResult effectResult, Filterable... sourceFilters) {
if (effectResult.getType() == EffectResult.Type.ADD_THREAT) {
AddThreatResult threatResult = (AddThreatResult) effectResult;

View File

@@ -0,0 +1,26 @@
package com.gempukku.lotro.logic.timing.results;
import com.gempukku.lotro.game.PhysicalCard;
import com.gempukku.lotro.logic.timing.EffectResult;
public class AddCultureTokenResult extends EffectResult {
private final String _performingPlayer;
private final PhysicalCard _source;
private final PhysicalCard _target;
public AddCultureTokenResult(String performingPlayer, PhysicalCard source, PhysicalCard target) {
super(Type.ADD_CULTURE_TOKEN);
_performingPlayer = performingPlayer;
_source = source;
_target = target;
}
public PhysicalCard getSource() {
return _source;
}
public PhysicalCard getTarget() { return _target; }
public String getPerformingPlayer() {
return _performingPlayer;
}
}

View File

@@ -0,0 +1,26 @@
package com.gempukku.lotro.logic.timing.results;
import com.gempukku.lotro.game.PhysicalCard;
import com.gempukku.lotro.logic.timing.EffectResult;
public class RemoveCultureTokenResult extends EffectResult {
private final String _performingPlayerId;
private final PhysicalCard _source;
private final PhysicalCard _target;
public RemoveCultureTokenResult(String performingPlayerId, PhysicalCard source, PhysicalCard target) {
super(Type.REMOVE_CULTURE_TOKEN);
_performingPlayerId = performingPlayerId;
_source = source;
_target = target;
}
public String getPerformingPlayer() {
return _performingPlayerId;
}
public PhysicalCard getSource() {
return _source;
}
public PhysicalCard getTarget() { return _target; }
}

View File

@@ -40,7 +40,7 @@ public class Card_V2_042_Tests
* Type: Condition
* Subtype: Support area
* Game Text: Each time a [moria] minion wins a skirmish, you may stack it here.
* Shadow: Play a unique minion stacked here, it is twilight cost -1 for each card stacked here. Discard this condition.
* Shadow: Play a unique minion stacked here, it is twilight cost -1 for each other card stacked here. Discard this condition.
*/
var scn = GetScenario();

View File

@@ -39,7 +39,7 @@ public class Card_V2_051_Tests
* Twilight Cost: 0
* Type: Event
* Subtype: Skirmish
* Game Text: Spot a valiant companion to have that companion replace a minion assigned to skirmish an unbound companion (and make them damage +1 if that unbound companion is Theoden).
* Game Text: Spot a valiant companion to have them replace an unbound companion in a skirmish (and make them damage +1 if that unbound companion is Theoden).
*/
var scn = GetScenario();