diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV02/setv02-Moria-playtest.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV02/setv02-Moria-playtest.hjson
index 9c2b3ae49..1aa40d908 100644
--- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV02/setv02-Moria-playtest.hjson
+++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV02/setv02-Moria-playtest.hjson
@@ -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.
Each time a minion takes a wound, add a threat.
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.
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.
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.
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: {
diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV02/setv02-Rohan-playtest.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV02/setv02-Rohan-playtest.hjson
index 70172d4ff..51c2f0861 100644
--- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV02/setv02-Rohan-playtest.hjson
+++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV02/setv02-Rohan-playtest.hjson
@@ -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.
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.
Each exhausted companion gains valiant.
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).
Skirmish: If a Hobbit companion is skirmishing, add this ally's strength to that Hobbit and make that Hobbit gain valiant 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.
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.
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.
If bearer is Eomer, he is damage +1.
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.
Bearer is valiant.
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
+ }
}
]
}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AddCultureTokens.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AddCultureTokens.java
index 1f52afc7a..e7f9ef054 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AddCultureTokens.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AddCultureTokens.java
@@ -60,7 +60,7 @@ public class AddCultureTokens implements EffectAppenderProducer {
List 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;
}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayCardFromDiscard.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayCardFromDiscard.java
index 4ab3b3cbe..5dca2595f 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayCardFromDiscard.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PlayCardFromDiscard.java
@@ -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
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/ReinforceTokens.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/ReinforceTokens.java
index 226f3f703..044e9f057 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/ReinforceTokens.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/ReinforceTokens.java
@@ -62,11 +62,11 @@ public class ReinforceTokens implements EffectAppenderProducer {
List 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));
}
}
}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RemoveCultureTokens.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RemoveCultureTokens.java
index e26f57754..d16a53081 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RemoveCultureTokens.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RemoveCultureTokens.java
@@ -70,9 +70,9 @@ public class RemoveCultureTokens implements EffectAppenderProducer {
List 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));
}
}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RemoveTokensCumulative.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RemoveTokensCumulative.java
index 4e3e8e25d..8d07e9812 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RemoveTokensCumulative.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/RemoveTokensCumulative.java
@@ -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;
}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/AddsCultureToken.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/AddsCultureToken.java
new file mode 100644
index 000000000..a84f1100a
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/AddsCultureToken.java
@@ -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;
+ }
+ };
+ }
+}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/RemovesCultureToken.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/RemovesCultureToken.java
new file mode 100644
index 000000000..34f370ffd
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/RemovesCultureToken.java
@@ -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;
+ }
+ };
+ }
+}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java
index e581c1709..4876717df 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/trigger/TriggerCheckerFactory.java
@@ -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());
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/AddTokenEffect.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/AddTokenEffect.java
index a1515eee5..b3c7fbf23 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/AddTokenEffect.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/AddTokenEffect.java
@@ -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);
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/RemoveTokenEffect.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/RemoveTokenEffect.java
index c1cfdbfb8..a4d3c45c9 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/RemoveTokenEffect.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/RemoveTokenEffect.java
@@ -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);
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/EffectResult.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/EffectResult.java
index 4ec91cde5..57faa1101 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/EffectResult.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/EffectResult.java
@@ -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,
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java
index 5944b03dc..7e4e5da27 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/TriggerConditions.java
@@ -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;
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/results/AddCultureTokenResult.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/results/AddCultureTokenResult.java
new file mode 100644
index 000000000..f55092988
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/results/AddCultureTokenResult.java
@@ -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;
+ }
+}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/results/RemoveCultureTokenResult.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/results/RemoveCultureTokenResult.java
new file mode 100644
index 000000000..28e649fdf
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/results/RemoveCultureTokenResult.java
@@ -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; }
+}
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_042_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_042_Tests.java
index ea029338e..4f8cb6cb2 100644
--- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_042_Tests.java
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_042_Tests.java
@@ -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();
diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_051_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_051_Tests.java
index ec871984a..09fa2fb88 100644
--- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_051_Tests.java
+++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/unofficial/pc/vsets/set_v02/Card_V2_051_Tests.java
@@ -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();