Merge branch 'grand-card-rework' into v2-cards

This commit is contained in:
Christian 'ketura' McCarty
2024-06-15 12:27:34 -05:00
15 changed files with 306 additions and 393 deletions

View File

@@ -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)
}
}
}
]
}
}
]
}

View File

@@ -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: <b>Search</b>.<br><b>Assignment:</b> 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: <b>Damage +1</b>.<br><b>Assignment:</b> Exert Orthanc Champion to assign it to an unbound companion. That companion may exert to prevent this.

View File

@@ -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: <b>Southron</b>. <b>Ambush (1)</b>.<br><b>Assignment:</b> 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)
}
}
]
}

View File

@@ -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))
}
}
}
{

View File

@@ -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
}
}
}
]

View File

@@ -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

View File

@@ -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
}
}
]
}

View File

@@ -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)
}
}
}
]
}

View File

@@ -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))
}
}
]
}
]

View File

@@ -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)
}
}
}
}
]
}
]

View File

@@ -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));
}
}

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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<ActionContext> preventingPredicate;
private EffectAppender[] costAppenders;
private EffectAppender[] effectAppenders;
private EffectAppender[] insteadAppenders;
public PreventableEffectAppender(PlayerSource preventingPlayer, String preventText, Predicate<ActionContext> 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;
}
}

View File

@@ -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"))