From 45161fb0ed5fbf4bc677b4e450ed86f89900023d Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Fri, 8 Nov 2024 16:47:58 -0600 Subject: [PATCH] Assignment fixes and others - (Hopefully) Fixed forced assignment actions causing an incorrect message about too many assigned minions that soft-locks the game - Syntax fix for previous Siege Engine fix - Fixed Sam and Merry errata not being properly limited to once per turn - Fixed a front-end error related to the card display rework --- .../src/main/web/js/gemp-022/gameUi.js | 17 ++++++++ .../cards/official/set05/set05-Isengard.hjson | 2 +- .../cards/official/set07/set07-Sauron.hjson | 2 +- .../pc/errata/set01/set01-Shire-errata.hjson | 1 + .../pc/errata/set02/set02-Shire-errata.hjson | 1 + .../appender/AssignFpCharacterToSkirmish.java | 10 ++--- .../com/gempukku/lotro/filters/Filters.java | 14 +++---- ...PeoplePlayerAssignsMinionsGameProcess.java | 6 +-- .../official/set01/Card_01_262_Tests.java | 40 ++++++++++++++----- 9 files changed, 66 insertions(+), 27 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/gameUi.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/gameUi.js index f8f347748..aed25ee88 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/gameUi.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/gameUi.js @@ -2079,6 +2079,15 @@ var GempLotrGameUI = Class.extend({ var actionId = actionIds[i]; var actionText = actionTexts[i]; var blueprintId = blueprintIds[i]; + + var testingText = testingTexts[i]; + if (testingText == "null") { + testingText = null; + } + var backSideTestingText = backSideTestingTexts[i]; + if (backSideTestingText == "null") { + backSideTestingText = null; + } if (blueprintId == "inPlay") { var cardIdElem = $(".card:cardId(" + cardId + ")"); @@ -2227,6 +2236,14 @@ var GempLotrGameUI = Class.extend({ for (var i = 0; i < blueprintIds.length; i++) { var blueprintId = blueprintIds[i]; + var testingText = testingTexts[i]; + if (testingText == "null") { + testingText = null; + } + var backSideTestingText = backSideTestingTexts[i]; + if (backSideTestingText == "null") { + backSideTestingText = null; + } cardIds.push("temp" + i); var card = new Card(blueprintId, testingText, backSideTestingText, "SPECIAL", "temp" + i, null); diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set05/set05-Isengard.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set05/set05-Isengard.hjson index 404af1b5b..438fba8a0 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set05/set05-Isengard.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set05/set05-Isengard.hjson @@ -920,7 +920,7 @@ effect: { type: AddCultureTokens culture: isengard - select: machine + select: choose(machine) } } { diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set07/set07-Sauron.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set07/set07-Sauron.hjson index 136894a1d..910306714 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set07/set07-Sauron.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/official/set07/set07-Sauron.hjson @@ -1196,7 +1196,7 @@ type: assignFpCharacterToSkirmish fpCharacter: choose(ringBearer) minion: self - ignoreUnassigned: true + ignoreExistingAssignments: true } } ] diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set01/set01-Shire-errata.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set01/set01-Shire-errata.hjson index 03dfd15aa..18e6c419b 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set01/set01-Shire-errata.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set01/set01-Shire-errata.hjson @@ -85,6 +85,7 @@ resistance: 5 effects: { type: activated + limitPerTurn: 1 phase: fellowship cost: { type: exert diff --git a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set02/set02-Shire-errata.hjson b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set02/set02-Shire-errata.hjson index c7c1195ec..f6531b7be 100644 --- a/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set02/set02-Shire-errata.hjson +++ b/gemp-lotr/gemp-lotr-cards/src/main/resources/cards/unofficial/pc/errata/set02/set02-Shire-errata.hjson @@ -73,6 +73,7 @@ resistance: 6 effects: { type: activated + limitPerTurn: 1 phase: fellowship cost: { type: exert 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 9ea16e7dc..d4e51f5b7 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 @@ -21,7 +21,7 @@ import java.util.Collection; public class AssignFpCharacterToSkirmish implements EffectAppenderProducer { @Override public EffectAppender createEffectAppender(JSONObject effectObject, CardGenerationEnvironment environment) throws InvalidCardDefinitionException { - FieldUtils.validateAllowedFields(effectObject, "player", "fpCharacter", "minion", "memorizeMinion", "memorizeFPCharacter", "ignoreUnassigned", "preventCost", "preventText", "insteadEffect"); + FieldUtils.validateAllowedFields(effectObject, "player", "fpCharacter", "minion", "memorizeMinion", "memorizeFPCharacter", "ignoreExistingAssignments", "preventCost", "preventText", "insteadEffect"); final String player = FieldUtils.getString(effectObject.get("player"), "player", "you"); final String fpCharacter = FieldUtils.getString(effectObject.get("fpCharacter"), "fpCharacter", "choose(any)"); @@ -39,7 +39,7 @@ public class AssignFpCharacterToSkirmish implements EffectAppenderProducer { 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); + final boolean ignoreExistingAssignments = FieldUtils.getBoolean(effectObject.get("ignoreExistingAssignments"), "ignoreExistingAssignments", false); final PlayerSource playerSource = PlayerResolver.resolvePlayer(player); @@ -52,7 +52,7 @@ public class AssignFpCharacterToSkirmish implements EffectAppenderProducer { final String assigningPlayer = playerSource.getPlayer(actionContext); Side assigningSide = GameUtils.getSide(actionContext.getGame(), assigningPlayer); final Filterable filter = minionFilter.getFilterable(actionContext); - return Filters.assignableToSkirmishAgainst(assigningSide, filter, ignoreUnassigned, false); + return Filters.assignableToSkirmishAgainst(assigningSide, filter, ignoreExistingAssignments, false); }, fpCharacterMemory, player, "Choose character to assign to skirmish", environment)); result.addEffectAppender( CardResolver.resolveCard(minion, @@ -60,7 +60,7 @@ public class AssignFpCharacterToSkirmish implements EffectAppenderProducer { final String assigningPlayer = playerSource.getPlayer(actionContext); Side assigningSide = GameUtils.getSide(actionContext.getGame(), assigningPlayer); final Collection fpChar = actionContext.getCardsFromMemory(fpCharacterMemory); - return Filters.assignableToSkirmishAgainst(assigningSide, Filters.in(fpChar), ignoreUnassigned, false); + return Filters.assignableToSkirmishAgainst(assigningSide, Filters.in(fpChar), ignoreExistingAssignments, false); }, minionMemory, player, "Choose minion to assign to character", environment)); DelayedAppender assignAppender = new DelayedAppender() { @@ -71,7 +71,7 @@ public class AssignFpCharacterToSkirmish implements EffectAppenderProducer { final Collection 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); + effect.setIgnoreSingleMinionRestriction(ignoreExistingAssignments); return effect; } else { return null; diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java index 2f12c3c22..3d3d9d6fc 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/filters/Filters.java @@ -194,13 +194,13 @@ public class Filters { return assignableToSkirmishAgainst(assignedBySide, againstFilter, false, false); } - public static Filter assignableToSkirmishAgainst(final Side assignedBySide, final Filterable againstFilter, final boolean ignoreUnassigned, final boolean allowAllyToSkirmish) { + public static Filter assignableToSkirmishAgainst(final Side assignedBySide, final Filterable againstFilter, final boolean ignoreExistingAssignments, final boolean allowAllyToSkirmish) { return Filters.and( - assignableToSkirmish(assignedBySide, ignoreUnassigned, allowAllyToSkirmish), + assignableToSkirmish(assignedBySide, ignoreExistingAssignments, allowAllyToSkirmish), (Filter) (game, physicalCard) -> { for (PhysicalCard card : Filters.filterActive(game, againstFilter)) { if (card.getBlueprint().getSide() != physicalCard.getBlueprint().getSide() - && Filters.assignableToSkirmish(assignedBySide, ignoreUnassigned, allowAllyToSkirmish).accepts(game, card)) { + && Filters.assignableToSkirmish(assignedBySide, ignoreExistingAssignments, allowAllyToSkirmish).accepts(game, card)) { Map> thisAssignment = new HashMap<>(); if (card.getBlueprint().getSide() == Side.FREE_PEOPLE) { if (thisAssignment.containsKey(card)) @@ -222,7 +222,7 @@ public class Filters { }); } - public static Filter assignableToSkirmish(final Side assignedBySide, final boolean ignoreUnassigned, final boolean allowAllyToSkirmish) { + public static Filter assignableToSkirmish(final Side assignedBySide, final boolean ignoreExistingAssignments, final boolean allowAllyToSkirmish) { Filter assignableFilter = Filters.or( Filters.and( CardType.ALLY, @@ -253,9 +253,9 @@ public class Filters { return Filters.and( assignableFilter, (Filter) (game, physicalCard) -> { - if (!ignoreUnassigned) { - boolean notAssignedToSkirmish = Filters.notAssignedToSkirmish.accepts(game, physicalCard); - if (!notAssignedToSkirmish) + if (!ignoreExistingAssignments) { + boolean assignedToSkirmish = Filters.assignedToSkirmish.accepts(game, physicalCard); + if (assignedToSkirmish) return false; } return game.getModifiersQuerying().canBeAssignedToSkirmish(game, assignedBySide, physicalCard); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/assign/FreePeoplePlayerAssignsMinionsGameProcess.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/assign/FreePeoplePlayerAssignsMinionsGameProcess.java index e5a6ad38e..e4924ae6e 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/assign/FreePeoplePlayerAssignsMinionsGameProcess.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/timing/processes/turn/assign/FreePeoplePlayerAssignsMinionsGameProcess.java @@ -44,14 +44,14 @@ public class FreePeoplePlayerAssignsMinionsGameProcess implements GameProcess { protected void doPlayEffect(final LotroGame game) { final GameState gameState = game.getGameState(); - final Collection minions = Filters.filterActive(game, CardType.MINION, Filters.assignableToSkirmish(Side.FREE_PEOPLE, true, false)); + final Collection minions = Filters.filterActive(game, CardType.MINION, Filters.assignableToSkirmish(Side.FREE_PEOPLE, false, false)); if (minions.size() > 0) { final Collection freePeopleTargets = Filters.filterActive(game, Filters.and( Filters.or( CardType.COMPANION, CardType.ALLY), - Filters.assignableToSkirmish(Side.FREE_PEOPLE, true, false))); + Filters.assignableToSkirmish(Side.FREE_PEOPLE, false, false))); game.getUserFeedback().sendAwaitingDecision(gameState.getCurrentPlayerId(), @@ -60,7 +60,7 @@ public class FreePeoplePlayerAssignsMinionsGameProcess implements GameProcess { public void decisionMade(String result) throws DecisionResultInvalidException { Map> assignments = getAssignmentsBasedOnResponse(result); - Set unassignedMinions = new HashSet<>(Filters.filterActive(game, CardType.MINION)); + Set unassignedMinions = new HashSet<>(Filters.filterActive(game, CardType.MINION, Filters.assignableToSkirmish(Side.FREE_PEOPLE, false, false))); // Validate minion count (Defender) for (PhysicalCard freeCard : assignments.keySet()) { Set minionsAssigned = assignments.get(freeCard); diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_262_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_262_Tests.java index b6c8cff46..9be5e8004 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_262_Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_262_Tests.java @@ -17,8 +17,9 @@ public class Card_01_262_Tests return new GenericCardTestHelper( new HashMap<>() {{ - put("card", "1_262"); - // put other cards in here as needed for the test case + put("assassin", "1_262"); + put("runner", "1_178"); + put("sam", "1_310"); }}, GenericCardTestHelper.FellowshipSites, GenericCardTestHelper.FOTRFrodo, @@ -46,7 +47,7 @@ public class Card_01_262_Tests var scn = GetScenario(); - var card = scn.GetFreepsCard("card"); + var card = scn.GetFreepsCard("assassin"); assertEquals("Orc Assassin", card.getBlueprint().getTitle()); assertNull(card.getBlueprint().getSubtitle()); @@ -62,18 +63,37 @@ public class Card_01_262_Tests assertEquals(6, card.getBlueprint().getSiteNumber()); } - // Uncomment any @Test markers below once this is ready to be used - //@Test - public void OrcAssassinTest1() throws DecisionResultInvalidException, CardNotFoundException { + @Test + public void OrcAssassinDoesNotInterruptSkirmishesAfterUsingAssignmentAbility() throws DecisionResultInvalidException, CardNotFoundException { //Pre-game setup var scn = GetScenario(); - var card = scn.GetFreepsCard("card"); - scn.FreepsMoveCardToHand(card); + var assassin = scn.GetShadowCard("assassin"); + var runner = scn.GetShadowCard("runner"); + scn.ShadowMoveCharToTable(assassin, runner); + + var frodo = scn.GetRingBearer(); + var sam = scn.GetFreepsCard("sam"); + scn.FreepsMoveCharToTable(sam); scn.StartGame(); - scn.FreepsPlayCard(card); - assertEquals(2, scn.GetTwilight()); + scn.SkipToPhase(Phase.ASSIGNMENT); + scn.FreepsPassCurrentPhaseAction(); + + assertTrue(scn.ShadowActionAvailable(assassin)); + scn.ShadowUseCardAction(assassin); + assertEquals(2, scn.GetFreepsCardChoiceCount()); + + assertTrue(scn.CanBeAssigned(sam)); + scn.FreepsChooseCard(sam); + assertTrue(scn.IsCharAssigned(sam)); + assertTrue(scn.IsCharAssigned(assassin)); + + scn.PassCurrentPhaseActions(); + scn.FreepsAssignToMinions(frodo, runner); + // If beginning skirmishes now fails, then there is some dangling minion that Gemp thinks + // is unassigned, which isn't right. + scn.FreepsResolveSkirmish(sam); } }