From d2c05f6045ba46e408b23f095d7afa175b1c41c2 Mon Sep 17 00:00:00 2001 From: Christian 'ketura' McCarty Date: Fri, 22 Nov 2024 20:07:59 -0600 Subject: [PATCH] Adding greyed-out styling for inactive cards - Inactive cards are now automatically greyed out whenever a new turn starts - Fixed the deck inspection window not showing when your deck play operation failed (such as when using Bridge of Khazad-dum with no Balrog) --- .../src/main/web/css/gemp-001/game.css | 8 ++++++ .../src/main/web/js/gemp-022/cards/Card.js | 5 +++- .../main/web/js/gemp-022/cards/CardDisplay.js | 4 +++ .../main/web/js/gemp-022/gameAnimations.js | 28 +++++++++++++++++-- .../communication/GameStateListener.java | 3 +- .../game/state/GameCommunicationChannel.java | 7 +++-- .../gempukku/lotro/game/state/GameState.java | 17 +++++++++-- .../choose/ChooseCardsFromDeckEffect.java | 26 +++++++++++++++-- .../at/effects/RemoveFromGameAtTest.java | 1 + .../official/set01/Card_01_087_Tests.java | 2 +- 10 files changed, 87 insertions(+), 14 deletions(-) diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/game.css b/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/game.css index d5e0f12c0..cbf992168 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/game.css +++ b/gemp-lotr/gemp-lotr-async/src/main/web/css/gemp-001/game.css @@ -473,4 +473,12 @@ ul.ui-tabs-nav { .ui-button-icon-primary.ui-icon.ui-icon-search, .ui-button-icon-primary.ui-icon.ui-icon-circle-close { margin-left:4px; +} + +.card.inactive img { + filter: grayscale(0.7) contrast(0.5) brightness(0.6); +} + +.card.inactive tokenOverlay { + color: #777777; } \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/cards/Card.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/cards/Card.js index f50914d96..00b8d30d1 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/cards/Card.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/cards/Card.js @@ -505,6 +505,7 @@ class Card { return foil; } + //Used for representing physical cards static CreateCardDiv(image, testingText, text, foil, tokens, noBorder, errata, incomplete) { var cardDiv = $("
" + ((text != null) ? text : "") + "
"); @@ -534,7 +535,7 @@ class Card { // var collapsedDiv = $("
"); // cardDiv.append(collapsedDiv); - + if (tokens === undefined || tokens) { var overlayDiv = $("
"); cardDiv.append(overlayDiv); @@ -563,6 +564,7 @@ class Card { return cardDiv; } + //Used by non-game pages such as the deckbuilder and main hall static CreateFullCardDiv(image, testingText, foil, horizontal, noBorder) { var foilPresentation = Card.getFoilPresentation(); @@ -611,6 +613,7 @@ class Card { return cardDiv; } + //Used for ephemeral card displays such as event display or the "affected by card" effect static CreateSimpleCardDiv(image, testingText, foil, incomplete, borderWidth) { var cardDiv = $("
"); diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/cards/CardDisplay.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/cards/CardDisplay.js index 0b1810dcf..2738e25e3 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/cards/CardDisplay.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/cards/CardDisplay.js @@ -97,6 +97,9 @@ class CardDisplay { if(card !== undefined && maxWidth !== undefined && maxHeight !== undefined) { this.reloadFromCard(card, maxWidth, maxHeight); } + else { + this.baseDiv.data("card", {}); + } } clear() { @@ -115,6 +118,7 @@ class CardDisplay { } reloadFromCard(card, maxWidth, maxHeight, noborder) { + this.baseDiv.data("card", card); this.currentBP = card.blueprintId; this.frontside = card.imageUrl; if(!this.frontside) { diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/gameAnimations.js b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/gameAnimations.js index 34ed26a99..5abaaecd5 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/gameAnimations.js +++ b/gemp-lotr/gemp-lotr-async/src/main/web/js/gemp-022/gameAnimations.js @@ -60,6 +60,9 @@ var GameAnimations = Class.extend({ if (this.game.spectatorMode || this.game.replayMode || (participantId != this.game.bottomPlayerId)) { var card = new Card(blueprintId, testingText, backSideTestingText, "ANIMATION", "anim", participantId); var cardDiv = Card.CreateSimpleCardDiv(card.imageUrl, card.testingText, card.foil, card.incomplete, 16); + + // var display = new CardDisplay(card, $("#main").width() / 2, $("#main").width() / 2) + // var cardDiv = display.baseDiv; $("#main").queue( function (next) { @@ -137,7 +140,10 @@ var GameAnimations = Class.extend({ var card = new Card(blueprintId, testingText, backSideTestingText, "ANIMATION", "anim" + i, participantId); var cardDiv = Card.CreateSimpleCardDiv(card.imageUrl, card.testingText, card.foil, card.incomplete, 16); - + + // var display = new CardDisplay(card, $("#main").width() / 2, $("#main").width() / 2) + // var cardDiv = display.baseDiv; + var targetCard = $(".card:cardId(" + targetCardId + ")"); if (targetCard.length > 0) { cardDiv.data("card", card); @@ -433,10 +439,13 @@ var GameAnimations = Class.extend({ if (card.length > 0) { var cardData = card.data("card"); + if (cardData.zone == "ATTACHED" || cardData.zone == "STACKED") { $(".card").each( function () { var cardData = $(this).data("card"); + if(!cardData || !cardData.attachedCards) + return; var index = -1; for (var i = 0; i < cardData.attachedCards.length; i++) if (cardData.attachedCards[i].data("card").cardId == cardId) { @@ -493,6 +502,7 @@ var GameAnimations = Class.extend({ var that = this; $("#main").queue( function (next) { + var inactiveCardIds = element.getAttribute("otherCardIds"); var playerId = element.getAttribute("participantId"); var playerIndex = that.game.getPlayerIndex(playerId); @@ -505,6 +515,20 @@ var GameAnimations = Class.extend({ $(this).removeClass("current"); }); that.game.advPathGroup.setCurrentPlayerIndex(playerIndex); + + if(inactiveCardIds) { + var ids = inactiveCardIds.split(","); + + $(".card").each(function () { + var cardData = $(this).data("card"); + if ($.inArray(cardData.cardId, ids) > -1) { + $(this).addClass("inactive"); + } + else { + $(this).removeClass("inactive"); + } + }); + } next(); }); @@ -658,7 +682,7 @@ var GameAnimations = Class.extend({ $(".card").each(function () { var cardData = $(this).data("card"); - if (cardData.skirmish == true) { + if (cardData && cardData.skirmish == true) { delete cardData.skirmish; } }); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/communication/GameStateListener.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/communication/GameStateListener.java index e75855a06..f1d3ea0de 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/communication/GameStateListener.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/communication/GameStateListener.java @@ -8,7 +8,6 @@ import com.gempukku.lotro.logic.timing.GameStats; import java.util.Collection; import java.util.List; -import java.util.Map; import java.util.Set; public interface GameStateListener { @@ -26,7 +25,7 @@ public interface GameStateListener { void setTwilight(int twilightPool); - void setCurrentPlayerId(String playerId); + void setCurrentPlayerId(String playerId, Set inactiveCards); String getAssignedPlayerId(); void setCurrentPhase(String currentPhase); diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameCommunicationChannel.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameCommunicationChannel.java index 419f544f1..99b69005c 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameCommunicationChannel.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameCommunicationChannel.java @@ -10,7 +10,6 @@ import com.gempukku.lotro.logic.timing.GameStats; import com.gempukku.polling.LongPollableResource; import com.gempukku.polling.WaitingRequest; -import java.time.LocalDateTime; import java.util.*; import static com.gempukku.lotro.game.state.GameEvent.Type.*; @@ -167,8 +166,10 @@ public class GameCommunicationChannel implements GameStateListener, LongPollable } @Override - public void setCurrentPlayerId(String currentPlayerId) { - appendEvent(new GameEvent(TURN_CHANGE).participantId(currentPlayerId)); + public void setCurrentPlayerId(String currentPlayerId, Set inactiveCards) { + appendEvent(new GameEvent(TURN_CHANGE) + .participantId(currentPlayerId) + .otherCardIds(getCardIds(inactiveCards))); } @Override diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameState.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameState.java index 98599236a..f8303b83e 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameState.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/state/GameState.java @@ -13,6 +13,7 @@ import org.apache.logging.log4j.Logger; import java.security.InvalidParameterException; import java.util.*; import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Collectors; public class GameState { private static final Logger _log = LogManager.getLogger(GameState.class); @@ -230,7 +231,7 @@ public class GameState { if (_playerOrder != null) { listener.initializeBoard(_playerOrder.getAllPlayers(), _format.discardPileIsPublic()); if (_currentPlayerId != null) - listener.setCurrentPlayerId(_currentPlayerId); + listener.setCurrentPlayerId(_currentPlayerId, Collections.emptySet()); if (_currentPhase != null) listener.setCurrentPhase(getPhaseString()); listener.setTwilight(_twilightPool); @@ -301,6 +302,9 @@ public class GameState { } listener.sendGameStats(gameStats); + + if (_currentPlayerId != null) + listener.setCurrentPlayerId(_currentPlayerId, getInactiveCards()); } for (String lastMessage : _lastMessages) @@ -821,8 +825,15 @@ public class GameState { _moveCount = 0; _fierceSkirmishes = false; - for (GameStateListener listener : getAllGameStateListeners()) - listener.setCurrentPlayerId(_currentPlayerId); + for (var listener : getAllGameStateListeners()) { + listener.setCurrentPlayerId(_currentPlayerId, getInactiveCards()); + } + } + + public Set getInactiveCards() { + return _inPlay.stream() + .filter(x -> !isCardInPlayActive(x)) + .collect(Collectors.toSet()); } public int getTurnNumber() { diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/choose/ChooseCardsFromDeckEffect.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/choose/ChooseCardsFromDeckEffect.java index 1da3dbfb9..0ab9f68a0 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/choose/ChooseCardsFromDeckEffect.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/logic/effects/choose/ChooseCardsFromDeckEffect.java @@ -55,9 +55,31 @@ public abstract class ChooseCardsFromDeckEffect extends AbstractEffect { int minimum = Math.min(_minimum, cards.size()); if (_maximum == 0) { - cardsSelected(game, Collections.emptySet()); + if (showAll) { + game.getUserFeedback().sendAwaitingDecision(_playerId, + new ArbitraryCardsSelectionDecision(2, "You may inspect the contents of your deck while retrieving cards", game.getGameState().getDeck(_deckId), new LinkedList<>(), 0, 0) { + @Override + public void decisionMade(String result2) throws DecisionResultInvalidException { + cardsSelected(game, Collections.emptySet()); + } + }); + } + else { + cardsSelected(game, Collections.emptySet()); + } } else if (cards.size() == minimum) { - cardsSelected(game, cards); + if (showAll) { + game.getUserFeedback().sendAwaitingDecision(_playerId, + new ArbitraryCardsSelectionDecision(2, "You may inspect the contents of your deck while retrieving cards", game.getGameState().getDeck(_deckId), new LinkedList<>(), 0, 0) { + @Override + public void decisionMade(String result2) throws DecisionResultInvalidException { + cardsSelected(game, cards); + } + }); + } + else { + cardsSelected(game, cards); + } } else { game.getUserFeedback().sendAwaitingDecision(_playerId, new ArbitraryCardsSelectionDecision(1, "Choose cards from deck", new LinkedList<>(cards), minimum, _maximum) { diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/effects/RemoveFromGameAtTest.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/effects/RemoveFromGameAtTest.java index 50f507a4a..6bf52c656 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/effects/RemoveFromGameAtTest.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/at/effects/RemoveFromGameAtTest.java @@ -38,6 +38,7 @@ public class RemoveFromGameAtTest extends AbstractAtTest { pass(P2); selectYes(P1); selectCardAction(P2, grond); + pass(P2); //dismiss revealed deck cards assertEquals(Zone.REMOVED, gimliInDeck.getZone()); assertEquals(Zone.REMOVED, aragornInDeck.getZone()); } diff --git a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_087_Tests.java b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_087_Tests.java index d9a45e9db..d6c6e82f7 100644 --- a/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_087_Tests.java +++ b/gemp-lotr/gemp-lotr-server/src/test/java/com/gempukku/lotro/cards/official/set01/Card_01_087_Tests.java @@ -131,7 +131,7 @@ public class Card_01_087_Tests assertEquals(Zone.HAND, bb.getZone()); scn.FreepsPlayCard(late); - + scn.FreepsDismissRevealedCards(); assertEquals(Zone.DISCARD, late.getZone()); } }