From 2c70b8b7e0f56bffca947682dc749b62e13337b9 Mon Sep 17 00:00:00 2001 From: Alessandro Coli Date: Thu, 21 Nov 2019 16:49:50 +0100 Subject: [PATCH] End of the stack modal panel implementation, rollback about the Wild Quests implementation --- .../java/forge/screens/match/CMatchUI.java | 247 ++++++++++-------- .../forge/quest/QuestEventDifficulty.java | 3 +- .../forge/quest/QuestEventDuelManager.java | 6 - .../java/forge/quest/io/QuestDuelReader.java | 73 +----- 4 files changed, 152 insertions(+), 177 deletions(-) diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java b/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java index 08735225c1b..bf5ea0d7a8a 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java @@ -51,10 +51,12 @@ import forge.LobbyPlayer; import forge.Singletons; import forge.StaticData; import forge.assets.FSkinProp; +import forge.card.CardStateName; import forge.control.KeyboardShortcuts; import forge.deck.CardPool; import forge.deck.Deck; import forge.deckchooser.FDeckViewer; +import forge.game.GameEntity; import forge.game.GameEntityView; import forge.game.GameView; import forge.game.ability.AbilityKey; @@ -70,6 +72,7 @@ import forge.game.player.DelayedReveal; import forge.game.player.IHasIcon; import forge.game.player.PlayerView; import forge.game.spellability.SpellAbility; +import forge.game.spellability.SpellAbilityStackInstance; import forge.game.spellability.SpellAbilityView; import forge.game.spellability.StackItemView; import forge.game.spellability.TargetChoices; @@ -1213,114 +1216,68 @@ public final class CMatchUI if(stackIndex == nextNotifiableStackIndex) { // We can go and show the modal - StackItemView siv = event.si.getView(); - - String who = event.sa.getActivatingPlayer().getName(); - String action = event.sa.isSpell() ? " cast " : event.sa.isTrigger() ? " triggered " : " activated "; - String what = event.sa.getStackDescription().startsWith("Morph ") ? "Morph" : event.sa.getHostCard().toString(); - - StringBuilder sb = new StringBuilder(); - sb.append(who).append(action).append(what); - - if (event.sa.getTargetRestrictions() != null) { - sb.append(" targeting "); - TargetChoices targets = event.si.getTargetChoices(); - sb.append(targets.getTargetedString()); - } - sb.append("."); - String message1 = sb.toString(); - String message2 = event.si.getStackDescription(); - String messageTotal = message1 + "\n\n" + message2; - - - int rotation = getRotation(event.sa.getCardView()); - - FImagePanel imagePanel = new FImagePanel(); - BufferedImage bufferedImage = FImageUtil.getImage(siv.getSourceCard().getCurrentState()); - imagePanel.setImage(bufferedImage, rotation, AutoSizeImageMode.SOURCE); - int imageWidth = 433; - int imageHeight = 600; - Dimension imagePanelDimension = new Dimension(imageWidth,imageHeight); - imagePanel.setMinimumSize(imagePanelDimension); - - final Dimension parentSize = JOptionPane.getRootFrame().getSize(); - Dimension maxSize = new Dimension(1400, parentSize.height - 100); + SpellAbility sa = event.sa; + SpellAbilityStackInstance si = event.si; MigLayout migLayout = new MigLayout("insets 15, left, gap 30, fill"); JPanel mainPanel = new JPanel(migLayout); + final Dimension parentSize = JOptionPane.getRootFrame().getSize(); + Dimension maxSize = new Dimension(1400, parentSize.height - 100); mainPanel.setMaximumSize(maxSize); - mainPanel.setOpaque(false); + mainPanel.setOpaque(false); + + // Big Image + addBigImageToStackModalPanel(mainPanel, si); - mainPanel.add(imagePanel, "cell 0 0, spany 3"); + // Text + addTextToStackModalPanel(mainPanel,sa,si); - final FTextArea prompt1 = new FTextArea(messageTotal); - prompt1.setFont(FSkin.getFont(21)); - prompt1.setAutoSize(true); - prompt1.setMinimumSize(new Dimension(475,200)); - mainPanel.add(prompt1, "cell 1 0, aligny top"); - - SpellAbility sourceSA = (SpellAbility) event.sa.getTriggeringObject(AbilityKey.SourceSA); + // Small images + int numSmallImages = 0; + + // If current effect is a triggered/activated ability of an enchantment card, I want to show the enchanted card + GameEntityView enchantedEntityView = null; + Card hostCard = sa.getHostCard(); + if(hostCard.isEnchantment()) { + GameEntity enchantedEntity = hostCard.getEntityAttachedTo(); + if(enchantedEntity != null) { + enchantedEntityView = enchantedEntity.getView(); + numSmallImages++; + } else if ((sa.getRootAbility() != null) + && (sa.getRootAbility().getPaidList("Sacrificed") != null) + && !sa.getRootAbility().getPaidList("Sacrificed").isEmpty()) { + // If the player activated its ability by sacrificing the enchantment, the enchantment has not anything attached anymore and the ex-enchanted card has to be searched in other ways.. for example, the green enchantment "Carapace" + enchantedEntity = sa.getRootAbility().getPaidList("Sacrificed").get(0).getEnchantingCard(); + if(enchantedEntity != null) { + enchantedEntityView = enchantedEntity.getView(); + numSmallImages++; + } + } + } + + // If current effect is a triggered ability, I want to show the triggering card if present + SpellAbility sourceSA = (SpellAbility) si.getTriggeringObject(AbilityKey.SourceSA); + CardView sourceCardView = null; if(sourceSA != null) { - // Current card is target of a triggered ability - CardView sourceCardView = sourceSA.getHostCard().getView(); - int currRotation = getRotation(sourceCardView); - FImagePanel targetPanel = new FImagePanel(); - bufferedImage = FImageUtil.getImage(sourceCardView.getCurrentState()); - targetPanel.setImage(bufferedImage, currRotation, AutoSizeImageMode.SOURCE); - imageWidth = 217; - imageHeight = 300; - Dimension targetPanelDimension = new Dimension(imageWidth,imageHeight); - targetPanel.setMinimumSize(targetPanelDimension); - mainPanel.add(targetPanel, "cell 1 1, aligny bottom"); - } else { - FCollectionView targetCards = CardView.getCollection(event.si.getTargetChoices().getTargetCards()); - - List targetSpellCards = new ArrayList(); - for(SpellAbility currSA : event.si.getTargetChoices().getTargetSpells()) { - CardView currCardView = currSA.getCardView(); - targetSpellCards.add(currCardView); - } - - FCollectionView targetPlayers = PlayerView.getCollection(event.si.getTargetChoices().getTargetPlayers()); - - int numTarget = targetCards.size() + targetSpellCards.size() + targetPlayers.size(); - - if(targetCards != null) { - for (CardView currCardView : targetCards) { - int currRotation = getRotation(currCardView); - FImagePanel targetPanel = new FImagePanel(); - bufferedImage = FImageUtil.getImage(currCardView.getCurrentState()); - targetPanel.setImage(bufferedImage, currRotation, AutoSizeImageMode.SOURCE); - imageWidth = 217; - imageHeight = 300; - Dimension targetPanelDimension = new Dimension(imageWidth,imageHeight); - targetPanel.setMinimumSize(targetPanelDimension); - mainPanel.add(targetPanel, "cell 1 1, split " + numTarget+ ", aligny bottom"); - } - } - if(targetSpellCards != null) { - for (CardView currCardView : targetSpellCards) { - int currRotation = getRotation(currCardView); - FImagePanel targetPanel = new FImagePanel(); - bufferedImage = FImageUtil.getImage(currCardView.getCurrentState()); - targetPanel.setImage(bufferedImage, currRotation, AutoSizeImageMode.SOURCE); - imageWidth = 217; - imageHeight = 300; - Dimension targetPanelDimension = new Dimension(imageWidth,imageHeight); - targetPanel.setMinimumSize(targetPanelDimension); - mainPanel.add(targetPanel, "cell 1 1, split " + numTarget+ ", aligny bottom"); - } - } - if(targetPlayers != null) { - for (PlayerView playerView : targetPlayers) { - SkinImage playerAvatar = getPlayerAvatar(playerView, 0); - final FLabel lblIcon = new FLabel.Builder().icon(playerAvatar).build(); - Dimension dimension = playerAvatar.getSizeForPaint(JOptionPane.getRootFrame().getGraphics()); - mainPanel.add(lblIcon, "cell 1 1, split " + numTarget+ ", w " + dimension.getWidth() + ", h " + dimension.getHeight() + ", aligny bottom"); - } - } - } - + sourceCardView = sourceSA.getHostCard().getView(); + numSmallImages++; + } + + // I also want to show each type of targets (both cards and players) + List targets = getTargets(si,new ArrayList()); + numSmallImages = numSmallImages + targets.size(); + + // Now I know how many small images - on to render them + if(enchantedEntityView != null) { + addSmallImageToStackModalPanel(enchantedEntityView,mainPanel,numSmallImages); + } + if(sourceCardView != null) { + addSmallImageToStackModalPanel(sourceCardView,mainPanel,numSmallImages); + } + for(GameEntityView gev : targets) { + addSmallImageToStackModalPanel(gev, mainPanel, numSmallImages); + } + FOptionPane.showOptionDialog(null, "Forge", null, mainPanel, ImmutableList.of("OK")); // here the user closed the modal - time to update the next notifiable stack index nextNotifiableStackIndex++; @@ -1340,6 +1297,90 @@ public final class CMatchUI } } + private List getTargets(SpellAbilityStackInstance si, List result){ + if(si == null) { + return result; + } else { + FCollectionView targetCards = CardView.getCollection(si.getTargetChoices().getTargetCards()); + for(CardView currCardView: targetCards) { + result.add(currCardView); + } + + for(SpellAbility currSA : si.getTargetChoices().getTargetSpells()) { + CardView currCardView = currSA.getCardView(); + result.add(currCardView); + } + + FCollectionView targetPlayers = PlayerView.getCollection(si.getTargetChoices().getTargetPlayers()); + for(PlayerView currPlayerView : targetPlayers) { + result.add(currPlayerView); + } + + return getTargets(si.getSubInstance(),result); + } + } + + private void addBigImageToStackModalPanel(JPanel mainPanel, SpellAbilityStackInstance si) { + StackItemView siv = si.getView(); + int rotation = getRotation(si.getCardView()); + + FImagePanel imagePanel = new FImagePanel(); + BufferedImage bufferedImage = FImageUtil.getImage(siv.getSourceCard().getCurrentState()); + imagePanel.setImage(bufferedImage, rotation, AutoSizeImageMode.SOURCE); + int imageWidth = 433; + int imageHeight = 600; + Dimension imagePanelDimension = new Dimension(imageWidth,imageHeight); + imagePanel.setMinimumSize(imagePanelDimension); + + mainPanel.add(imagePanel, "cell 0 0, spany 3"); + } + + private void addTextToStackModalPanel(JPanel mainPanel, SpellAbility sa, SpellAbilityStackInstance si) { + String who = sa.getActivatingPlayer().getName(); + String action = sa.isSpell() ? " cast " : sa.isTrigger() ? " triggered " : " activated "; + String what = sa.getStackDescription().startsWith("Morph ") ? "Morph" : sa.getHostCard().toString(); + + StringBuilder sb = new StringBuilder(); + sb.append(who).append(action).append(what); + + if (sa.getTargetRestrictions() != null) { + sb.append(" targeting "); + TargetChoices targets = si.getTargetChoices(); + sb.append(targets.getTargetedString()); + } + sb.append("."); + String message1 = sb.toString(); + String message2 = si.getStackDescription(); + String messageTotal = message1 + "\n\n" + message2; + + final FTextArea prompt1 = new FTextArea(messageTotal); + prompt1.setFont(FSkin.getFont(21)); + prompt1.setAutoSize(true); + prompt1.setMinimumSize(new Dimension(475,200)); + mainPanel.add(prompt1, "cell 1 0, aligny top"); + } + + private void addSmallImageToStackModalPanel(GameEntityView gameEntityView, JPanel mainPanel, int numTarget) { + if(gameEntityView instanceof CardView) { + CardView cardView = (CardView) gameEntityView; + int currRotation = getRotation(cardView); + FImagePanel targetPanel = new FImagePanel(); + BufferedImage bufferedImage = FImageUtil.getImage(cardView.getCurrentState()); + targetPanel.setImage(bufferedImage, currRotation, AutoSizeImageMode.SOURCE); + int imageWidth = 217; + int imageHeight = 300; + Dimension targetPanelDimension = new Dimension(imageWidth,imageHeight); + targetPanel.setMinimumSize(targetPanelDimension); + mainPanel.add(targetPanel, "cell 1 1, split " + numTarget+ ", aligny bottom"); + } else if(gameEntityView instanceof PlayerView) { + PlayerView playerView = (PlayerView) gameEntityView; + SkinImage playerAvatar = getPlayerAvatar(playerView, 0); + final FLabel lblIcon = new FLabel.Builder().icon(playerAvatar).build(); + Dimension dimension = playerAvatar.getSizeForPaint(JOptionPane.getRootFrame().getGraphics()); + mainPanel.add(lblIcon, "cell 1 1, split " + numTarget+ ", w " + dimension.getWidth() + ", h " + dimension.getHeight() + ", aligny bottom"); + } + } + private int getRotation(CardView cardView) { final int rotation; if (cardView.isSplitCard()) { @@ -1347,9 +1388,9 @@ public final class CMatchUI if (cardName.isEmpty()) { cardName = cardView.getAlternateState().getName(); } PaperCard pc = StaticData.instance().getCommonCards().getCard(cardName); - boolean isAftermath = pc != null && Card.getCardForUi(pc).hasKeyword(Keyword.AFTERMATH); + boolean hasKeywordAftermath = pc != null && Card.getCardForUi(pc).hasKeyword(Keyword.AFTERMATH); - rotation = cardView.isFaceDown() ? 0 : isAftermath ? 270 : 90; // rotate Aftermath splits the other way to correctly show the right split (graveyard) half + rotation = cardView.isFaceDown() ? 0 : hasKeywordAftermath ? (CardStateName.LeftSplit.equals(cardView.getState(false).getState()) ? 0 : 270) : 90; // rotate Aftermath splits the other way to correctly show the right split (graveyard) half } else { CardStateView cardStateView = cardView.getState(false); rotation = cardStateView.isPlane() || cardStateView.isPhenomenon() ? 90 : 0; diff --git a/forge-gui/src/main/java/forge/quest/QuestEventDifficulty.java b/forge-gui/src/main/java/forge/quest/QuestEventDifficulty.java index 46a0f234123..cfdb7d2b65a 100644 --- a/forge-gui/src/main/java/forge/quest/QuestEventDifficulty.java +++ b/forge-gui/src/main/java/forge/quest/QuestEventDifficulty.java @@ -10,8 +10,7 @@ public enum QuestEventDifficulty { EASY ("easy", 1. ), MEDIUM("medium", 1.5), HARD ("hard", 2. ), - EXPERT("very hard", 3. ), - WILD("wild", 2. ); + EXPERT("very hard", 3. ); private final String inFile; private final double multiplier; diff --git a/forge-gui/src/main/java/forge/quest/QuestEventDuelManager.java b/forge-gui/src/main/java/forge/quest/QuestEventDuelManager.java index 8628676404f..138176ed248 100644 --- a/forge-gui/src/main/java/forge/quest/QuestEventDuelManager.java +++ b/forge-gui/src/main/java/forge/quest/QuestEventDuelManager.java @@ -66,7 +66,6 @@ public class QuestEventDuelManager implements QuestEventDuelManagerInterface { private static List mediumOrder = Arrays.asList(QuestEventDifficulty.MEDIUM, QuestEventDifficulty.HARD, QuestEventDifficulty.EASY, QuestEventDifficulty.EXPERT); private static List hardOrder = Arrays.asList(QuestEventDifficulty.HARD, QuestEventDifficulty.MEDIUM, QuestEventDifficulty.EASY, QuestEventDifficulty.EXPERT); private static List expertOrder = Arrays.asList(QuestEventDifficulty.EXPERT, QuestEventDifficulty.HARD, QuestEventDifficulty.MEDIUM, QuestEventDifficulty.EASY); - private static List wildOrder = Arrays.asList(QuestEventDifficulty.WILD); private List getOrderForDifficulty(QuestEventDifficulty d) { final List difficultyOrder; @@ -84,9 +83,6 @@ public class QuestEventDuelManager implements QuestEventDuelManagerInterface { case EXPERT: difficultyOrder = expertOrder; break; - case WILD: - difficultyOrder = wildOrder; - break; default: throw new RuntimeException("unhandled difficulty: " + d); } @@ -207,7 +203,6 @@ public class QuestEventDuelManager implements QuestEventDuelManagerInterface { } } - addDuel(duelOpponents, QuestEventDifficulty.WILD, 1); addRandomDuel(duelOpponents, randomDuelDifficulty); return duelOpponents; @@ -227,7 +222,6 @@ public class QuestEventDuelManager implements QuestEventDuelManagerInterface { sortedDuels.put(QuestEventDifficulty.MEDIUM, new ArrayList<>()); sortedDuels.put(QuestEventDifficulty.HARD, new ArrayList<>()); sortedDuels.put(QuestEventDifficulty.EXPERT, new ArrayList<>()); - sortedDuels.put(QuestEventDifficulty.WILD, new ArrayList<>()); for (final QuestEventDuel qd : allDuels) { sortedDuels.add(qd.getDifficulty(), qd); diff --git a/forge-gui/src/main/java/forge/quest/io/QuestDuelReader.java b/forge-gui/src/main/java/forge/quest/io/QuestDuelReader.java index ce4d4e554a6..616f4a0e0a3 100644 --- a/forge-gui/src/main/java/forge/quest/io/QuestDuelReader.java +++ b/forge-gui/src/main/java/forge/quest/io/QuestDuelReader.java @@ -3,73 +3,23 @@ package forge.quest.io; import forge.ImageKeys; import forge.deck.io.DeckSerializer; import forge.deck.io.DeckStorage; -import forge.properties.ForgeConstants; import forge.quest.QuestEvent; import forge.quest.QuestEventDifficulty; import forge.quest.QuestEventDuel; import forge.util.FileSection; import forge.util.FileUtil; -import forge.util.TextUtil; import forge.util.storage.StorageReaderFolder; import java.io.File; import java.io.FilenameFilter; -import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.NoSuchElementException; -import java.util.TreeMap; - -import org.apache.commons.lang3.StringUtils; public class QuestDuelReader extends StorageReaderFolder { - - private static final String WILD_DEFAULT_ICON_NAME = "Wild.jpg"; - private static final String WILD_DIR_NAME = "wild"; - public QuestDuelReader(File deckDir0) { super(deckDir0, QuestEvent.FN_GET_NAME); // TODO Auto-generated constructor stub } - - @Override - public Map readAll() { - - List dirList = new ArrayList(); - dirList.add(directory); - - File directoryWild = new File(directory.getAbsolutePath() + ForgeConstants.PATH_SEPARATOR + WILD_DIR_NAME + ForgeConstants.PATH_SEPARATOR); - if(directoryWild.exists()) { - dirList.add(directoryWild); - } - - final Map result = new TreeMap<>(); - - for(File currDir : dirList) { - final File[] files = currDir.listFiles(this.getFileFilter()); - for (final File file : files) { - try { - final QuestEventDuel newDeck = this.read(file); - if (null == newDeck) { - final String msg = "An object stored in " + file.getPath() + " failed to load.\nPlease submit this as a bug with the mentioned file/directory attached."; - throw new RuntimeException(msg); - } - - String newKey = keySelector.apply(newDeck); - if (result.containsKey(newKey)) { - System.err.println("StorageReaderFolder: an object with key " + newKey + " is already present - skipping new entry"); - } else { - result.put(newKey, newDeck); - } - } catch (final NoSuchElementException ex) { - final String message = TextUtil.concatWithSpace( file.getName(),"failed to load because ----", ex.getMessage()); - objectsThatFailedToLoad.add(message); - } - } - } - - return result; - } @Override protected QuestEventDuel read(File file) { @@ -78,23 +28,14 @@ public class QuestDuelReader extends StorageReaderFolder { // Common properties FileSection sectionMeta = FileSection.parse(contents.get("metadata"), "="); + qc.setTitle(sectionMeta.get("Title")); qc.setName(sectionMeta.get("Name")); // Challenges have unique titles - - boolean difficultySpecified = !StringUtils.isEmpty(sectionMeta.get("Difficulty")); - if(difficultySpecified) { - qc.setTitle(sectionMeta.get("Title")); - qc.setDifficulty(QuestEventDifficulty.fromString(sectionMeta.get("Difficulty"))); - qc.setDescription(sectionMeta.get("Description", "").replace("\\n", "\n")); - qc.setCardReward(sectionMeta.get("Card Reward")); - qc.setIconImageKey(ImageKeys.ICON_PREFIX + sectionMeta.get("Icon")); - if (sectionMeta.contains("Profile")) { - qc.setProfile(sectionMeta.get("Profile")); - } - } else { - qc.setDifficulty(QuestEventDifficulty.WILD); - qc.setTitle(sectionMeta.get("Title") != null ? sectionMeta.get("Title") : qc.getName()); - qc.setDescription(sectionMeta.get("Description") != null ? sectionMeta.get("Description") : "Wild opponent"); - qc.setIconImageKey(ImageKeys.ICON_PREFIX + (sectionMeta.get("Icon") != null ? sectionMeta.get("Icon") : WILD_DEFAULT_ICON_NAME)); + qc.setDifficulty(QuestEventDifficulty.fromString(sectionMeta.get("Difficulty"))); + qc.setDescription(sectionMeta.get("Description", "").replace("\\n", "\n")); + qc.setCardReward(sectionMeta.get("Card Reward")); + qc.setIconImageKey(ImageKeys.ICON_PREFIX + sectionMeta.get("Icon")); + if (sectionMeta.contains("Profile")) { + qc.setProfile(sectionMeta.get("Profile")); } // Deck