diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set03/set3-isengard.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set03/set3-isengard.hjson
index a731f9535..190c2a249 100644
--- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set03/set3-isengard.hjson
+++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set03/set3-isengard.hjson
@@ -645,47 +645,18 @@
type: exert
select: self
}
- effect: [
- {
- type: chooseActiveCards
- select: choose(culture(isengard),minion,assignableToSkirmishAgainst(companion,not(ringBearer)))
- text: Choose ISENGARD minion to assign
- memorize: assignedMinion
+ effect: {
+ type: assignFpCharacterToSkirmish
+ fpCharacter: choose(companion,not(ringBearer))
+ minion: choose(culture(isengard),minion)
+ memorizeFPCharacter: assignedCompanion
+ memorizeMinion: assignedMinion
+ preventText: Would you like to exert {assignedCompanion} to prevent it being assigned to {assignedMinion}
+ preventCost: {
+ type: exert
+ select: memory(assignedCompanion)
}
- {
- type: chooseActiveCards
- select: choose(companion,not(ringBearer),assignableToSkirmishAgainst(memory(assignedMinion)))
- text: Choose companion (except Ring-Bearer) to assign
- memorize: assignedCompanion
- }
- {
- type: If
- check: [
- {
- type: hasInMemory
- memory: assignedMinion
- }
- {
- type: hasInMemory
- memory: assignedCompanion
- }
- ]
- true: {
- type: preventable
- player: fp
- text: Would you like to exert {assignedCompanion} to prevent it being assigned to {assignedMinion}
- cost: {
- type: exert
- select: memory(assignedCompanion)
- }
- effect: {
- type: assignFpCharacterToSkirmish
- fpCharacter: memory(assignedCompanion)
- minion: memory(assignedMinion)
- }
- }
- }
- ]
+ }
}
]
}
diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set04/set04-Isengard.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set04/set04-Isengard.hjson
index 443e82393..30fb53b2d 100644
--- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set04/set04-Isengard.hjson
+++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set04/set04-Isengard.hjson
@@ -427,42 +427,17 @@
select: choose(culture(isengard),tracker)
memorize: exertedTracker
},
- effect: [
- {
- type: chooseActiveCards
- select: choose(unbound,companion,assignableToSkirmishAgainst(memory(exertedTracker)))
- text: Choose companion to assign {exertedTracker} to
- memorize: chosenCompanion
- }
- {
- type: if
- check: {
- type: memoryMatches
- memory: chosenCompanion
- filter: hobbit
- }
- true: {
- type: assignFPCharacterToSkirmish
- fpCharacter: memory(chosenCompanion)
- minion: memory(exertedTracker)
- }
- false: {
- type: preventable
- text: Would you like to exert {chosenCompanion} to prevent {exertedTracker} to be assigned to it?
- player: fp
- cost: {
- type: exert
- player: fp
- select: memory(chosenCompanion)
- }
- effect: {
- type: assignFPCharacterToSkirmish
- fpCharacter: memory(chosenCompanion)
- minion: memory(exertedTracker)
- }
- }
- }
- ]
+ effect: {
+ type: assignFPCharacterToSkirmish
+ fpCharacter: choose(unbound,companion)
+ minion: memory(exertedTracker)
+ memorizeFPCharacter: chosenCompanion
+ preventText: Would you like to exert {chosenCompanion} to prevent {exertedTracker} to be assigned to it?
+ preventCost: {
+ type: exert
+ select: choose(memory(chosenCompanion),not(hobbit))
+ }
+ }
}
gametext: Search.
Assignment: Exert an [isengard] tracker to assign it to an unbound companion. That companion may exert to prevent this (unless that companion is a Hobbit).
lore: What are they wanted for?... Why alive? Do they give good sport?'
@@ -1319,18 +1294,14 @@
}
]
effect: {
- type: preventable
- text: Would you like to exert bearer of Many Riddles to prevent {chosenTracker} being assigned to it?
- player: fp
- cost: {
+ type: assignFPCharacterToSkirmish
+ fpCharacter: bearer
+ minion: memory(chosenTracker)
+ preventText: Would you like to exert bearer of Many Riddles to prevent {chosenTracker} being assigned to it?
+ preventCost: {
type: exert
select: bearer
}
- effect: {
- type: assignFPCharacterToSkirmish
- fpCharacter: bearer
- minion: memory(chosenTracker)
- }
}
}
]
@@ -1591,28 +1562,17 @@
select: self
}
]
- effect: [
- {
- type: chooseActiveCards
- select: choose(unbound,companion,assignableToSkirmishAgainst(self))
- text: Choose companion to assign it to
- memorize: chosenCompanion
+ effect: {
+ type: assignFPCharacterToSkirmish
+ fpCharacter: choose(unbound,companion,assignableToSkirmishAgainst(self))
+ minion: self
+ memorizeFPCharacter: chosenCompanion
+ preventText: Would you like to exert {chosenCompanion} to prevent {self} being assigned to it?
+ preventCost: {
+ type: exert
+ select: memory(chosenCompanion)
}
- {
- type: preventable
- text: Would you like to exert {chosenCompanion} to prevent Orthanc Champion being assigned to it?
- player: fp
- cost: {
- type: exert
- select: memory(chosenCompanion)
- }
- effect: {
- type: assignFPCharacterToSkirmish
- fpCharacter: memory(chosenCompanion)
- minion: self
- }
- }
- ]
+ }
}
]
gametext: Damage +1.
Assignment: Exert Orthanc Champion to assign it to an unbound companion. That companion may exert to prevent this.
diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set04/set04-Raider.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set04/set04-Raider.hjson
index 84d98396e..e25b9b315 100644
--- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set04/set04-Raider.hjson
+++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set04/set04-Raider.hjson
@@ -2052,21 +2052,16 @@
}
]
effect: {
- type: preventable
- player: fp
- text: Would you like to discard an unbound companion to prevent Southron Commander from being assigned to the Ring-bearer?
- cost: {
+ type: assignFpCharacterToSkirmish
+ fpCharacter: choose(ringBearer)
+ minion: self
+ memorizeFPCharacter: ringBearer
+ preventText: Would you like to discard an unbound companion to prevent {self} from being assigned to {ringBearer}?
+ preventCost: {
type: discard
- player: fp
select: choose(unbound,companion)
}
- effect: {
- type: assignFpCharacterToSkirmish
- fpCharacter: choose(ringBearer)
- minion: self
- }
}
-
}
]
gametext: Southron. Ambush (1).
Assignment: Spot 6 companions to assign this minion to the Ring-bearer. The Free Peoples player may discard an unbound companion to prevent this.
@@ -2439,19 +2434,16 @@
}
]
effect: {
- type: preventable
- player: fp
- text: Would you like to make opponent discard a companion to prevent assigning Southron Troop to the Ring-bearer?
- cost: {
+ type: assignFPCharacterToSkirmish
+ fpCharacter: choose(ringBearer)
+ minion: self
+ memorizeFPCharacter: ringBearer
+ preventText: Would you like to make opponent discard a companion to prevent assigning {self} to {ringBearer}?
+ preventCost: {
type: discard
player: shadow
select: choose(companion,not(ringBearer))
}
- effect: {
- type: assignFpCharacterToSkirmish
- fpCharacter: choose(ringBearer)
- minion: self
- }
}
}
]
@@ -2576,18 +2568,15 @@
}
]
effect: {
- type: preventable
- player: fp
- text: Would you like to add 4 twilight to prevent Southron Wanderer getting assigned to skirmish against the Ring-bearer
- cost: {
+ type: assignFpCharacterToSkirmish
+ fpCharacter: choose(ringBearer)
+ minion: self
+ memorizeFPCharacter: ringBearer
+ preventText: Would you like to add 4 twilight to prevent {self} getting assigned to skirmish against {ringBearer}?
+ preventCost: {
type: addTwilight
amount: 4
}
- effect: {
- type: assignFpCharacterToSkirmish
- fpCharacter: choose(ringBearer)
- minion: self
- }
}
}
@@ -2629,24 +2618,16 @@
type: event
effect: [
{
- type: chooseActiveCards
- text: Choose an Easterling to assign to Ring-bearer
- select: choose(easterling,assignableToSkirmishAgainst(ringBearer))
- memorize: chosenEasterling
- }
- {
- type: preventable
- player: fp
- text: Would you like to add burden to prevent assigning {chosenEasterling} to the Ring-bearer?
- cost: {
+ type: assignFpCharacterToSkirmish
+ fpCharacter: choose(ringBearer)
+ minion: choose(easterling)
+ memorizeFPCharacter: ringBearer
+ memorizeMinion: chosenEasterling
+ preventText: Would you like to add burden to prevent assigning {chosenEasterling} to {ringBearer}?
+ preventCost: {
type: addBurdens
amount: 1
}
- effect: {
- type: assignFpCharacterToSkirmish
- fpCharacter: choose(ringBearer)
- minion: memory(chosenEasterling)
- }
}
]
}
diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set10/set10-Gollum.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set10/set10-Gollum.hjson
index da3c2ad01..f94f63526 100644
--- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set10/set10-Gollum.hjson
+++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set10/set10-Gollum.hjson
@@ -240,24 +240,21 @@
type: activated
phase: assignment
effect: {
- type: preventable
- player: free people
- text: Would you like to add a burden and assign Gollum?
- cost: [
- {
- type: addBurdens
- }
- {
- type: assignFpCharacterToSkirmish
- fpCharacter: choose(any)
- minion: choose(name(Gollum))
- }
- ]
- effect: {
- type: assignFpCharacterToSkirmish
- fpCharacter: choose(companion,hasAttached(artifact))
- minion: choose(name(Gollum))
+ type: assignFpCharacterToSkirmish
+ fpCharacter: choose(companion,hasAttached(artifact))
+ minion: choose(name(Gollum))
+ memorizeFPCharacter: chosenCompanion
+ memorizeMinion: gollum
+ preventText: Would you like to add a burden and assign Gollum to prevent assigning {chosenCompanion} to {gollum}?
+ preventCost: {
+ type: addBurdens
}
+ insteadEffect: {
+ type: assignFpCharacterToSkirmish
+ player: free people
+ fpCharacter: choose(any)
+ minion: choose(name(Gollum))
+ }
}
}
{
diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set11/set11-Orc.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set11/set11-Orc.hjson
index 216adde9f..5c4a0ad31 100644
--- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set11/set11-Orc.hjson
+++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set11/set11-Orc.hjson
@@ -178,19 +178,15 @@
select: self
}
effect: {
- type: preventable
- player: free people
- text: Would you like to discard an artifact to prevent the assignment?
- cost: {
+ type: assignFpCharacterToSkirmish
+ fpCharacter: choose(companion,hasAttached(artifact))
+ minion: self
+ memorizeFPCharacter: chosenCompanion
+ preventText: Would you like to discard an artifact to prevent the assignment of {chosenCompanion} to {self}?
+ preventCost: {
type: discard
- player: free people
select: choose(artifact)
}
- effect: {
- type: assignFpCharacterToSkirmish
- fpCharacter: choose(companion,hasAttached(artifact))
- minion: self
- }
}
}
]
diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set15/set15-Orc.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set15/set15-Orc.hjson
index a1121017f..1d425bd8b 100644
--- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set15/set15-Orc.hjson
+++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set15/set15-Orc.hjson
@@ -1384,18 +1384,15 @@
count: 6
}
true: {
- type: preventable
- player: free people
- text: Would you like to exert a companion to prevent assigning Tower Troll to skirmish?
- cost: {
+ type: assignFPCharacterToSkirmish
+ fpCharacter: choose(companion,not(ringBearer))
+ minion: self
+ memorizeFPCharacter: chosenCompanion
+ preventText: Would you like to exert a companion to prevent assigning {chosenCompanion} to skirmish {self}?
+ preventCost: {
type: exert
select: choose(companion)
}
- effect: {
- type: assignFPCharacterToSkirmish
- fpCharacter: choose(companion,not(ringBearer))
- minion: self
- }
}
false: {
type: assignFPCharacterToSkirmish
diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set18/set18-Uruk-hai.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set18/set18-Uruk-hai.hjson
index 9a0b3eb06..92100cc3d 100644
--- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set18/set18-Uruk-hai.hjson
+++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set18/set18-Uruk-hai.hjson
@@ -290,16 +290,12 @@
}
effect: [
{
- type: chooseActiveCards
- text: Choose unbound companion to assign Lurtz to
- select: choose(unbound,companion,assignableToSkirmishAgainst(self))
- memorize: chosenCompanion
- }
- {
- type: preventable
- player: free people
- text: Would you like to exert {chosenCompanion} or add a burden to prevent assigning it to Lurtz?
- cost: {
+ type: assignFPCharacterToSkirmish
+ fpCharacter: choose(unbound,companion)
+ minion: self
+ memorizeFPCharacter: chosenCompanion
+ preventText: Would you like to exert {chosenCompanion} or add a burden to prevent assigning it to {self}?
+ preventCost: {
type: choice
texts: [
Exert - {chosenCompanion}
@@ -315,11 +311,6 @@
}
]
}
- effect: {
- type: assignFPCharacterToSkirmish
- fpCharacter: memory(chosenCompanion)
- minion: self
- }
}
]
}
diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set19/set19.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set19/set19.hjson
index f7048615a..dda3f504b 100644
--- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set19/set19.hjson
+++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set19/set19.hjson
@@ -624,28 +624,17 @@
type: exert
select: self
}
- effect: [
- {
- type: chooseActiveCards
- text: Choose unbound companion to assign Grima to
- select: choose(unbound,companion,assignableToSkirmishAgainst(name(Grima)))
- memorize: chosenCompanion
- }
- {
- type: preventable
- player: fp
- text: Would you like to exert {chosenCompanion} to prevent Grima assigning to it
- cost: {
- type: exert
- select: memory(chosenCompanion)
- }
- effect: {
- type: assignFpCharacterToSkirmish
- fpCharacter: memory(chosenCompanion)
- minion: choose(name(Grima))
- }
- }
- ]
+ effect: {
+ type: assignFPCharacterToSkirmish
+ fpCharacter: choose(unbound,companion)
+ minion: self
+ memorizeFPCharacter: chosenCompanion
+ preventText: Would you like to exert {chosenCompanion} to prevent {self} assigning to it?
+ preventCost: {
+ type: exert
+ select: memory(chosenCompanion)
+ }
+ }
}
]
}
diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/hobbit/set32/set32-shadow.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/hobbit/set32/set32-shadow.hjson
index a26776398..7bfac4de1 100644
--- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/hobbit/set32/set32-shadow.hjson
+++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/hobbit/set32/set32-shadow.hjson
@@ -878,45 +878,31 @@
select: self
}
effect: [
- {
- type: chooseActiveCards
- select: choose(minion,or(culture(gundabad),culture(wraith)),assignableToSkirmishAgainst(companion,not(name(Bilbo))))
- text: Choose minion to assign to a companion
- memorize: chosenMinion
- }
- {
- type: chooseActiveCards
- select: choose(companion,not(name(Bilbo)),assignableToSkirmishAgainst(memory(chosenMinion)))
- text: Choose companion
- memorize: chosenCompanion
- }
- {
- type: preventable
- player: fp
- text: Would you like to add 2 doubts or exert {chosenCompanion} to prevent it from being assigned to {chosenMinion}?
- cost: {
- type: choice
- texts: [
- Add 2 doubts
- Exert the companion
- ]
- effects: [
- {
- type: addBurdens
- amount: 2
+ {
+ type: assignFPCharacterToSkirmish
+ fpCharacter: choose(companion,not(name(Bilbo)))
+ minion: choose(minion,or(culture(gundabad),culture(wraith)))
+ memorizeFPCharacter: chosenCompanion
+ memorizeMinion: chosenMinion
+ preventText: Would you like to add 2 doubts or exert {chosenCompanion} to prevent it from being assigned to {chosenMinion}?
+ preventCost: {
+ type: choice
+ texts: [
+ Add 2 doubts
+ Exert the companion
+ ]
+ effects: [
+ {
+ type: addBurdens
+ amount: 2
+ }
+ {
+ type: exert
+ select: memory(chosenCompanion)
+ }
+ ]
}
- {
- type: exert
- select: choose(memory(chosenCompanion))
- }
- ]
}
- effect: {
- type: assignFpCharacterToSkirmish
- fpCharacter: choose(memory(chosenCompanion))
- minion: choose(memory(chosenMinion))
- }
- }
]
}
]
diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV01/V1_moria.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV01/V1_moria.hjson
index ea5e4b079..38ad5d0c1 100644
--- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV01/V1_moria.hjson
+++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/setV01/V1_moria.hjson
@@ -31,27 +31,19 @@
select: self
}
effect: [
- {
- type: ChooseActiveCards
- text: Choose a {moria} creature to assign to the Ring-bearer.
- select: choose(culture(moria),creature)
- memorize: chosenCreature
- }
- {
- type: Preventable
- player: freeps
- text: Would you like to exert the Ring-bearer twice to prevent {chosenCreature} being assigned to them?
- cost: {
+ {
+ type: assignFPCharacterToSkirmish
+ fpCharacter: choose(ringBearer)
+ minion: choose(culture(moria),creature)
+ memorizeFPCharacter: ringBearer
+ memorizeMinion: chosenCreature
+ preventText: Would you like to exert {ringBearer} twice to prevent {chosenCreature} being assigned to them?
+ preventCost: {
type: Exert
- select: choose(Ring-bearer)
+ select: memory(ringBearer)
times: 2
- }
- effect: {
- type: assignFpCharacterToSkirmish
- fpCharacter: choose(ringbearer)
- minion: memory(chosenCreature)
- }
- }
+ }
+ }
]
}
]
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/OpponentPlayerSource.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/OpponentPlayerSource.java
new file mode 100644
index 000000000..5608f4ca4
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/OpponentPlayerSource.java
@@ -0,0 +1,16 @@
+package com.gempukku.lotro.cards.build;
+
+import com.gempukku.lotro.logic.GameUtils;
+
+public class OpponentPlayerSource implements PlayerSource {
+ private PlayerSource playerSource;
+
+ public OpponentPlayerSource(PlayerSource playerSource) {
+ this.playerSource = playerSource;
+ }
+
+ @Override
+ public String getPlayer(ActionContext actionContext) {
+ return GameUtils.getFirstOpponent(actionContext.getGame(), playerSource.getPlayer(actionContext));
+ }
+}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AssignFpCharacterToSkirmish.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AssignFpCharacterToSkirmish.java
index ed82002a3..b05df803d 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AssignFpCharacterToSkirmish.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/AssignFpCharacterToSkirmish.java
@@ -17,18 +17,26 @@ import com.gempukku.lotro.logic.timing.Effect;
import org.json.simple.JSONObject;
import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
public class AssignFpCharacterToSkirmish implements EffectAppenderProducer {
@Override
public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
- FieldUtils.validateAllowedFields(effectObject, "player", "fpCharacter", "minion", "memorizeMinion", "memorizeFPCharacter", "ignoreUnassigned");
+ FieldUtils.validateAllowedFields(effectObject, "player", "fpCharacter", "minion", "memorizeMinion", "memorizeFPCharacter", "ignoreUnassigned", "preventCost", "preventText", "insteadEffect");
final String player = FieldUtils.getString(effectObject.get("player"), "player", "you");
final String fpCharacter = FieldUtils.getString(effectObject.get("fpCharacter"), "fpCharacter", "choose(any)");
final String minion = FieldUtils.getString(effectObject.get("minion"), "minion", "choose(any)");
+ JSONObject[] preventCostArray = FieldUtils.getObjectArray(effectObject.get("preventCost"), "preventCost");
+ JSONObject[] insteadEffectArray = FieldUtils.getObjectArray(effectObject.get("insteadEffect"), "insteadEffect");
+ final String preventText = FieldUtils.getString(effectObject.get("preventText"), "preventText");
+ if ((preventCostArray.length > 0 && preventText == null) || (preventCostArray.length == 0 && preventText != null))
+ throw new InvalidCardDefinitionException("preventText and preventCost have to be specified (or not) together");
+ if (insteadEffectArray.length > 0 && preventCostArray.length == 0)
+ throw new InvalidCardDefinitionException("preventCost is required if insteadEffect is present");
+ EffectAppender[] preventEffectAppenders = environment.getEffectAppenderFactory().getEffectAppenders(preventCostArray, environment);
+ EffectAppender[] insteadEffectAppenders = environment.getEffectAppenderFactory().getEffectAppenders(insteadEffectArray, environment);
+
final String minionMemory = FieldUtils.getString(effectObject.get("memorizeMinion"), "memorizeMinion", "_tempMinion");
final String fpCharacterMemory = FieldUtils.getString(effectObject.get("memorizeFPCharacter"), "memorizeFPCharacter", "_tempFpCharacter");
final boolean ignoreUnassigned = FieldUtils.getBoolean(effectObject.get("ignoreUnassigned"), "ignoreUnassigned", false);
@@ -38,7 +46,6 @@ public class AssignFpCharacterToSkirmish implements EffectAppenderProducer {
final FilterableSource minionFilter = getSource(minion, environment);
MultiEffectAppender result = new MultiEffectAppender();
-
result.addEffectAppender(
CardResolver.resolveCard(fpCharacter,
(actionContext) -> {
@@ -52,29 +59,41 @@ public class AssignFpCharacterToSkirmish implements EffectAppenderProducer {
(actionContext) -> {
final String assigningPlayer = playerSource.getPlayer(actionContext);
Side assigningSide = GameUtils.getSide(actionContext.getGame(), assigningPlayer);
- final Collection extends PhysicalCard> fpChar = actionContext.getCardsFromMemory("_tempFpCharacter");
+ final Collection extends PhysicalCard> fpChar = actionContext.getCardsFromMemory(fpCharacterMemory);
return Filters.assignableToSkirmishAgainst(assigningSide, Filters.in(fpChar), ignoreUnassigned, false);
}, minionMemory, player, "Choose minion to assign to character", environment));
- result.addEffectAppender(
- new DelayedAppender() {
- @Override
- protected List extends Effect> createEffects(boolean cost, CostToEffectAction action, ActionContext actionContext) {
- final String assigningPlayer = playerSource.getPlayer(actionContext);
- final Collection extends PhysicalCard> fpChar = actionContext.getCardsFromMemory(fpCharacterMemory);
- final Collection extends PhysicalCard> minion = actionContext.getCardsFromMemory(minionMemory);
- if (fpChar.size() == 1 && minion.size() == 1) {
- AssignmentEffect effect = new AssignmentEffect(assigningPlayer, fpChar.iterator().next(), minion.iterator().next());
- effect.setIgnoreSingleMinionRestriction(ignoreUnassigned);
- return Collections.singletonList(effect);
- }
- return null;
- }
- });
+
+ DelayedAppender assignAppender = new DelayedAppender() {
+ @Override
+ protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
+ final String assigningPlayer = playerSource.getPlayer(actionContext);
+ final Collection extends PhysicalCard> fpChar = actionContext.getCardsFromMemory(fpCharacterMemory);
+ final Collection extends PhysicalCard> minion = actionContext.getCardsFromMemory(minionMemory);
+ if (fpChar.size() == 1 && minion.size() == 1) {
+ AssignmentEffect effect = new AssignmentEffect(assigningPlayer, fpChar.iterator().next(), minion.iterator().next());
+ effect.setIgnoreSingleMinionRestriction(ignoreUnassigned);
+ return effect;
+ } else {
+ return null;
+ }
+ }
+ };
+
+ if (preventEffectAppenders.length > 0) {
+ result.addEffectAppender(
+ new PreventableEffectAppender(new OpponentPlayerSource(playerSource), preventText,
+ actionContext -> {
+ final Collection extends PhysicalCard> fpChar = actionContext.getCardsFromMemory(fpCharacterMemory);
+ final Collection extends PhysicalCard> minion1 = actionContext.getCardsFromMemory(minionMemory);
+ return fpChar.size() == 1 && minion1.size() == 1;
+ }, preventEffectAppenders, new EffectAppender[]{assignAppender}, insteadEffectAppenders));
+ } else {
+ result.addEffectAppender(assignAppender);
+ }
return result;
}
-
private FilterableSource getSource(String filter, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
if (filter.startsWith("choose(") && filter.endsWith(")"))
return environment.getFilterFactory().generateFilter(filter.substring(filter.indexOf("(") + 1, filter.lastIndexOf(")")), environment);
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PreventableAppenderProducer.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PreventableAppenderProducer.java
index c4169db80..b26105050 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PreventableAppenderProducer.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PreventableAppenderProducer.java
@@ -1,19 +1,13 @@
package com.gempukku.lotro.cards.build.field.effect.appender;
-import com.gempukku.lotro.cards.build.*;
+import com.gempukku.lotro.cards.build.CardGenerationEnvironment;
+import com.gempukku.lotro.cards.build.InvalidCardDefinitionException;
+import com.gempukku.lotro.cards.build.PlayerSource;
import com.gempukku.lotro.cards.build.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.PlayerResolver;
-import com.gempukku.lotro.game.state.LotroGame;
-import com.gempukku.lotro.logic.GameUtils;
-import com.gempukku.lotro.logic.actions.CostToEffectAction;
-import com.gempukku.lotro.logic.actions.SubAction;
-import com.gempukku.lotro.logic.decisions.YesNoDecision;
-import com.gempukku.lotro.logic.effects.PlayoutDecisionEffect;
-import com.gempukku.lotro.logic.effects.StackActionEffect;
-import com.gempukku.lotro.logic.timing.Effect;
-import com.gempukku.lotro.logic.timing.UnrespondableEffect;
+import com.google.common.base.Predicates;
import org.json.simple.JSONObject;
public class PreventableAppenderProducer implements EffectAppenderProducer {
@@ -37,87 +31,6 @@ public class PreventableAppenderProducer implements EffectAppenderProducer {
final EffectAppender[] costAppenders = environment.getEffectAppenderFactory().getEffectAppenders(costArray, environment);
final EffectAppender[] insteadAppenders = environment.getEffectAppenderFactory().getEffectAppenders(insteadArray, environment);
- return new DelayedAppender() {
- @Override
- protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
- if (areCostsPlayable(actionContext)) {
- final String preventingPlayer = preventingPlayerSource.getPlayer(actionContext);
-
- String textToUse = GameUtils.substituteText(text, actionContext);
-
- SubAction subAction = new SubAction(action);
- subAction.appendEffect(
- new PlayoutDecisionEffect(preventingPlayer,
- new YesNoDecision(textToUse) {
- @Override
- protected void yes() {
- actionContext.getGame().getGameState().sendMessage(GameUtils.substituteText("{" + player + "} chooses to prevent.", actionContext));
- DelegateActionContext delegate = new DelegateActionContext(actionContext,
- preventingPlayer, actionContext.getGame(), actionContext.getSource(), actionContext.getEffectResult(),
- actionContext.getEffect());
- for (EffectAppender costAppender : costAppenders)
- costAppender.appendEffect(false, subAction, delegate);
-
- subAction.appendEffect(
- new UnrespondableEffect() {
- @Override
- protected void doPlayEffect(LotroGame game) {
- // If the prevention was not carried out, need to do the original action anyway
- if (!subAction.wasCarriedOut()) {
- game.getGameState().sendMessage(GameUtils.substituteText("{" + player + "} attempted to prevent, but could not carry it out.", actionContext));
- for (EffectAppender effectAppender : effectAppenders)
- effectAppender.appendEffect(false, subAction, actionContext);
- } else {
- for (EffectAppender insteadAppender : insteadAppenders) {
- insteadAppender.appendEffect(false, subAction, actionContext);
- }
- }
- }
-
- @Override
- public boolean wasCarriedOut() {
- // Cheating a bit, we need to check if the preventing effect was carried out,
- // but have no way of doing this, as we can do that through subAction only,
- // and this checking effect should be ALWAYS considered fine, even before it
- // was done
- return true;
- }
- });
- }
-
- @Override
- protected void no() {
- actionContext.getGame().getGameState().sendMessage(GameUtils.substituteText("{" + player + "} decides not to prevent.", actionContext));
- for (EffectAppender effectAppender : effectAppenders)
- effectAppender.appendEffect(false, subAction, actionContext);
- }
- }));
- return new StackActionEffect(subAction);
- } else {
- SubAction subAction = new SubAction(action);
- for (EffectAppender effectAppender : effectAppenders)
- effectAppender.appendEffect(false, subAction, actionContext);
- return new StackActionEffect(subAction);
- }
- }
-
- private boolean areCostsPlayable(ActionContext actionContext) {
- for (EffectAppender costAppender : costAppenders) {
- if (!costAppender.isPlayableInFull(actionContext))
- return false;
- }
- return true;
- }
-
- @Override
- public boolean isPlayableInFull(ActionContext actionContext) {
- for (EffectAppender effectAppender : effectAppenders) {
- if (!effectAppender.isPlayableInFull(actionContext))
- return false;
- }
-
- return true;
- }
- };
+ return new PreventableEffectAppender(preventingPlayerSource, text, Predicates.alwaysTrue(), costAppenders, effectAppenders, insteadAppenders);
}
}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PreventableEffectAppender.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PreventableEffectAppender.java
new file mode 100644
index 000000000..2c0e93c47
--- /dev/null
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/PreventableEffectAppender.java
@@ -0,0 +1,106 @@
+package com.gempukku.lotro.cards.build.field.effect.appender;
+
+import com.gempukku.lotro.cards.build.ActionContext;
+import com.gempukku.lotro.cards.build.DelegateActionContext;
+import com.gempukku.lotro.cards.build.PlayerSource;
+import com.gempukku.lotro.cards.build.field.effect.EffectAppender;
+import com.gempukku.lotro.game.state.LotroGame;
+import com.gempukku.lotro.logic.GameUtils;
+import com.gempukku.lotro.logic.actions.CostToEffectAction;
+import com.gempukku.lotro.logic.actions.SubAction;
+import com.gempukku.lotro.logic.decisions.YesNoDecision;
+import com.gempukku.lotro.logic.effects.PlayoutDecisionEffect;
+import com.gempukku.lotro.logic.effects.StackActionEffect;
+import com.gempukku.lotro.logic.timing.Effect;
+import com.gempukku.lotro.logic.timing.UnrespondableEffect;
+
+import java.util.function.Predicate;
+
+public class PreventableEffectAppender extends DelayedAppender {
+ private PlayerSource preventingPlayer;
+ private String preventText;
+ private Predicate preventingPredicate;
+ private EffectAppender[] costAppenders;
+ private EffectAppender[] effectAppenders;
+ private EffectAppender[] insteadAppenders;
+
+ public PreventableEffectAppender(PlayerSource preventingPlayer, String preventText, Predicate preventingPredicate,
+ EffectAppender[] costAppenders, EffectAppender[] effectAppenders, EffectAppender[] insteadAppenders) {
+ this.preventingPlayer = preventingPlayer;
+ this.preventText = preventText;
+ this.preventingPredicate = preventingPredicate;
+ this.costAppenders = costAppenders;
+ this.effectAppenders = effectAppenders;
+ this.insteadAppenders = insteadAppenders;
+ }
+
+ @Override
+ protected Effect createEffect(boolean cost, CostToEffectAction action, ActionContext actionContext) {
+ String textToUse = GameUtils.substituteText(preventText, actionContext);
+ String preventingPlayerId = preventingPlayer.getPlayer(actionContext);
+
+ DelegateActionContext preventCostActionContext = new DelegateActionContext(actionContext, preventingPlayerId, actionContext.getGame(), actionContext.getSource(), actionContext.getEffectResult(), actionContext.getEffect());
+
+ if (preventingPredicate.test(actionContext) && areCostsPlayable(preventCostActionContext)) {
+ SubAction subAction = new SubAction(action);
+ subAction.appendEffect(new PlayoutDecisionEffect(preventingPlayerId, new YesNoDecision(textToUse) {
+ @Override
+ protected void yes() {
+ actionContext.getGame().getGameState().sendMessage(GameUtils.substituteText(preventingPlayerId + " chooses to prevent.", actionContext));
+ for (EffectAppender costAppender : costAppenders)
+ costAppender.appendEffect(false, subAction, preventCostActionContext);
+
+ subAction.appendEffect(new UnrespondableEffect() {
+ @Override
+ protected void doPlayEffect(LotroGame game) {
+ // If the prevention was not carried out, need to do the original action anyway
+ if (!subAction.wasCarriedOut()) {
+ game.getGameState().sendMessage(GameUtils.substituteText(preventingPlayerId + " attempted to prevent, but could not carry it out.", actionContext));
+ for (EffectAppender effectAppender : effectAppenders)
+ effectAppender.appendEffect(false, subAction, actionContext);
+ } else {
+ for (EffectAppender insteadAppender : insteadAppenders) {
+ insteadAppender.appendEffect(false, subAction, preventCostActionContext);
+ }
+ }
+ }
+
+ @Override
+ public boolean wasCarriedOut() {
+ return true;
+ }
+ });
+ }
+
+ @Override
+ protected void no() {
+ actionContext.getGame().getGameState().sendMessage(GameUtils.substituteText(preventingPlayerId + " decides not to prevent.", actionContext));
+ for (EffectAppender effectAppender : effectAppenders)
+ effectAppender.appendEffect(false, subAction, actionContext);
+ }
+ }));
+ return new StackActionEffect(subAction);
+ } else {
+ SubAction subAction = new SubAction(action);
+ for (EffectAppender effectAppender : effectAppenders)
+ effectAppender.appendEffect(false, subAction, actionContext);
+ return new StackActionEffect(subAction);
+ }
+ }
+
+ private boolean areCostsPlayable(ActionContext actionContext) {
+ for (EffectAppender costAppender : costAppenders) {
+ if (!costAppender.isPlayableInFull(actionContext)) return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean isPlayableInFull(ActionContext actionContext) {
+ for (EffectAppender effectAppender : effectAppenders) {
+ if (!effectAppender.isPlayableInFull(actionContext)) return false;
+ }
+
+ return true;
+ }
+}
diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/resolver/PlayerResolver.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/resolver/PlayerResolver.java
index 4ad0c9e4a..b30164617 100644
--- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/resolver/PlayerResolver.java
+++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/cards/build/field/effect/appender/resolver/PlayerResolver.java
@@ -11,7 +11,6 @@ import java.util.Locale;
public class PlayerResolver {
public static PlayerSource resolvePlayer(String type, CardGenerationEnvironment environment) throws InvalidCardDefinitionException {
-
if (type.equalsIgnoreCase("you"))
return ActionContext::getPerformingPlayer;
if (type.equalsIgnoreCase("owner"))